2 * Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
3 * Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther
4 * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
5 * Copyright (C) 2008, 2009 Collabora Ltd. All rights reserved.
6 * Copyright (C) 2009, 2010 Gustavo Noronha Silva <gns@gnome.org>
7 * Copyright (C) Research In Motion Limited 2009. All rights reserved.
8 * Copyright (C) 2010 Igalia S.L.
9 * Copyright (C) 2011 Apple Inc. All rights reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "FrameLoaderClientGtk.h"
29 #include "AXObjectCache.h"
30 #include "AccessibilityObject.h"
31 #include "ArchiveResource.h"
32 #include "CachedFrame.h"
34 #include "DOMObjectCache.h"
35 #include "DocumentLoader.h"
36 #include "DocumentLoaderGtk.h"
37 #include "FormState.h"
38 #include "FrameLoader.h"
39 #include "FrameNetworkingContextGtk.h"
40 #include "FrameTree.h"
41 #include "FrameView.h"
44 #include "GtkPluginWidget.h"
45 #include "HTMLAppletElement.h"
46 #include "HTMLFormElement.h"
47 #include "HTMLFrameElement.h"
48 #include "HTMLFrameOwnerElement.h"
49 #include "HTMLNames.h"
50 #include "HTMLPlugInElement.h"
51 #include "JSDOMBinding.h"
52 #include "JSDOMWindow.h"
54 #include "MIMETypeRegistry.h"
55 #include "MouseEvent.h"
56 #include "NotImplemented.h"
58 #include "PluginDatabase.h"
59 #include "ProgressTracker.h"
60 #include "RenderPart.h"
61 #include "RenderView.h"
62 #include "ResourceHandle.h"
63 #include "ResourceLoader.h"
64 #include "ResourceRequest.h"
65 #include "ScriptController.h"
67 #include "webkiterror.h"
68 #include "webkitglobals.h"
69 #include "webkitglobalsprivate.h"
70 #include "webkiticondatabase.h"
71 #include "webkitnetworkrequest.h"
72 #include "webkitnetworkrequestprivate.h"
73 #include "webkitnetworkresponse.h"
74 #include "webkitnetworkresponseprivate.h"
75 #include "webkitviewportattributes.h"
76 #include "webkitviewportattributesprivate.h"
77 #include "webkitwebdatasourceprivate.h"
78 #include "webkitwebframe.h"
79 #include "webkitwebframeprivate.h"
80 #include "webkitwebnavigationaction.h"
81 #include "webkitwebnavigationactionprivate.h"
82 #include "webkitwebpolicydecision.h"
83 #include "webkitwebpolicydecisionprivate.h"
84 #include "webkitwebresource.h"
85 #include "webkitwebresourceprivate.h"
86 #include "webkitwebsettingsprivate.h"
87 #include "webkitwebview.h"
88 #include "webkitwebviewprivate.h"
89 #include <JavaScriptCore/APICast.h>
92 #include <glib/gi18n-lib.h>
94 #include <wtf/text/CString.h>
95 #include <wtf/text/StringConcatenate.h>
97 using namespace WebCore;
101 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
103 , m_policyDecision(0)
104 , m_loadingErrorPage(false)
106 , m_hasSentResponseToPlugin(false)
107 , m_hasRepresentation(false)
112 FrameLoaderClient::~FrameLoaderClient()
114 if (m_policyDecision)
115 g_object_unref(m_policyDecision);
119 String FrameLoaderClient::userAgent(const KURL& url)
121 WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame));
122 GOwnPtr<gchar> userAgentString(webkitWebSettingsUserAgentForURI(settings, url.string().utf8().data()));
123 return String::fromUTF8(userAgentString.get());
126 static void notifyAccessibilityStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
128 if (loadStatus != WEBKIT_LOAD_PROVISIONAL
129 && loadStatus != WEBKIT_LOAD_FAILED
130 && loadStatus != WEBKIT_LOAD_FINISHED)
133 WebKitWebFramePrivate* priv = frame->priv;
134 if (!priv->coreFrame || !priv->coreFrame->document())
137 RenderView* contentRenderer = priv->coreFrame->contentRenderer();
138 if (!contentRenderer)
141 AXObjectCache* axObjectCache = priv->coreFrame->document()->axObjectCache();
145 AccessibilityObject* coreAxObject = axObjectCache->getOrCreate(contentRenderer);
149 AtkObject* axObject = coreAxObject->wrapper();
150 if (!axObject || !ATK_IS_DOCUMENT(axObject))
153 switch (loadStatus) {
154 case WEBKIT_LOAD_PROVISIONAL:
155 g_signal_emit_by_name(axObject, "state-change", "busy", true);
156 if (core(frame)->loader()->loadType() == FrameLoadTypeReload)
157 g_signal_emit_by_name(axObject, "reload");
159 case WEBKIT_LOAD_FAILED:
160 g_signal_emit_by_name(axObject, "load-stopped");
161 g_signal_emit_by_name(axObject, "state-change", "busy", false);
163 case WEBKIT_LOAD_FINISHED:
164 g_signal_emit_by_name(axObject, "load-complete");
165 g_signal_emit_by_name(axObject, "state-change", "busy", false);
171 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
173 frame->priv->loadStatus = loadStatus;
174 g_object_notify(G_OBJECT(frame), "load-status");
176 WebKitWebView* webView = getViewFromFrame(frame);
177 if (frame == webkit_web_view_get_main_frame(webView)) {
178 webView->priv->loadStatus = loadStatus;
179 g_object_notify(G_OBJECT(webView), "load-status");
181 if (AXObjectCache::accessibilityEnabled())
182 notifyAccessibilityStatus(frame, loadStatus);
186 static void loadDone(WebKitWebFrame* frame, bool didSucceed)
188 // FIXME: load-done is deprecated. Please remove when signal's been removed.
189 g_signal_emit_by_name(frame, "load-done", didSucceed);
190 notifyStatus(frame, WEBKIT_LOAD_FINISHED);
193 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
195 RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData);
197 GRefPtr<WebKitWebDataSource> webDataSource(adoptGRef(kitNew(loader.get())));
198 loader->setDataSource(webDataSource.get());
200 return loader.release();
203 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>)
205 // FIXME: This is surely too simple
206 ASSERT(policyFunction);
209 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
212 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
215 ASSERT(loader->frame());
216 loader->commitData(data, length);
218 Frame* coreFrame = loader->frame();
219 if (coreFrame && coreFrame->document()->isMediaDocument())
220 loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response()));
224 if (!m_hasSentResponseToPlugin) {
225 m_pluginView->didReceiveResponse(loader->response());
226 m_hasSentResponseToPlugin = true;
229 // FIXME: We may want to investigate refactoring our plugin loading
230 // code to be similar to mac's.
231 // Also, see http://trac.webkit.org/changeset/24118.
235 m_pluginView->didReceiveData(data, length);
240 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long identifier)
246 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
251 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
256 // We convert this to string because it's easier to use strings as
257 // keys in a GHashTable.
258 static char* toString(unsigned long identifier)
260 return g_strdup_printf("%ld", identifier);
263 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
265 GRefPtr<WebKitNetworkResponse> networkResponse(0);
267 // We are adding one more resource to the load, or maybe we are
268 // just redirecting a load.
269 if (redirectResponse.isNull())
270 static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier);
272 networkResponse = adoptGRef(kitNew(redirectResponse));
274 WebKitWebView* webView = getViewFromFrame(m_frame);
275 GOwnPtr<gchar> identifierString(toString(identifier));
276 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
277 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
279 if (!redirectResponse.isNull()) {
280 // This is a redirect, so we need to update the WebResource's knowledge
282 g_free(webResource->priv->uri);
283 webResource->priv->uri = g_strdup(request.url().string().utf8().data());
286 g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get());
288 // Feed any changes back into the ResourceRequest object.
289 SoupMessage* message = webkit_network_request_get_message(networkRequest.get());
291 request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get()))));
295 request.updateFromSoupMessage(message);
298 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request)
300 GOwnPtr<gchar> identifierString(toString(identifier));
302 WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0));
304 if (loader == loader->frameLoader()->provisionalDocumentLoader()
305 && loader->frameLoader()->isLoadingMainFrame()) {
306 webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
310 webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
313 void FrameLoaderClient::postProgressStartedNotification()
315 WebKitWebView* webView = getViewFromFrame(m_frame);
316 g_signal_emit_by_name(webView, "load-started", m_frame);
318 g_object_notify(G_OBJECT(webView), "progress");
321 void FrameLoaderClient::postProgressEstimateChangedNotification()
323 WebKitWebView* webView = getViewFromFrame(m_frame);
324 Page* corePage = core(webView);
326 g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100));
328 g_object_notify(G_OBJECT(webView), "progress");
331 void FrameLoaderClient::postProgressFinishedNotification()
333 WebKitWebView* webView = getViewFromFrame(m_frame);
334 WebKitWebViewPrivate* privateData = webView->priv;
336 // We can get a stopLoad() from dispose when the object is being
337 // destroyed, don't emit the signal in that case.
338 if (!privateData->disposing)
339 g_signal_emit_by_name(webView, "load-finished", m_frame);
342 void FrameLoaderClient::frameLoaderDestroyed()
344 webkit_web_frame_core_frame_gone(m_frame);
345 g_object_unref(m_frame);
350 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long, const ResourceResponse& response)
352 // Update our knowledge of request soup flags - some are only set
353 // after the request is done.
354 loader->request().setSoupMessageFlags(response.soupMessageFlags());
356 m_response = response;
359 void FrameLoaderClient::dispatchDecidePolicyForResponse(FramePolicyFunction policyFunction, const ResourceResponse& response, const ResourceRequest& resourceRequest)
361 ASSERT(policyFunction);
365 if (resourceRequest.isNull()) {
366 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
370 WebKitWebView* page = getViewFromFrame(m_frame);
371 GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
373 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
374 if (m_policyDecision)
375 g_object_unref(m_policyDecision);
376 m_policyDecision = policyDecision;
378 String mimeType = response.mimeType();
380 gboolean isHandled = false;
381 g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled);
386 GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(webkit_web_frame_get_network_response(m_frame)));
387 if (networkResponse) {
388 ResourceResponse response = core(networkResponse.get());
389 if (response.isAttachment()) {
390 webkit_web_policy_decision_download(policyDecision);
395 if (canShowMIMEType(mimeType))
396 webkit_web_policy_decision_use(policyDecision);
398 webkit_web_policy_decision_ignore(policyDecision);
401 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame)
405 const Event* event = action.event();
406 if (event && event->isMouseEvent()) {
407 const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event);
408 // DOM button values are 0, 1 and 2 for left, middle and right buttons.
409 // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent.
410 button = mouseEvent->button() + 1;
413 gint modifierFlags = 0;
414 UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event));
416 if (keyStateEvent->shiftKey())
417 modifierFlags |= GDK_SHIFT_MASK;
418 if (keyStateEvent->ctrlKey())
419 modifierFlags |= GDK_CONTROL_MASK;
420 if (keyStateEvent->altKey())
421 modifierFlags |= GDK_MOD1_MASK;
422 if (keyStateEvent->metaKey())
423 modifierFlags |= GDK_MOD2_MASK;
426 return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
427 "reason", kit(action.type()),
428 "original-uri", action.url().string().utf8().data(),
430 "modifier-state", modifierFlags,
431 "target-frame", targetFrame,
435 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName)
437 ASSERT(policyFunction);
441 if (resourceRequest.isNull()) {
442 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
446 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
448 if (m_policyDecision)
449 g_object_unref(m_policyDecision);
450 m_policyDecision = policyDecision;
452 WebKitWebView* webView = getViewFromFrame(m_frame);
453 GRefPtr<WebKitNetworkRequest> request(adoptGRef(webkit_network_request_new(resourceRequest.url().string().utf8().data())));
454 GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, frameName.utf8().data())));
455 gboolean isHandled = false;
457 g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
459 // FIXME: I think Qt version marshals this to another thread so when we
460 // have multi-threaded download, we might need to do the same
462 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
465 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>)
467 ASSERT(policyFunction);
471 if (resourceRequest.isNull()) {
472 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
476 WebKitWebView* webView = getViewFromFrame(m_frame);
477 GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
478 WebKitNavigationResponse response;
480 * We still support the deprecated navigation-requested signal, if the
481 * application doesn't ignore the navigation then the new signal is
483 * navigation-policy-decision-requested must be emitted after
484 * navigation-requested as the policy decision can be async.
486 g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response);
488 if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
489 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
493 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
494 if (m_policyDecision)
495 g_object_unref(m_policyDecision);
496 m_policyDecision = policyDecision;
498 GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, 0)));
499 gboolean isHandled = false;
500 g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
502 // FIXME Implement default behavior when we can query the backend what protocols it supports
504 webkit_web_policy_decision_use(m_policyDecision);
507 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)
509 /* Check if we want to embed a GtkWidget, fallback to plugins later */
510 CString urlString = url.string().utf8();
511 CString mimeTypeString = mimeType.utf8();
513 ASSERT(paramNames.size() == paramValues.size());
514 GRefPtr<GHashTable> hash = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free));
515 for (unsigned i = 0; i < paramNames.size(); ++i) {
516 g_hash_table_insert(hash.get(),
517 g_strdup(paramNames[i].utf8().data()),
518 g_strdup(paramValues[i].utf8().data()));
521 GtkWidget* gtkWidget = 0;
522 g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget",
523 mimeTypeString.data(), urlString.data(), hash.get(), >kWidget);
525 return adoptRef(new GtkPluginWidget(gtkWidget));
527 RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
529 if (pluginView->status() == PluginStatusLoadedSuccessfully)
535 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
536 const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
539 Frame* parentFrame = core(m_frame);
540 WebKitWebView* webView = getViewFromFrame(m_frame);
541 WebCore::Page* page = core(webView);
542 ASSERT(page == parentFrame->page());
544 WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
545 WebKitWebFramePrivate* framePrivate = kitFrame->priv;
546 framePrivate->webView = webView;
548 RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame));
549 framePrivate->coreFrame = childFrame.get();
551 childFrame->tree()->setName(name);
552 parentFrame->tree()->appendChild(childFrame);
555 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
556 if (!childFrame->page())
559 g_signal_emit_by_name(webView, "frame-created", kitFrame);
561 parentFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
563 // The frame's onload handler may have removed it from the document.
564 if (!childFrame->tree()->parent())
567 return childFrame.release();
570 void FrameLoaderClient::didTransferChildFrameToNewDocument(WebCore::Page*)
574 // Update the frame's webview to the new parent's webview.
575 Frame* coreFrame = core(m_frame);
576 WebKitWebView* webView = getViewFromFrame(m_frame);
578 Frame* parentCoreFrame = coreFrame->tree()->parent();
579 WebKitWebFrame* parentKitFrame = kit(parentCoreFrame);
580 WebKitWebView* parentWebView = getViewFromFrame(parentKitFrame);
581 if (webView != parentWebView)
582 m_frame->priv->webView = parentWebView;
584 ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page());
587 void FrameLoaderClient::transferLoadingResourceFromPage(WebCore::ResourceLoader* loader, const WebCore::ResourceRequest& request, WebCore::Page* oldPage)
589 ASSERT(oldPage != core(m_frame)->page());
591 GOwnPtr<gchar> identifierString(toString(loader->identifier()));
592 ASSERT(!webkit_web_view_get_resource(getViewFromFrame(m_frame), identifierString.get()));
594 assignIdentifierToInitialRequest(loader->identifier(), loader->documentLoader(), request);
596 webkit_web_view_remove_resource(kit(oldPage), identifierString.get());
599 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
601 ASSERT(!m_pluginView);
602 m_pluginView = static_cast<PluginView*>(pluginWidget);
603 m_hasSentResponseToPlugin = false;
606 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues)
608 return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false);
611 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages)
613 return FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages);
616 String FrameLoaderClient::overrideMediaType() const
622 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
624 if (world != mainThreadNormalWorld())
627 // Is this obsolete now?
628 g_signal_emit_by_name(m_frame, "cleared");
630 Frame* coreFrame = core(m_frame);
633 Settings* settings = coreFrame->settings();
634 if (!settings || !settings->isJavaScriptEnabled())
637 // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead
638 // when there are no handlers.
639 JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
640 JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld()));
641 ASSERT(windowObject);
643 WebKitWebView* webView = getViewFromFrame(m_frame);
644 g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject);
646 // TODO: Re-attach debug clients if present.
647 // The Win port has an example of how we might do this.
650 void FrameLoaderClient::documentElementAvailable()
654 void FrameLoaderClient::didPerformFirstNavigation() const
656 WebKitCacheModel cacheModel = webkit_get_cache_model();
657 // If user agents do not determine the cache model, we use WEBKIT_CACHE_MODEL_WEB_BROWSER by default.
658 if (cacheModel == WEBKIT_CACHE_MODEL_DEFAULT)
659 webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER);
662 void FrameLoaderClient::registerForIconNotification(bool shouldRegister)
667 void FrameLoaderClient::setMainFrameDocumentReady(bool ready)
670 DOMObjectCache::clearByFrame(core(m_frame));
673 bool FrameLoaderClient::hasWebView() const
675 return getViewFromFrame(m_frame);
678 void FrameLoaderClient::dispatchDidFinishLoad()
680 if (m_loadingErrorPage) {
681 m_loadingErrorPage = false;
685 loadDone(m_frame, true);
688 void FrameLoaderClient::frameLoadCompleted()
693 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
698 void FrameLoaderClient::restoreViewState()
703 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
705 // FIXME: This is a very simple implementation. More sophisticated
706 // implementation would delegate the decision to a PolicyDelegate.
707 // See mac implementation for example.
711 bool FrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const
716 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
720 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
724 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const
728 void FrameLoaderClient::didDisplayInsecureContent()
733 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&)
738 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*)
740 m_hasRepresentation = true;
743 void FrameLoaderClient::forceLayout()
745 FrameView* view = core(m_frame)->view();
747 view->forceLayout(true);
750 void FrameLoaderClient::forceLayoutForNonHTML()
755 void FrameLoaderClient::setCopiesOnScroll()
760 void FrameLoaderClient::detachedFromParent2()
765 void FrameLoaderClient::detachedFromParent3()
770 void FrameLoaderClient::dispatchDidHandleOnloadEvents()
772 g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame);
775 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
780 void FrameLoaderClient::dispatchDidCancelClientRedirect()
785 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double)
790 void FrameLoaderClient::dispatchDidChangeLocationWithinPage()
792 WebKitWebFramePrivate* priv = m_frame->priv;
794 priv->uri = g_strdup(core(m_frame)->document()->url().string().utf8().data());
795 g_object_notify(G_OBJECT(m_frame), "uri");
796 WebKitWebView* webView = getViewFromFrame(m_frame);
797 if (m_frame == webkit_web_view_get_main_frame(webView))
798 g_object_notify(G_OBJECT(webView), "uri");
801 void FrameLoaderClient::dispatchDidPushStateWithinPage()
806 void FrameLoaderClient::dispatchDidReplaceStateWithinPage()
811 void FrameLoaderClient::dispatchDidPopStateWithinPage()
816 void FrameLoaderClient::dispatchWillClose()
821 void FrameLoaderClient::dispatchDidReceiveIcon()
823 if (m_loadingErrorPage)
826 const gchar* frameURI = webkit_web_frame_get_uri(m_frame);
827 WebKitIconDatabase* database = webkit_get_icon_database();
828 g_signal_emit_by_name(database, "icon-loaded", m_frame, frameURI);
830 WebKitWebView* webView = getViewFromFrame(m_frame);
832 // Avoid reporting favicons for non-main frames.
833 if (m_frame != webkit_web_view_get_main_frame(webView))
836 g_object_notify(G_OBJECT(webView), "icon-uri");
837 g_signal_emit_by_name(webView, "icon-loaded", webkit_web_view_get_icon_uri(webView));
840 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
842 if (m_loadingErrorPage)
845 notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL);
848 void FrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
850 if (m_loadingErrorPage)
853 WebKitWebFramePrivate* priv = m_frame->priv;
855 // FIXME: use direction of title.
856 priv->title = g_strdup(title.string().utf8().data());
858 g_signal_emit_by_name(m_frame, "title-changed", priv->title);
859 g_object_notify(G_OBJECT(m_frame), "title");
861 WebKitWebView* webView = getViewFromFrame(m_frame);
862 if (m_frame == webkit_web_view_get_main_frame(webView)) {
863 g_signal_emit_by_name(webView, "title-changed", m_frame, title.string().utf8().data());
864 g_object_notify(G_OBJECT(webView), "title");
868 void FrameLoaderClient::dispatchDidChangeIcons(WebCore::IconType)
873 void FrameLoaderClient::dispatchDidCommitLoad()
875 if (m_loadingErrorPage)
878 /* Update the URI once first data has been received.
879 * This means the URI is valid and successfully identify the page that's going to be loaded.
881 g_object_freeze_notify(G_OBJECT(m_frame));
883 WebKitWebFramePrivate* priv = m_frame->priv;
885 priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().string().utf8().data());
888 g_object_notify(G_OBJECT(m_frame), "uri");
889 g_object_notify(G_OBJECT(m_frame), "title");
891 g_signal_emit_by_name(m_frame, "load-committed");
892 notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED);
894 WebKitWebView* webView = getViewFromFrame(m_frame);
895 if (m_frame == webkit_web_view_get_main_frame(webView)) {
896 g_object_freeze_notify(G_OBJECT(webView));
897 g_object_notify(G_OBJECT(webView), "uri");
898 g_object_notify(G_OBJECT(webView), "title");
899 g_object_thaw_notify(G_OBJECT(webView));
900 g_signal_emit_by_name(webView, "load-committed", m_frame);
903 g_object_thaw_notify(G_OBJECT(m_frame));
906 void FrameLoaderClient::dispatchDidFinishDocumentLoad()
908 WebKitWebView* webView = getViewFromFrame(m_frame);
909 g_signal_emit_by_name(webView, "document-load-finished", m_frame);
912 void FrameLoaderClient::dispatchDidFirstLayout()
917 void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
919 if (m_loadingErrorPage)
922 notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT);
925 void FrameLoaderClient::dispatchShow()
927 WebKitWebView* webView = getViewFromFrame(m_frame);
928 webkit_web_view_notify_ready(webView);
931 void FrameLoaderClient::cancelPolicyCheck()
933 //FIXME Add support for more than one policy decision at once
934 if (m_policyDecision)
935 webkit_web_policy_decision_cancel(m_policyDecision);
938 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*)
943 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*)
945 m_hasRepresentation = true;
948 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*)
953 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l)
955 setTitle(l->title(), l->url());
958 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const
964 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
970 bool FrameLoaderClient::canShowMIMEType(const String& type) const
972 return (MIMETypeRegistry::isSupportedImageMIMEType(type)
973 || MIMETypeRegistry::isSupportedNonImageMIMEType(type)
974 || MIMETypeRegistry::isSupportedMediaMIMEType(type)
975 || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type));
978 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const
984 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const
990 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader)
993 // This is necessary to create an empty document,
994 // but it has to be skipped in the provisional phase.
995 if (m_hasRepresentation)
996 documentLoader->writer()->setEncoding("", false);
998 m_pluginView->didFinishLoading();
1000 m_hasSentResponseToPlugin = false;
1005 void FrameLoaderClient::provisionalLoadStarted()
1010 void FrameLoaderClient::didFinishLoad() {
1014 void FrameLoaderClient::prepareForDataSourceReplacement()
1019 void FrameLoaderClient::setTitle(const StringWithDirection& title, const KURL& url)
1021 WebKitWebFramePrivate* frameData = m_frame->priv;
1022 g_free(frameData->title);
1023 // FIXME: use direction of title.
1024 frameData->title = g_strdup(title.string().utf8().data());
1027 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int dataLength)
1032 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier)
1034 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1036 WebKitWebView* webView = getViewFromFrame(m_frame);
1037 GOwnPtr<gchar> identifierString(toString(identifier));
1038 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
1040 // A NULL WebResource means the load has been interrupted, and
1041 // replaced by another one while this resource was being loaded.
1045 const char* uri = webkit_web_resource_get_uri(webResource);
1046 RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri)));
1048 // If coreResource is NULL here, the resource failed to load,
1049 // unless it's the main resource.
1050 if (!coreResource && webResource != webkit_web_view_get_main_resource(webView))
1054 coreResource = loader->mainResource();
1056 webkit_web_resource_init_with_core_resource(webResource, coreResource.get());
1058 // FIXME: This function should notify the application that the resource
1059 // finished loading, maybe using a load-status property in the
1060 // WebKitWebResource object, similar to what we do for WebKitWebFrame'
1065 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
1067 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1069 // FIXME: This function should notify the application that the resource failed
1070 // loading, maybe a 'load-error' signal in the WebKitWebResource object.
1074 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
1080 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
1082 dispatchDidFailLoad(error);
1085 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
1087 if (m_loadingErrorPage)
1090 notifyStatus(m_frame, WEBKIT_LOAD_FAILED);
1092 WebKitWebView* webView = getViewFromFrame(m_frame);
1093 GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()),
1095 error.localizedDescription().utf8().data());
1096 gboolean isHandled = false;
1097 g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled);
1100 g_error_free(webError);
1104 if (!shouldFallBack(error)) {
1105 g_error_free(webError);
1109 m_loadingErrorPage = true;
1112 gchar* fileContent = 0;
1113 gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL);
1114 GFile* errorFile = g_file_new_for_uri(errorURI);
1118 content = makeString("<html><body>", webError->message, "</body></html>");
1120 gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0);
1122 content = makeString("<html><body>", webError->message, "</body></html>");
1124 content = String::format(fileContent, error.failingURL().utf8().data(), webError->message);
1127 webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data());
1129 g_free(fileContent);
1132 g_object_unref(errorFile);
1134 g_error_free(webError);
1137 void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
1139 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1140 WebKitWebView* view = getViewFromFrame(m_frame);
1142 webkit_web_view_request_download(view, networkRequest.get(), response, handle);
1145 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request)
1147 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED,
1148 request.url().string(), _("Load request cancelled"));
1151 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request)
1153 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT,
1154 request.url().string(), _("Not allowed to use restricted network port"));
1157 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1159 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL,
1160 request.url().string(), _("URL cannot be shown"));
1163 ResourceError FrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1165 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE,
1166 request.url().string(), _("Frame load was interrupted"));
1169 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1171 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE,
1172 response.url().string(), _("Content with the specified MIME type cannot be shown"));
1175 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1177 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST,
1178 response.url().string(), _("File does not exist"));
1181 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1183 return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD,
1184 response.url().string(), _("Plugin will handle load"));
1187 bool FrameLoaderClient::shouldFallBack(const ResourceError& error)
1189 return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD);
1192 bool FrameLoaderClient::canCachePage() const
1197 Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&)
1199 WebKitWebView* webView = getViewFromFrame(m_frame);
1200 WebKitWebView* newWebView = 0;
1202 g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView);
1207 WebKitWebViewPrivate* privateData = newWebView->priv;
1208 return core(privateData->mainFrame);
1211 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&)
1216 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error)
1219 m_pluginView->didFail(error);
1221 m_hasSentResponseToPlugin = false;
1225 void FrameLoaderClient::startDownload(const ResourceRequest& request, const String& /* suggestedName */)
1227 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1228 WebKitWebView* view = getViewFromFrame(m_frame);
1230 webkit_web_view_request_download(view, networkRequest.get());
1233 void FrameLoaderClient::updateGlobalHistory()
1238 void FrameLoaderClient::updateGlobalHistoryRedirectLinks()
1243 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1247 static void postCommitFrameViewSetup(WebKitWebFrame *frame)
1249 WebKitWebView* containingWindow = getViewFromFrame(frame);
1250 webkit_web_view_clear_resources(containingWindow);
1252 // Invalidate the viewport attributes - they will only be valid
1253 // again if the page we're beginning to load now has an
1254 // appropriate viewport meta tag.
1255 WebKitWebViewPrivate* priv = containingWindow->priv;
1256 priv->viewportAttributes->priv->isValid = FALSE;
1257 g_object_notify(G_OBJECT(priv->viewportAttributes.get()), "valid");
1259 if (priv->currentMenu) {
1260 gtk_widget_destroy(GTK_WIDGET(priv->currentMenu));
1261 priv->currentMenu = 0;
1264 // Do not allow click counting between main frame loads.
1265 priv->clickCounter.reset();
1268 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1270 ASSERT(cachedFrame->view());
1272 Frame* frame = core(m_frame);
1273 if (frame != frame->page()->mainFrame())
1276 postCommitFrameViewSetup(m_frame);
1279 void FrameLoaderClient::transitionToCommittedForNewPage()
1281 WebKitWebView* containingWindow = getViewFromFrame(m_frame);
1282 GtkAllocation allocation;
1283 #if GTK_CHECK_VERSION(2, 18, 0)
1284 gtk_widget_get_allocation(GTK_WIDGET(containingWindow), &allocation);
1286 allocation = GTK_WIDGET(containingWindow)->allocation;
1288 IntSize size = IntSize(allocation.width, allocation.height);
1289 bool transparent = webkit_web_view_get_transparent(containingWindow);
1290 Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white;
1291 Frame* frame = core(m_frame);
1294 frame->createView(size, backgroundColor, transparent, IntSize(), false);
1296 // We need to do further manipulation on the FrameView if it was the mainFrame
1297 if (frame != frame->page()->mainFrame())
1300 postCommitFrameViewSetup(m_frame);
1303 void FrameLoaderClient::didSaveToPageCache()
1307 void FrameLoaderClient::didRestoreFromPageCache()
1311 void FrameLoaderClient::dispatchDidBecomeFrameset(bool)
1315 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext()
1317 return FrameNetworkingContextGtk::create(core(m_frame));