| /* |
| * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com> |
| * Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther |
| * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de> |
| * Copyright (C) 2008, 2009 Collabora Ltd. All rights reserved. |
| * Copyright (C) 2009, 2010 Gustavo Noronha Silva <gns@gnome.org> |
| * Copyright (C) Research In Motion Limited 2009. All rights reserved. |
| * Copyright (C) 2010 Igalia S.L. |
| * Copyright (C) 2011 Apple Inc. All rights reserved. |
| * |
| * This library is free software; you can redistribute it and/or |
| * modify it under the terms of the GNU Lesser General Public |
| * License as published by the Free Software Foundation; either |
| * version 2 of the License, or (at your option) any later version. |
| * |
| * This library is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| * Lesser General Public License for more details. |
| * |
| * You should have received a copy of the GNU Lesser General Public |
| * License along with this library; if not, write to the Free Software |
| * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include "config.h" |
| #include "FrameLoaderClientGtk.h" |
| |
| #include "AXObjectCache.h" |
| #include "AccessibilityObject.h" |
| #include "ArchiveResource.h" |
| #include "CachedFrame.h" |
| #include "Color.h" |
| #include "DOMObjectCache.h" |
| #include "DocumentLoader.h" |
| #include "DocumentLoaderGtk.h" |
| #include "FormState.h" |
| #include "FrameLoader.h" |
| #include "FrameNetworkingContextGtk.h" |
| #include "FrameTree.h" |
| #include "FrameView.h" |
| #include "GOwnPtr.h" |
| #include "GRefPtr.h" |
| #include "GtkPluginWidget.h" |
| #include "HTMLAppletElement.h" |
| #include "HTMLFormElement.h" |
| #include "HTMLFrameElement.h" |
| #include "HTMLFrameOwnerElement.h" |
| #include "HTMLNames.h" |
| #include "HTMLPlugInElement.h" |
| #include "JSDOMBinding.h" |
| #include "JSDOMWindow.h" |
| #include "Language.h" |
| #include "MIMETypeRegistry.h" |
| #include "MouseEvent.h" |
| #include "NotImplemented.h" |
| #include "Page.h" |
| #include "PluginDatabase.h" |
| #include "ProgressTracker.h" |
| #include "RenderPart.h" |
| #include "RenderView.h" |
| #include "ResourceHandle.h" |
| #include "ResourceRequest.h" |
| #include "ScriptController.h" |
| #include "Settings.h" |
| #include "webkiterror.h" |
| #include "webkitglobals.h" |
| #include "webkitglobalsprivate.h" |
| #include "webkiticondatabase.h" |
| #include "webkitnetworkrequest.h" |
| #include "webkitnetworkrequestprivate.h" |
| #include "webkitnetworkresponse.h" |
| #include "webkitnetworkresponseprivate.h" |
| #include "webkitviewportattributes.h" |
| #include "webkitviewportattributesprivate.h" |
| #include "webkitwebdatasourceprivate.h" |
| #include "webkitwebframe.h" |
| #include "webkitwebframeprivate.h" |
| #include "webkitwebnavigationaction.h" |
| #include "webkitwebnavigationactionprivate.h" |
| #include "webkitwebpolicydecision.h" |
| #include "webkitwebpolicydecisionprivate.h" |
| #include "webkitwebresource.h" |
| #include "webkitwebresourceprivate.h" |
| #include "webkitwebsettingsprivate.h" |
| #include "webkitwebview.h" |
| #include "webkitwebviewprivate.h" |
| #include <JavaScriptCore/APICast.h> |
| #include <gio/gio.h> |
| #include <glib.h> |
| #include <glib/gi18n-lib.h> |
| #include <stdio.h> |
| #include <wtf/text/CString.h> |
| #include <wtf/text/StringConcatenate.h> |
| |
| using namespace WebCore; |
| |
| namespace WebKit { |
| |
| FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame) |
| : m_frame(frame) |
| , m_policyDecision(0) |
| , m_loadingErrorPage(false) |
| , m_pluginView(0) |
| , m_hasSentResponseToPlugin(false) |
| , m_hasRepresentation(false) |
| { |
| ASSERT(m_frame); |
| } |
| |
| FrameLoaderClient::~FrameLoaderClient() |
| { |
| if (m_policyDecision) |
| g_object_unref(m_policyDecision); |
| } |
| |
| static void initializeDomainsList(HashSet<String>& googleDomains) |
| { |
| // Google search domains. |
| googleDomains.add("biz"); |
| googleDomains.add("com"); |
| googleDomains.add("net"); |
| googleDomains.add("org"); |
| googleDomains.add("ae"); |
| googleDomains.add("ag"); |
| googleDomains.add("am"); |
| googleDomains.add("at"); |
| googleDomains.add("az"); |
| googleDomains.add("be"); |
| googleDomains.add("bi"); |
| googleDomains.add("ca"); |
| googleDomains.add("cc"); |
| googleDomains.add("cd"); |
| googleDomains.add("cg"); |
| googleDomains.add("ch"); |
| googleDomains.add("cl"); |
| googleDomains.add("com.br"); |
| googleDomains.add("co.uk"); |
| googleDomains.add("co.kr"); |
| googleDomains.add("co.jp"); |
| googleDomains.add("de"); |
| googleDomains.add("dj"); |
| googleDomains.add("dk"); |
| googleDomains.add("es"); |
| googleDomains.add("fi"); |
| googleDomains.add("fm"); |
| googleDomains.add("fr"); |
| googleDomains.add("gg"); |
| googleDomains.add("gl"); |
| googleDomains.add("gm"); |
| googleDomains.add("gs"); |
| googleDomains.add("hn"); |
| googleDomains.add("hu"); |
| googleDomains.add("ie"); |
| googleDomains.add("it"); |
| googleDomains.add("je"); |
| googleDomains.add("kz"); |
| googleDomains.add("li"); |
| googleDomains.add("lt"); |
| googleDomains.add("lu"); |
| googleDomains.add("lv"); |
| googleDomains.add("ma"); |
| googleDomains.add("ms"); |
| googleDomains.add("mu"); |
| googleDomains.add("mw"); |
| googleDomains.add("nl"); |
| googleDomains.add("no"); |
| googleDomains.add("nu"); |
| googleDomains.add("pl"); |
| googleDomains.add("pn"); |
| googleDomains.add("pt"); |
| googleDomains.add("ru"); |
| googleDomains.add("rw"); |
| googleDomains.add("sh"); |
| googleDomains.add("sk"); |
| googleDomains.add("sm"); |
| googleDomains.add("st"); |
| googleDomains.add("td"); |
| googleDomains.add("tk"); |
| googleDomains.add("tp"); |
| googleDomains.add("tv"); |
| googleDomains.add("us"); |
| googleDomains.add("uz"); |
| googleDomains.add("ws"); |
| } |
| |
| static bool isGoogleDomain(String host) |
| { |
| DEFINE_STATIC_LOCAL(HashSet<String>, googleDomains, ()); |
| DEFINE_STATIC_LOCAL(Vector<String>, otherGoogleDomains, ()); |
| |
| if (googleDomains.isEmpty()) { |
| otherGoogleDomains.append("gmail.com"); |
| otherGoogleDomains.append("youtube.com"); |
| otherGoogleDomains.append("gstatic.com"); |
| otherGoogleDomains.append("ytimg.com"); |
| |
| initializeDomainsList(googleDomains); |
| } |
| |
| // First check if this is one of the various google.com international domains. |
| int position = host.find(".google."); |
| if (position > 0 && googleDomains.contains(host.substring(position + sizeof(".google.")))) |
| return true; |
| |
| // Then we check the possibility of it being one of the other, .com-only google domains. |
| for (unsigned int i = 0; i < otherGoogleDomains.size(); i++) { |
| if (host.endsWith(otherGoogleDomains.at(i))) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| String FrameLoaderClient::userAgent(const KURL& url) |
| { |
| WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame)); |
| |
| gboolean useQuirks; |
| g_object_get(settings, "enable-site-specific-quirks", &useQuirks, NULL); |
| |
| // For Google domains, drop the browser's custom User Agent string, and use the standard |
| // WebKit/Safari one, so they don't give us a broken experience. |
| if (useQuirks && isGoogleDomain(url.host())) |
| return webkitUserAgent(); |
| |
| return String::fromUTF8(webkit_web_settings_get_user_agent(settings)); |
| } |
| |
| static void notifyAccessibilityStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) |
| { |
| if (loadStatus != WEBKIT_LOAD_PROVISIONAL |
| && loadStatus != WEBKIT_LOAD_FAILED |
| && loadStatus != WEBKIT_LOAD_FINISHED) |
| return; |
| |
| WebKitWebFramePrivate* priv = frame->priv; |
| if (!priv->coreFrame || !priv->coreFrame->document()) |
| return; |
| |
| RenderView* contentRenderer = priv->coreFrame->contentRenderer(); |
| if (!contentRenderer) |
| return; |
| |
| AXObjectCache* axObjectCache = priv->coreFrame->document()->axObjectCache(); |
| if (!axObjectCache) |
| return; |
| |
| AccessibilityObject* coreAxObject = axObjectCache->getOrCreate(contentRenderer); |
| if (!coreAxObject) |
| return; |
| |
| AtkObject* axObject = coreAxObject->wrapper(); |
| if (!axObject || !ATK_IS_DOCUMENT(axObject)) |
| return; |
| |
| switch (loadStatus) { |
| case WEBKIT_LOAD_PROVISIONAL: |
| g_signal_emit_by_name(axObject, "state-change", "busy", true); |
| if (core(frame)->loader()->loadType() == FrameLoadTypeReload) |
| g_signal_emit_by_name(axObject, "reload"); |
| break; |
| case WEBKIT_LOAD_FAILED: |
| g_signal_emit_by_name(axObject, "load-stopped"); |
| g_signal_emit_by_name(axObject, "state-change", "busy", false); |
| break; |
| case WEBKIT_LOAD_FINISHED: |
| g_signal_emit_by_name(axObject, "load-complete"); |
| g_signal_emit_by_name(axObject, "state-change", "busy", false); |
| default: |
| break; |
| } |
| } |
| |
| static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus) |
| { |
| frame->priv->loadStatus = loadStatus; |
| g_object_notify(G_OBJECT(frame), "load-status"); |
| |
| WebKitWebView* webView = getViewFromFrame(frame); |
| if (frame == webkit_web_view_get_main_frame(webView)) { |
| webView->priv->loadStatus = loadStatus; |
| g_object_notify(G_OBJECT(webView), "load-status"); |
| |
| if (AXObjectCache::accessibilityEnabled()) |
| notifyAccessibilityStatus(frame, loadStatus); |
| } |
| } |
| |
| static void loadDone(WebKitWebFrame* frame, bool didSucceed) |
| { |
| // FIXME: load-done is deprecated. Please remove when signal's been removed. |
| g_signal_emit_by_name(frame, "load-done", didSucceed); |
| notifyStatus(frame, WEBKIT_LOAD_FINISHED); |
| } |
| |
| WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData) |
| { |
| RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData); |
| |
| GRefPtr<WebKitWebDataSource> webDataSource(adoptGRef(kitNew(loader.get()))); |
| loader->setDataSource(webDataSource.get()); |
| |
| return loader.release(); |
| } |
| |
| void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>) |
| { |
| // FIXME: This is surely too simple |
| ASSERT(policyFunction); |
| if (!policyFunction) |
| return; |
| (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); |
| } |
| |
| void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length) |
| { |
| if (!m_pluginView) { |
| ASSERT(loader->frame()); |
| loader->commitData(data, length); |
| |
| Frame* coreFrame = loader->frame(); |
| if (coreFrame && coreFrame->document()->isMediaDocument()) |
| loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response())); |
| } |
| |
| if (m_pluginView) { |
| if (!m_hasSentResponseToPlugin) { |
| m_pluginView->didReceiveResponse(loader->response()); |
| m_hasSentResponseToPlugin = true; |
| } |
| |
| // FIXME: We may want to investigate refactoring our plugin loading |
| // code to be similar to mac's. |
| // Also, see http://trac.webkit.org/changeset/24118. |
| if (!m_pluginView) |
| return; |
| |
| m_pluginView->didReceiveData(data, length); |
| } |
| } |
| |
| bool |
| FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long identifier) |
| { |
| notImplemented(); |
| return false; |
| } |
| |
| void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&) |
| { |
| notImplemented(); |
| } |
| |
| // We convert this to string because it's easier to use strings as |
| // keys in a GHashTable. |
| static char* toString(unsigned long identifier) |
| { |
| return g_strdup_printf("%ld", identifier); |
| } |
| |
| void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse) |
| { |
| GRefPtr<WebKitNetworkResponse> networkResponse(0); |
| |
| // We are adding one more resource to the load, or maybe we are |
| // just redirecting a load. |
| if (redirectResponse.isNull()) |
| static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier); |
| else |
| networkResponse = adoptGRef(kitNew(redirectResponse)); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| GOwnPtr<gchar> identifierString(toString(identifier)); |
| WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); |
| GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request))); |
| |
| if (!redirectResponse.isNull()) { |
| // This is a redirect, so we need to update the WebResource's knowledge |
| // of the URI. |
| g_free(webResource->priv->uri); |
| webResource->priv->uri = g_strdup(request.url().string().utf8().data()); |
| } |
| |
| g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get()); |
| |
| // Feed any changes back into the ResourceRequest object. |
| SoupMessage* message = webkit_network_request_get_message(networkRequest.get()); |
| if (!message) { |
| request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get())))); |
| return; |
| } |
| |
| request.updateFromSoupMessage(message); |
| } |
| |
| void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request) |
| { |
| GOwnPtr<gchar> identifierString(toString(identifier)); |
| |
| WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0)); |
| |
| if (loader == loader->frameLoader()->provisionalDocumentLoader() |
| && loader->frameLoader()->isLoadingMainFrame()) { |
| webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource); |
| return; |
| } |
| |
| webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource); |
| } |
| |
| void FrameLoaderClient::postProgressStartedNotification() |
| { |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| g_signal_emit_by_name(webView, "load-started", m_frame); |
| |
| g_object_notify(G_OBJECT(webView), "progress"); |
| } |
| |
| void FrameLoaderClient::postProgressEstimateChangedNotification() |
| { |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| Page* corePage = core(webView); |
| |
| g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100)); |
| |
| g_object_notify(G_OBJECT(webView), "progress"); |
| } |
| |
| void FrameLoaderClient::postProgressFinishedNotification() |
| { |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| WebKitWebViewPrivate* privateData = webView->priv; |
| |
| // We can get a stopLoad() from dispose when the object is being |
| // destroyed, don't emit the signal in that case. |
| if (!privateData->disposing) |
| g_signal_emit_by_name(webView, "load-finished", m_frame); |
| } |
| |
| void FrameLoaderClient::frameLoaderDestroyed() |
| { |
| webkit_web_frame_core_frame_gone(m_frame); |
| g_object_unref(m_frame); |
| m_frame = 0; |
| delete this; |
| } |
| |
| void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long, const ResourceResponse& response) |
| { |
| // Update our knowledge of request soup flags - some are only set |
| // after the request is done. |
| loader->request().setSoupMessageFlags(response.soupMessageFlags()); |
| |
| m_response = response; |
| } |
| |
| void FrameLoaderClient::dispatchDecidePolicyForResponse(FramePolicyFunction policyFunction, const ResourceResponse& response, const ResourceRequest& resourceRequest) |
| { |
| ASSERT(policyFunction); |
| if (!policyFunction) |
| return; |
| |
| if (resourceRequest.isNull()) { |
| (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); |
| return; |
| } |
| |
| WebKitWebView* page = getViewFromFrame(m_frame); |
| GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest))); |
| |
| WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); |
| if (m_policyDecision) |
| g_object_unref(m_policyDecision); |
| m_policyDecision = policyDecision; |
| |
| String mimeType = response.mimeType(); |
| |
| gboolean isHandled = false; |
| g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled); |
| |
| if (isHandled) |
| return; |
| |
| GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(webkit_web_frame_get_network_response(m_frame))); |
| if (networkResponse) { |
| ResourceResponse response = core(networkResponse.get()); |
| if (response.isAttachment()) { |
| webkit_web_policy_decision_download(policyDecision); |
| return; |
| } |
| } |
| |
| if (canShowMIMEType(mimeType)) |
| webkit_web_policy_decision_use(policyDecision); |
| else |
| webkit_web_policy_decision_ignore(policyDecision); |
| } |
| |
| static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame) |
| { |
| gint button = -1; |
| |
| const Event* event = action.event(); |
| if (event && event->isMouseEvent()) { |
| const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event); |
| // DOM button values are 0, 1 and 2 for left, middle and right buttons. |
| // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent. |
| button = mouseEvent->button() + 1; |
| } |
| |
| gint modifierFlags = 0; |
| UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event)); |
| if (keyStateEvent) { |
| if (keyStateEvent->shiftKey()) |
| modifierFlags |= GDK_SHIFT_MASK; |
| if (keyStateEvent->ctrlKey()) |
| modifierFlags |= GDK_CONTROL_MASK; |
| if (keyStateEvent->altKey()) |
| modifierFlags |= GDK_MOD1_MASK; |
| if (keyStateEvent->metaKey()) |
| modifierFlags |= GDK_MOD2_MASK; |
| } |
| |
| return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION, |
| "reason", kit(action.type()), |
| "original-uri", action.url().string().utf8().data(), |
| "button", button, |
| "modifier-state", modifierFlags, |
| "target-frame", targetFrame, |
| NULL)); |
| } |
| |
| void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName) |
| { |
| ASSERT(policyFunction); |
| if (!policyFunction) |
| return; |
| |
| if (resourceRequest.isNull()) { |
| (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); |
| return; |
| } |
| |
| WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); |
| |
| if (m_policyDecision) |
| g_object_unref(m_policyDecision); |
| m_policyDecision = policyDecision; |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| GRefPtr<WebKitNetworkRequest> request(adoptGRef(webkit_network_request_new(resourceRequest.url().string().utf8().data()))); |
| GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, frameName.utf8().data()))); |
| gboolean isHandled = false; |
| |
| g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled); |
| |
| // FIXME: I think Qt version marshals this to another thread so when we |
| // have multi-threaded download, we might need to do the same |
| if (!isHandled) |
| (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse); |
| } |
| |
| void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>) |
| { |
| ASSERT(policyFunction); |
| if (!policyFunction) |
| return; |
| |
| if (resourceRequest.isNull()) { |
| (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); |
| return; |
| } |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest))); |
| WebKitNavigationResponse response; |
| /* |
| * We still support the deprecated navigation-requested signal, if the |
| * application doesn't ignore the navigation then the new signal is |
| * emitted. |
| * navigation-policy-decision-requested must be emitted after |
| * navigation-requested as the policy decision can be async. |
| */ |
| g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response); |
| |
| if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) { |
| (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore); |
| return; |
| } |
| |
| WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction); |
| if (m_policyDecision) |
| g_object_unref(m_policyDecision); |
| m_policyDecision = policyDecision; |
| |
| GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, 0))); |
| gboolean isHandled = false; |
| g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled); |
| |
| // FIXME Implement default behavior when we can query the backend what protocols it supports |
| if (!isHandled) |
| webkit_web_policy_decision_use(m_policyDecision); |
| } |
| |
| PassRefPtr<Widget> FrameLoaderClient::createPlugin(const IntSize& pluginSize, HTMLPlugInElement* element, const KURL& url, const Vector<String>& paramNames, const Vector<String>& paramValues, const String& mimeType, bool loadManually) |
| { |
| /* Check if we want to embed a GtkWidget, fallback to plugins later */ |
| CString urlString = url.string().utf8(); |
| CString mimeTypeString = mimeType.utf8(); |
| |
| ASSERT(paramNames.size() == paramValues.size()); |
| GRefPtr<GHashTable> hash = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free)); |
| for (unsigned i = 0; i < paramNames.size(); ++i) { |
| g_hash_table_insert(hash.get(), |
| g_strdup(paramNames[i].utf8().data()), |
| g_strdup(paramValues[i].utf8().data())); |
| } |
| |
| GtkWidget* gtkWidget = 0; |
| g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget", |
| mimeTypeString.data(), urlString.data(), hash.get(), >kWidget); |
| if (gtkWidget) |
| return adoptRef(new GtkPluginWidget(gtkWidget)); |
| |
| RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually); |
| |
| if (pluginView->status() == PluginStatusLoadedSuccessfully) |
| return pluginView; |
| |
| return 0; |
| } |
| |
| PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, |
| const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight) |
| { |
| ASSERT(m_frame); |
| Frame* parentFrame = core(m_frame); |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| WebCore::Page* page = core(webView); |
| ASSERT(page == parentFrame->page()); |
| |
| WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL)); |
| WebKitWebFramePrivate* framePrivate = kitFrame->priv; |
| framePrivate->webView = webView; |
| |
| RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame)); |
| framePrivate->coreFrame = childFrame.get(); |
| |
| childFrame->tree()->setName(name); |
| parentFrame->tree()->appendChild(childFrame); |
| childFrame->init(); |
| |
| // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. |
| if (!childFrame->page()) |
| return 0; |
| |
| g_signal_emit_by_name(webView, "frame-created", kitFrame); |
| |
| parentFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get()); |
| |
| // The frame's onload handler may have removed it from the document. |
| if (!childFrame->tree()->parent()) |
| return 0; |
| |
| return childFrame.release(); |
| } |
| |
| void FrameLoaderClient::didTransferChildFrameToNewDocument(WebCore::Page*) |
| { |
| ASSERT(m_frame); |
| |
| // Update the frame's webview to the new parent's webview. |
| Frame* coreFrame = core(m_frame); |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| |
| Frame* parentCoreFrame = coreFrame->tree()->parent(); |
| WebKitWebFrame* parentKitFrame = kit(parentCoreFrame); |
| WebKitWebView* parentWebView = getViewFromFrame(parentKitFrame); |
| if (webView != parentWebView) |
| m_frame->priv->webView = parentWebView; |
| |
| ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page()); |
| } |
| |
| void FrameLoaderClient::transferLoadingResourceFromPage(unsigned long identifier, WebCore::DocumentLoader* docLoader, const WebCore::ResourceRequest& request, WebCore::Page* oldPage) |
| { |
| ASSERT(oldPage != core(m_frame)->page()); |
| |
| GOwnPtr<gchar> identifierString(toString(identifier)); |
| ASSERT(!webkit_web_view_get_resource(getViewFromFrame(m_frame), identifierString.get())); |
| |
| assignIdentifierToInitialRequest(identifier, docLoader, request); |
| |
| webkit_web_view_remove_resource(kit(oldPage), identifierString.get()); |
| } |
| |
| void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget) |
| { |
| ASSERT(!m_pluginView); |
| m_pluginView = static_cast<PluginView*>(pluginWidget); |
| m_hasSentResponseToPlugin = false; |
| } |
| |
| PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues) |
| { |
| return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false); |
| } |
| |
| ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages) |
| { |
| return FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages); |
| } |
| |
| String FrameLoaderClient::overrideMediaType() const |
| { |
| notImplemented(); |
| return String(); |
| } |
| |
| void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world) |
| { |
| if (world != mainThreadNormalWorld()) |
| return; |
| |
| // Is this obsolete now? |
| g_signal_emit_by_name(m_frame, "cleared"); |
| |
| Frame* coreFrame = core(m_frame); |
| ASSERT(coreFrame); |
| |
| Settings* settings = coreFrame->settings(); |
| if (!settings || !settings->isJavaScriptEnabled()) |
| return; |
| |
| // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead |
| // when there are no handlers. |
| JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec()); |
| JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld())); |
| ASSERT(windowObject); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject); |
| |
| // TODO: Re-attach debug clients if present. |
| // The Win port has an example of how we might do this. |
| } |
| |
| void FrameLoaderClient::documentElementAvailable() |
| { |
| } |
| |
| void FrameLoaderClient::didPerformFirstNavigation() const |
| { |
| WebKitCacheModel cacheModel = webkit_get_cache_model(); |
| // If user agents do not determine the cache model, we use WEBKIT_CACHE_MODEL_WEB_BROWSER by default. |
| if (cacheModel == WEBKIT_CACHE_MODEL_DEFAULT) |
| webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER); |
| } |
| |
| void FrameLoaderClient::registerForIconNotification(bool shouldRegister) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::setMainFrameDocumentReady(bool ready) |
| { |
| if (!ready) |
| DOMObjectCache::clearByFrame(core(m_frame)); |
| } |
| |
| bool FrameLoaderClient::hasWebView() const |
| { |
| return getViewFromFrame(m_frame); |
| } |
| |
| void FrameLoaderClient::dispatchDidFinishLoad() |
| { |
| if (m_loadingErrorPage) { |
| m_loadingErrorPage = false; |
| return; |
| } |
| |
| loadDone(m_frame, true); |
| } |
| |
| void FrameLoaderClient::frameLoadCompleted() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::saveViewStateToItem(HistoryItem*) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::restoreViewState() |
| { |
| notImplemented(); |
| } |
| |
| bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const |
| { |
| // FIXME: This is a very simple implementation. More sophisticated |
| // implementation would delegate the decision to a PolicyDelegate. |
| // See mac implementation for example. |
| return item != 0; |
| } |
| |
| bool FrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const |
| { |
| return true; |
| } |
| |
| void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const |
| { |
| } |
| |
| void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const |
| { |
| } |
| |
| void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const |
| { |
| } |
| |
| void FrameLoaderClient::didDisplayInsecureContent() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*) |
| { |
| m_hasRepresentation = true; |
| } |
| |
| void FrameLoaderClient::forceLayout() |
| { |
| FrameView* view = core(m_frame)->view(); |
| if (view) |
| view->forceLayout(true); |
| } |
| |
| void FrameLoaderClient::forceLayoutForNonHTML() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::setCopiesOnScroll() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::detachedFromParent2() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::detachedFromParent3() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidHandleOnloadEvents() |
| { |
| g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame); |
| } |
| |
| void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidCancelClientRedirect() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidChangeLocationWithinPage() |
| { |
| WebKitWebFramePrivate* priv = m_frame->priv; |
| g_free(priv->uri); |
| priv->uri = g_strdup(core(m_frame)->document()->url().string().utf8().data()); |
| g_object_notify(G_OBJECT(m_frame), "uri"); |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| if (m_frame == webkit_web_view_get_main_frame(webView)) |
| g_object_notify(G_OBJECT(webView), "uri"); |
| } |
| |
| void FrameLoaderClient::dispatchDidPushStateWithinPage() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidReplaceStateWithinPage() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidPopStateWithinPage() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchWillClose() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidReceiveIcon() |
| { |
| if (m_loadingErrorPage) |
| return; |
| |
| const gchar* frameURI = webkit_web_frame_get_uri(m_frame); |
| WebKitIconDatabase* database = webkit_get_icon_database(); |
| g_signal_emit_by_name(database, "icon-loaded", m_frame, frameURI); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| |
| // Avoid reporting favicons for non-main frames. |
| if (m_frame != webkit_web_view_get_main_frame(webView)) |
| return; |
| |
| g_object_notify(G_OBJECT(webView), "icon-uri"); |
| g_signal_emit_by_name(webView, "icon-loaded", webkit_web_view_get_icon_uri(webView)); |
| } |
| |
| void FrameLoaderClient::dispatchDidStartProvisionalLoad() |
| { |
| if (m_loadingErrorPage) |
| return; |
| |
| notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL); |
| } |
| |
| void FrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title) |
| { |
| if (m_loadingErrorPage) |
| return; |
| |
| WebKitWebFramePrivate* priv = m_frame->priv; |
| g_free(priv->title); |
| // FIXME: use direction of title. |
| priv->title = g_strdup(title.string().utf8().data()); |
| |
| g_signal_emit_by_name(m_frame, "title-changed", priv->title); |
| g_object_notify(G_OBJECT(m_frame), "title"); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| if (m_frame == webkit_web_view_get_main_frame(webView)) { |
| g_signal_emit_by_name(webView, "title-changed", m_frame, title.string().utf8().data()); |
| g_object_notify(G_OBJECT(webView), "title"); |
| } |
| } |
| |
| void FrameLoaderClient::dispatchDidChangeIcons() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidCommitLoad() |
| { |
| if (m_loadingErrorPage) |
| return; |
| |
| /* Update the URI once first data has been received. |
| * This means the URI is valid and successfully identify the page that's going to be loaded. |
| */ |
| g_object_freeze_notify(G_OBJECT(m_frame)); |
| |
| WebKitWebFramePrivate* priv = m_frame->priv; |
| g_free(priv->uri); |
| priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().string().utf8().data()); |
| g_free(priv->title); |
| priv->title = NULL; |
| g_object_notify(G_OBJECT(m_frame), "uri"); |
| g_object_notify(G_OBJECT(m_frame), "title"); |
| |
| g_signal_emit_by_name(m_frame, "load-committed"); |
| notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| if (m_frame == webkit_web_view_get_main_frame(webView)) { |
| g_object_freeze_notify(G_OBJECT(webView)); |
| g_object_notify(G_OBJECT(webView), "uri"); |
| g_object_notify(G_OBJECT(webView), "title"); |
| g_object_thaw_notify(G_OBJECT(webView)); |
| g_signal_emit_by_name(webView, "load-committed", m_frame); |
| } |
| |
| g_object_thaw_notify(G_OBJECT(m_frame)); |
| } |
| |
| void FrameLoaderClient::dispatchDidFinishDocumentLoad() |
| { |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| g_signal_emit_by_name(webView, "document-load-finished", m_frame); |
| } |
| |
| void FrameLoaderClient::dispatchDidFirstLayout() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout() |
| { |
| if (m_loadingErrorPage) |
| return; |
| |
| notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT); |
| } |
| |
| void FrameLoaderClient::dispatchShow() |
| { |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| webkit_web_view_notify_ready(webView); |
| } |
| |
| void FrameLoaderClient::cancelPolicyCheck() |
| { |
| //FIXME Add support for more than one policy decision at once |
| if (m_policyDecision) |
| webkit_web_policy_decision_cancel(m_policyDecision); |
| } |
| |
| void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*) |
| { |
| m_hasRepresentation = true; |
| } |
| |
| void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l) |
| { |
| setTitle(l->title(), l->url()); |
| } |
| |
| bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const |
| { |
| notImplemented(); |
| return true; |
| } |
| |
| bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const |
| { |
| notImplemented(); |
| return false; |
| } |
| |
| bool FrameLoaderClient::canShowMIMEType(const String& type) const |
| { |
| return (MIMETypeRegistry::isSupportedImageMIMEType(type) |
| || MIMETypeRegistry::isSupportedNonImageMIMEType(type) |
| || MIMETypeRegistry::isSupportedMediaMIMEType(type) |
| || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type)); |
| } |
| |
| bool FrameLoaderClient::representationExistsForURLScheme(const String&) const |
| { |
| notImplemented(); |
| return false; |
| } |
| |
| String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const |
| { |
| notImplemented(); |
| return String(); |
| } |
| |
| void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader) |
| { |
| if (!m_pluginView) { |
| // This is necessary to create an empty document, |
| // but it has to be skipped in the provisional phase. |
| if (m_hasRepresentation) |
| documentLoader->writer()->setEncoding("", false); |
| } else { |
| m_pluginView->didFinishLoading(); |
| m_pluginView = 0; |
| m_hasSentResponseToPlugin = false; |
| } |
| } |
| |
| |
| void FrameLoaderClient::provisionalLoadStarted() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::didFinishLoad() { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::prepareForDataSourceReplacement() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::setTitle(const StringWithDirection& title, const KURL& url) |
| { |
| WebKitWebFramePrivate* frameData = m_frame->priv; |
| g_free(frameData->title); |
| // FIXME: use direction of title. |
| frameData->title = g_strdup(title.string().utf8().data()); |
| } |
| |
| void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int dataLength) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier) |
| { |
| static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| GOwnPtr<gchar> identifierString(toString(identifier)); |
| WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get()); |
| |
| // A NULL WebResource means the load has been interrupted, and |
| // replaced by another one while this resource was being loaded. |
| if (!webResource) |
| return; |
| |
| const char* uri = webkit_web_resource_get_uri(webResource); |
| RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri))); |
| |
| // If coreResource is NULL here, the resource failed to load, |
| // unless it's the main resource. |
| if (!coreResource && webResource != webkit_web_view_get_main_resource(webView)) |
| return; |
| |
| if (!coreResource) |
| coreResource = loader->mainResource(); |
| |
| webkit_web_resource_init_with_core_resource(webResource, coreResource.get()); |
| |
| // FIXME: This function should notify the application that the resource |
| // finished loading, maybe using a load-status property in the |
| // WebKitWebResource object, similar to what we do for WebKitWebFrame' |
| // signal. |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error) |
| { |
| static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier); |
| |
| // FIXME: This function should notify the application that the resource failed |
| // loading, maybe a 'load-error' signal in the WebKitWebResource object. |
| notImplemented(); |
| } |
| |
| bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) |
| { |
| notImplemented(); |
| return false; |
| } |
| |
| void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error) |
| { |
| dispatchDidFailLoad(error); |
| } |
| |
| void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error) |
| { |
| if (m_loadingErrorPage) |
| return; |
| |
| notifyStatus(m_frame, WEBKIT_LOAD_FAILED); |
| |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()), |
| error.errorCode(), |
| error.localizedDescription().utf8().data()); |
| gboolean isHandled = false; |
| g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled); |
| |
| if (isHandled) { |
| g_error_free(webError); |
| return; |
| } |
| |
| if (!shouldFallBack(error)) { |
| g_error_free(webError); |
| return; |
| } |
| |
| m_loadingErrorPage = true; |
| |
| String content; |
| gchar* fileContent = 0; |
| gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL); |
| GFile* errorFile = g_file_new_for_uri(errorURI); |
| g_free(errorURI); |
| |
| if (!errorFile) |
| content = makeString("<html><body>", webError->message, "</body></html>"); |
| else { |
| gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0); |
| if (!loaded) |
| content = makeString("<html><body>", webError->message, "</body></html>"); |
| else |
| content = String::format(fileContent, error.failingURL().utf8().data(), webError->message); |
| } |
| |
| webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data()); |
| |
| g_free(fileContent); |
| |
| if (errorFile) |
| g_object_unref(errorFile); |
| |
| g_error_free(webError); |
| } |
| |
| void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response) |
| { |
| GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request))); |
| WebKitWebView* view = getViewFromFrame(m_frame); |
| |
| webkit_web_view_request_download(view, networkRequest.get(), response, handle); |
| } |
| |
| ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED, |
| request.url().string(), _("Load request cancelled")); |
| } |
| |
| ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT, |
| request.url().string(), _("Not allowed to use restricted network port")); |
| } |
| |
| ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL, |
| request.url().string(), _("URL cannot be shown")); |
| } |
| |
| ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE, |
| request.url().string(), _("Frame load was interrupted")); |
| } |
| |
| ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE, |
| response.url().string(), _("Content with the specified MIME type cannot be shown")); |
| } |
| |
| ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST, |
| response.url().string(), _("File does not exist")); |
| } |
| |
| ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response) |
| { |
| return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD, |
| response.url().string(), _("Plugin will handle load")); |
| } |
| |
| bool FrameLoaderClient::shouldFallBack(const ResourceError& error) |
| { |
| return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD); |
| } |
| |
| bool FrameLoaderClient::canCachePage() const |
| { |
| return true; |
| } |
| |
| Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&) |
| { |
| WebKitWebView* webView = getViewFromFrame(m_frame); |
| WebKitWebView* newWebView = 0; |
| |
| g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView); |
| |
| if (!newWebView) |
| return 0; |
| |
| WebKitWebViewPrivate* privateData = newWebView->priv; |
| return core(privateData->mainFrame); |
| } |
| |
| void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&) |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error) |
| { |
| if (m_pluginView) { |
| m_pluginView->didFail(error); |
| m_pluginView = 0; |
| m_hasSentResponseToPlugin = false; |
| } |
| } |
| |
| void FrameLoaderClient::startDownload(const ResourceRequest& request) |
| { |
| GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request))); |
| WebKitWebView* view = getViewFromFrame(m_frame); |
| |
| webkit_web_view_request_download(view, networkRequest.get()); |
| } |
| |
| void FrameLoaderClient::updateGlobalHistory() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::updateGlobalHistoryRedirectLinks() |
| { |
| notImplemented(); |
| } |
| |
| void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame) |
| { |
| // We need to do this here in order to disconnect the scrollbars |
| // that are being used by the frame that is being cached from the |
| // adjustments, otherwise they will react to changes in the |
| // adjustments, and bad things will happen. |
| if (cachedFrame->view()) |
| cachedFrame->view()->setGtkAdjustments(0, 0); |
| } |
| |
| static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues) |
| { |
| WebKitWebView* containingWindow = getViewFromFrame(frame); |
| webkit_web_view_clear_resources(containingWindow); |
| |
| WebKitWebViewPrivate* priv = containingWindow->priv; |
| view->setGtkAdjustments(priv->horizontalAdjustment.get(), priv->verticalAdjustment.get(), resetValues); |
| |
| // Invalidate the viewport attributes - they will only be valid |
| // again if the page we're beginning to load now has an |
| // appropriate viewport meta tag. |
| containingWindow->priv->viewportAttributes->priv->isValid = FALSE; |
| g_object_notify(G_OBJECT(containingWindow->priv->viewportAttributes.get()), "valid"); |
| |
| if (priv->currentMenu) { |
| gtk_widget_destroy(GTK_WIDGET(priv->currentMenu)); |
| priv->currentMenu = 0; |
| } |
| |
| // Do not allow click counting between main frame loads. |
| priv->previousClickTime = 0; |
| } |
| |
| void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame) |
| { |
| ASSERT(cachedFrame->view()); |
| |
| Frame* frame = core(m_frame); |
| if (frame != frame->page()->mainFrame()) |
| return; |
| |
| postCommitFrameViewSetup(m_frame, cachedFrame->view(), false); |
| } |
| |
| void FrameLoaderClient::transitionToCommittedForNewPage() |
| { |
| WebKitWebView* containingWindow = getViewFromFrame(m_frame); |
| GtkAllocation allocation; |
| #if GTK_CHECK_VERSION(2, 18, 0) |
| gtk_widget_get_allocation(GTK_WIDGET(containingWindow), &allocation); |
| #else |
| allocation = GTK_WIDGET(containingWindow)->allocation; |
| #endif |
| IntSize size = IntSize(allocation.width, allocation.height); |
| bool transparent = webkit_web_view_get_transparent(containingWindow); |
| Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white; |
| Frame* frame = core(m_frame); |
| ASSERT(frame); |
| |
| frame->createView(size, backgroundColor, transparent, IntSize(), false); |
| |
| // We need to do further manipulation on the FrameView if it was the mainFrame |
| if (frame != frame->page()->mainFrame()) |
| return; |
| |
| postCommitFrameViewSetup(m_frame, frame->view(), true); |
| } |
| |
| void FrameLoaderClient::didSaveToPageCache() |
| { |
| } |
| |
| void FrameLoaderClient::didRestoreFromPageCache() |
| { |
| } |
| |
| void FrameLoaderClient::dispatchDidBecomeFrameset(bool) |
| { |
| } |
| |
| PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext() |
| { |
| return FrameNetworkingContextGtk::create(core(m_frame)); |
| } |
| |
| } |