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.
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 #include "FrameLoaderClientGtk.h"
28 #include "ArchiveResource.h"
29 #include "CachedFrame.h"
31 #include "DOMObjectCache.h"
32 #include "DocumentLoader.h"
33 #include "DocumentLoaderGtk.h"
34 #include "FormState.h"
35 #include "FrameLoader.h"
36 #include "FrameNetworkingContextGtk.h"
37 #include "FrameTree.h"
38 #include "FrameView.h"
41 #include "GtkPluginWidget.h"
42 #include "HTMLAppletElement.h"
43 #include "HTMLFormElement.h"
44 #include "HTMLFrameElement.h"
45 #include "HTMLFrameOwnerElement.h"
46 #include "HTMLNames.h"
47 #include "HTMLPlugInElement.h"
48 #include "JSDOMBinding.h"
49 #include "JSDOMWindow.h"
51 #include "MIMETypeRegistry.h"
52 #include "MouseEvent.h"
53 #include "NotImplemented.h"
55 #include "PluginDatabase.h"
56 #include "ProgressTracker.h"
57 #include "RenderPart.h"
58 #include "ResourceHandle.h"
59 #include "ResourceRequest.h"
60 #include "ScriptController.h"
62 #include "webkiterror.h"
63 #include "webkitglobals.h"
64 #include "webkitglobalsprivate.h"
65 #include "webkitnetworkrequest.h"
66 #include "webkitnetworkrequestprivate.h"
67 #include "webkitnetworkresponse.h"
68 #include "webkitnetworkresponseprivate.h"
69 #include "webkitviewportattributes.h"
70 #include "webkitviewportattributesprivate.h"
71 #include "webkitwebdatasourceprivate.h"
72 #include "webkitwebframe.h"
73 #include "webkitwebframeprivate.h"
74 #include "webkitwebnavigationaction.h"
75 #include "webkitwebnavigationactionprivate.h"
76 #include "webkitwebpolicydecision.h"
77 #include "webkitwebpolicydecisionprivate.h"
78 #include "webkitwebresource.h"
79 #include "webkitwebresourceprivate.h"
80 #include "webkitwebsettingsprivate.h"
81 #include "webkitwebview.h"
82 #include "webkitwebviewprivate.h"
83 #include <JavaScriptCore/APICast.h>
86 #include <glib/gi18n-lib.h>
88 #include <wtf/text/CString.h>
89 #include <wtf/text/StringConcatenate.h>
91 using namespace WebCore;
95 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
98 , m_loadingErrorPage(false)
100 , m_hasSentResponseToPlugin(false)
101 , m_hasRepresentation(false)
106 FrameLoaderClient::~FrameLoaderClient()
108 if (m_policyDecision)
109 g_object_unref(m_policyDecision);
112 static void initializeDomainsList(HashSet<String>& googleDomains)
114 // Google search domains.
115 googleDomains.add("biz");
116 googleDomains.add("com");
117 googleDomains.add("net");
118 googleDomains.add("org");
119 googleDomains.add("ae");
120 googleDomains.add("ag");
121 googleDomains.add("am");
122 googleDomains.add("at");
123 googleDomains.add("az");
124 googleDomains.add("be");
125 googleDomains.add("bi");
126 googleDomains.add("ca");
127 googleDomains.add("cc");
128 googleDomains.add("cd");
129 googleDomains.add("cg");
130 googleDomains.add("ch");
131 googleDomains.add("cl");
132 googleDomains.add("com.br");
133 googleDomains.add("co.uk");
134 googleDomains.add("co.kr");
135 googleDomains.add("co.jp");
136 googleDomains.add("de");
137 googleDomains.add("dj");
138 googleDomains.add("dk");
139 googleDomains.add("es");
140 googleDomains.add("fi");
141 googleDomains.add("fm");
142 googleDomains.add("fr");
143 googleDomains.add("gg");
144 googleDomains.add("gl");
145 googleDomains.add("gm");
146 googleDomains.add("gs");
147 googleDomains.add("hn");
148 googleDomains.add("hu");
149 googleDomains.add("ie");
150 googleDomains.add("it");
151 googleDomains.add("je");
152 googleDomains.add("kz");
153 googleDomains.add("li");
154 googleDomains.add("lt");
155 googleDomains.add("lu");
156 googleDomains.add("lv");
157 googleDomains.add("ma");
158 googleDomains.add("ms");
159 googleDomains.add("mu");
160 googleDomains.add("mw");
161 googleDomains.add("nl");
162 googleDomains.add("no");
163 googleDomains.add("nu");
164 googleDomains.add("pl");
165 googleDomains.add("pn");
166 googleDomains.add("pt");
167 googleDomains.add("ru");
168 googleDomains.add("rw");
169 googleDomains.add("sh");
170 googleDomains.add("sk");
171 googleDomains.add("sm");
172 googleDomains.add("st");
173 googleDomains.add("td");
174 googleDomains.add("tk");
175 googleDomains.add("tp");
176 googleDomains.add("tv");
177 googleDomains.add("us");
178 googleDomains.add("uz");
179 googleDomains.add("ws");
182 static bool isGoogleDomain(String host)
184 DEFINE_STATIC_LOCAL(HashSet<String>, googleDomains, ());
185 DEFINE_STATIC_LOCAL(Vector<String>, otherGoogleDomains, ());
187 if (googleDomains.isEmpty()) {
188 otherGoogleDomains.append("gmail.com");
189 otherGoogleDomains.append("youtube.com");
190 otherGoogleDomains.append("gstatic.com");
191 otherGoogleDomains.append("ytimg.com");
193 initializeDomainsList(googleDomains);
196 // First check if this is one of the various google.com international domains.
197 int position = host.find(".google.");
198 if (position > 0 && googleDomains.contains(host.substring(position + sizeof(".google."))))
201 // Then we check the possibility of it being one of the other, .com-only google domains.
202 for (unsigned int i = 0; i < otherGoogleDomains.size(); i++) {
203 if (host.endsWith(otherGoogleDomains.at(i)))
210 String FrameLoaderClient::userAgent(const KURL& url)
212 WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame));
215 g_object_get(settings, "enable-site-specific-quirks", &useQuirks, NULL);
217 // For Google domains, drop the browser's custom User Agent string, and use the standard
218 // WebKit/Safari one, so they don't give us a broken experience.
219 if (useQuirks && isGoogleDomain(url.host()))
220 return webkitUserAgent();
222 return String::fromUTF8(webkit_web_settings_get_user_agent(settings));
225 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
227 frame->priv->loadStatus = loadStatus;
228 g_object_notify(G_OBJECT(frame), "load-status");
230 WebKitWebView* webView = getViewFromFrame(frame);
231 if (frame == webkit_web_view_get_main_frame(webView)) {
232 webView->priv->loadStatus = loadStatus;
233 g_object_notify(G_OBJECT(webView), "load-status");
237 static void loadDone(WebKitWebFrame* frame, bool didSucceed)
239 // FIXME: load-done is deprecated. Please remove when signal's been removed.
240 g_signal_emit_by_name(frame, "load-done", didSucceed);
241 notifyStatus(frame, WEBKIT_LOAD_FINISHED);
244 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
246 RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData);
248 GRefPtr<WebKitWebDataSource> webDataSource(adoptGRef(kitNew(loader.get())));
249 loader->setDataSource(webDataSource.get());
251 return loader.release();
254 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>)
256 // FIXME: This is surely too simple
257 ASSERT(policyFunction);
260 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
263 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
266 ASSERT(loader->frame());
267 loader->commitData(data, length);
269 Frame* coreFrame = loader->frame();
270 if (coreFrame && coreFrame->document()->isMediaDocument())
271 loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response()));
275 if (!m_hasSentResponseToPlugin) {
276 m_pluginView->didReceiveResponse(loader->response());
277 m_hasSentResponseToPlugin = true;
280 // FIXME: We may want to investigate refactoring our plugin loading
281 // code to be similar to mac's.
282 // Also, see http://trac.webkit.org/changeset/24118.
286 m_pluginView->didReceiveData(data, length);
291 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long identifier)
297 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
302 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
307 // We convert this to string because it's easier to use strings as
308 // keys in a GHashTable.
309 static char* toString(unsigned long identifier)
311 return g_strdup_printf("%ld", identifier);
314 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
316 GRefPtr<WebKitNetworkResponse> networkResponse(0);
318 // We are adding one more resource to the load, or maybe we are
319 // just redirecting a load.
320 if (redirectResponse.isNull())
321 static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier);
323 networkResponse = adoptGRef(kitNew(redirectResponse));
325 WebKitWebView* webView = getViewFromFrame(m_frame);
326 GOwnPtr<gchar> identifierString(toString(identifier));
327 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
328 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
330 if (!redirectResponse.isNull()) {
331 // This is a redirect, so we need to update the WebResource's knowledge
333 g_free(webResource->priv->uri);
334 webResource->priv->uri = g_strdup(request.url().string().utf8().data());
337 g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get());
339 // Feed any changes back into the ResourceRequest object.
340 SoupMessage* message = webkit_network_request_get_message(networkRequest.get());
342 request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get()))));
346 request.updateFromSoupMessage(message);
349 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request)
351 GOwnPtr<gchar> identifierString(toString(identifier));
353 WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0));
355 if (loader == loader->frameLoader()->provisionalDocumentLoader()
356 && loader->frameLoader()->isLoadingMainFrame()) {
357 webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
361 webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
364 void FrameLoaderClient::postProgressStartedNotification()
366 WebKitWebView* webView = getViewFromFrame(m_frame);
367 g_signal_emit_by_name(webView, "load-started", m_frame);
369 g_object_notify(G_OBJECT(webView), "progress");
372 void FrameLoaderClient::postProgressEstimateChangedNotification()
374 WebKitWebView* webView = getViewFromFrame(m_frame);
375 Page* corePage = core(webView);
377 g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100));
379 g_object_notify(G_OBJECT(webView), "progress");
382 void FrameLoaderClient::postProgressFinishedNotification()
384 WebKitWebView* webView = getViewFromFrame(m_frame);
385 WebKitWebViewPrivate* privateData = webView->priv;
387 // We can get a stopLoad() from dispose when the object is being
388 // destroyed, don't emit the signal in that case.
389 if (!privateData->disposing)
390 g_signal_emit_by_name(webView, "load-finished", m_frame);
393 void FrameLoaderClient::frameLoaderDestroyed()
395 webkit_web_frame_core_frame_gone(m_frame);
396 g_object_unref(m_frame);
401 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long, const ResourceResponse& response)
403 // Update our knowledge of request soup flags - some are only set
404 // after the request is done.
405 loader->request().setSoupMessageFlags(response.soupMessageFlags());
407 m_response = response;
410 void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String& mimeType, const ResourceRequest& resourceRequest)
412 ASSERT(policyFunction);
416 if (resourceRequest.isNull()) {
417 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
421 WebKitWebView* page = getViewFromFrame(m_frame);
422 GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
424 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
425 if (m_policyDecision)
426 g_object_unref(m_policyDecision);
427 m_policyDecision = policyDecision;
429 gboolean isHandled = false;
430 g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled);
435 GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(webkit_web_frame_get_network_response(m_frame)));
436 if (networkResponse) {
437 ResourceResponse response = core(networkResponse.get());
438 if (response.isAttachment()) {
439 webkit_web_policy_decision_download(policyDecision);
444 if (canShowMIMEType(mimeType))
445 webkit_web_policy_decision_use(policyDecision);
447 webkit_web_policy_decision_ignore(policyDecision);
450 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame)
454 const Event* event = action.event();
455 if (event && event->isMouseEvent()) {
456 const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event);
457 // DOM button values are 0, 1 and 2 for left, middle and right buttons.
458 // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent.
459 button = mouseEvent->button() + 1;
462 gint modifierFlags = 0;
463 UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event));
465 if (keyStateEvent->shiftKey())
466 modifierFlags |= GDK_SHIFT_MASK;
467 if (keyStateEvent->ctrlKey())
468 modifierFlags |= GDK_CONTROL_MASK;
469 if (keyStateEvent->altKey())
470 modifierFlags |= GDK_MOD1_MASK;
471 if (keyStateEvent->metaKey())
472 modifierFlags |= GDK_MOD2_MASK;
475 return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
476 "reason", kit(action.type()),
477 "original-uri", action.url().string().utf8().data(),
479 "modifier-state", modifierFlags,
480 "target-frame", targetFrame,
484 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName)
486 ASSERT(policyFunction);
490 if (resourceRequest.isNull()) {
491 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
495 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
497 if (m_policyDecision)
498 g_object_unref(m_policyDecision);
499 m_policyDecision = policyDecision;
501 WebKitWebView* webView = getViewFromFrame(m_frame);
502 GRefPtr<WebKitNetworkRequest> request(adoptGRef(webkit_network_request_new(resourceRequest.url().string().utf8().data())));
503 GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, frameName.utf8().data())));
504 gboolean isHandled = false;
506 g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
508 // FIXME: I think Qt version marshals this to another thread so when we
509 // have multi-threaded download, we might need to do the same
511 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
514 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>)
516 ASSERT(policyFunction);
520 if (resourceRequest.isNull()) {
521 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
525 WebKitWebView* webView = getViewFromFrame(m_frame);
526 GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
527 WebKitNavigationResponse response;
529 * We still support the deprecated navigation-requested signal, if the
530 * application doesn't ignore the navigation then the new signal is
532 * navigation-policy-decision-requested must be emitted after
533 * navigation-requested as the policy decision can be async.
535 g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response);
537 if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
538 (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
542 WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
543 if (m_policyDecision)
544 g_object_unref(m_policyDecision);
545 m_policyDecision = policyDecision;
547 GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, 0)));
548 gboolean isHandled = false;
549 g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
551 // FIXME Implement default behavior when we can query the backend what protocols it supports
553 webkit_web_policy_decision_use(m_policyDecision);
556 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)
558 /* Check if we want to embed a GtkWidget, fallback to plugins later */
559 CString urlString = url.string().utf8();
560 CString mimeTypeString = mimeType.utf8();
562 ASSERT(paramNames.size() == paramValues.size());
563 GRefPtr<GHashTable> hash = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free));
564 for (unsigned i = 0; i < paramNames.size(); ++i) {
565 g_hash_table_insert(hash.get(),
566 g_strdup(paramNames[i].utf8().data()),
567 g_strdup(paramValues[i].utf8().data()));
570 GtkWidget* gtkWidget = 0;
571 g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget",
572 mimeTypeString.data(), urlString.data(), hash.get(), >kWidget);
574 return adoptRef(new GtkPluginWidget(gtkWidget));
576 RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
578 if (pluginView->status() == PluginStatusLoadedSuccessfully)
584 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
585 const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
588 Frame* parentFrame = core(m_frame);
589 WebKitWebView* webView = getViewFromFrame(m_frame);
590 WebCore::Page* page = core(webView);
591 ASSERT(page == parentFrame->page());
593 WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
594 WebKitWebFramePrivate* framePrivate = kitFrame->priv;
595 framePrivate->webView = webView;
597 RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame));
598 framePrivate->coreFrame = childFrame.get();
600 childFrame->tree()->setName(name);
601 parentFrame->tree()->appendChild(childFrame);
604 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
605 if (!childFrame->page())
608 g_signal_emit_by_name(webView, "frame-created", kitFrame);
610 parentFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
612 // The frame's onload handler may have removed it from the document.
613 if (!childFrame->tree()->parent())
616 return childFrame.release();
619 void FrameLoaderClient::didTransferChildFrameToNewDocument(WebCore::Page*)
623 // Update the frame's webview to the new parent's webview.
624 Frame* coreFrame = core(m_frame);
625 WebKitWebView* webView = getViewFromFrame(m_frame);
627 Frame* parentCoreFrame = coreFrame->tree()->parent();
628 WebKitWebFrame* parentKitFrame = kit(parentCoreFrame);
629 WebKitWebView* parentWebView = getViewFromFrame(parentKitFrame);
630 if (webView != parentWebView)
631 m_frame->priv->webView = parentWebView;
633 ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page());
636 void FrameLoaderClient::transferLoadingResourceFromPage(unsigned long identifier, WebCore::DocumentLoader* docLoader, const WebCore::ResourceRequest& request, WebCore::Page* oldPage)
638 ASSERT(oldPage != core(m_frame)->page());
640 GOwnPtr<gchar> identifierString(toString(identifier));
641 ASSERT(!webkit_web_view_get_resource(getViewFromFrame(m_frame), identifierString.get()));
643 assignIdentifierToInitialRequest(identifier, docLoader, request);
645 webkit_web_view_remove_resource(kit(oldPage), identifierString.get());
648 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
650 ASSERT(!m_pluginView);
651 m_pluginView = static_cast<PluginView*>(pluginWidget);
652 m_hasSentResponseToPlugin = false;
655 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues)
657 return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false);
660 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
662 return FrameLoader::defaultObjectContentType(url, mimeType);
665 String FrameLoaderClient::overrideMediaType() const
671 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
673 if (world != mainThreadNormalWorld())
676 // Is this obsolete now?
677 g_signal_emit_by_name(m_frame, "cleared");
679 Frame* coreFrame = core(m_frame);
682 Settings* settings = coreFrame->settings();
683 if (!settings || !settings->isJavaScriptEnabled())
686 // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead
687 // when there are no handlers.
688 JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
689 JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld()));
690 ASSERT(windowObject);
692 WebKitWebView* webView = getViewFromFrame(m_frame);
693 g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject);
695 // TODO: Re-attach debug clients if present.
696 // The Win port has an example of how we might do this.
699 void FrameLoaderClient::documentElementAvailable()
703 void FrameLoaderClient::didPerformFirstNavigation() const
705 WebKitCacheModel cacheModel = webkit_get_cache_model();
706 // If user agents do not determine the cache model, we use WEBKIT_CACHE_MODEL_WEB_BROWSER by default.
707 if (cacheModel == WEBKIT_CACHE_MODEL_DEFAULT)
708 webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER);
711 void FrameLoaderClient::registerForIconNotification(bool shouldRegister)
716 void FrameLoaderClient::setMainFrameDocumentReady(bool ready)
719 DOMObjectCache::clearByFrame(core(m_frame));
722 bool FrameLoaderClient::hasWebView() const
724 return getViewFromFrame(m_frame);
727 void FrameLoaderClient::dispatchDidFinishLoad()
729 if (m_loadingErrorPage) {
730 m_loadingErrorPage = false;
734 loadDone(m_frame, true);
737 void FrameLoaderClient::frameLoadCompleted()
742 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
747 void FrameLoaderClient::restoreViewState()
752 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
754 // FIXME: This is a very simple implementation. More sophisticated
755 // implementation would delegate the decision to a PolicyDelegate.
756 // See mac implementation for example.
760 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
764 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
768 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const
772 void FrameLoaderClient::didDisplayInsecureContent()
777 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&)
782 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*)
784 m_hasRepresentation = true;
787 void FrameLoaderClient::forceLayout()
789 FrameView* view = core(m_frame)->view();
791 view->forceLayout(true);
794 void FrameLoaderClient::forceLayoutForNonHTML()
799 void FrameLoaderClient::setCopiesOnScroll()
804 void FrameLoaderClient::detachedFromParent2()
809 void FrameLoaderClient::detachedFromParent3()
814 void FrameLoaderClient::dispatchDidHandleOnloadEvents()
816 g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame);
819 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
824 void FrameLoaderClient::dispatchDidCancelClientRedirect()
829 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double)
834 void FrameLoaderClient::dispatchDidChangeLocationWithinPage()
836 WebKitWebFramePrivate* priv = m_frame->priv;
838 priv->uri = g_strdup(core(m_frame)->document()->url().prettyURL().utf8().data());
839 g_object_notify(G_OBJECT(m_frame), "uri");
840 WebKitWebView* webView = getViewFromFrame(m_frame);
841 if (m_frame == webkit_web_view_get_main_frame(webView))
842 g_object_notify(G_OBJECT(webView), "uri");
845 void FrameLoaderClient::dispatchDidPushStateWithinPage()
850 void FrameLoaderClient::dispatchDidReplaceStateWithinPage()
855 void FrameLoaderClient::dispatchDidPopStateWithinPage()
860 void FrameLoaderClient::dispatchWillClose()
865 void FrameLoaderClient::dispatchDidReceiveIcon()
867 if (m_loadingErrorPage)
870 WebKitWebView* webView = getViewFromFrame(m_frame);
872 // Avoid reporting favicons for non-main frames.
873 if (m_frame != webkit_web_view_get_main_frame(webView))
876 g_object_notify(G_OBJECT(webView), "icon-uri");
877 g_signal_emit_by_name(webView, "icon-loaded", webkit_web_view_get_icon_uri(webView));
880 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
882 if (m_loadingErrorPage)
885 notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL);
888 void FrameLoaderClient::dispatchDidReceiveTitle(const String& title)
890 if (m_loadingErrorPage)
893 WebKitWebFramePrivate* priv = m_frame->priv;
895 priv->title = g_strdup(title.utf8().data());
897 g_signal_emit_by_name(m_frame, "title-changed", priv->title);
898 g_object_notify(G_OBJECT(m_frame), "title");
900 WebKitWebView* webView = getViewFromFrame(m_frame);
901 if (m_frame == webkit_web_view_get_main_frame(webView)) {
902 g_signal_emit_by_name(webView, "title-changed", m_frame, title.utf8().data());
903 g_object_notify(G_OBJECT(webView), "title");
907 void FrameLoaderClient::dispatchDidChangeIcons()
912 void FrameLoaderClient::dispatchDidCommitLoad()
914 if (m_loadingErrorPage)
917 /* Update the URI once first data has been received.
918 * This means the URI is valid and successfully identify the page that's going to be loaded.
920 g_object_freeze_notify(G_OBJECT(m_frame));
922 WebKitWebFramePrivate* priv = m_frame->priv;
924 priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().prettyURL().utf8().data());
927 g_object_notify(G_OBJECT(m_frame), "uri");
928 g_object_notify(G_OBJECT(m_frame), "title");
930 g_signal_emit_by_name(m_frame, "load-committed");
931 notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED);
933 WebKitWebView* webView = getViewFromFrame(m_frame);
934 if (m_frame == webkit_web_view_get_main_frame(webView)) {
935 g_object_freeze_notify(G_OBJECT(webView));
936 g_object_notify(G_OBJECT(webView), "uri");
937 g_object_notify(G_OBJECT(webView), "title");
938 g_object_thaw_notify(G_OBJECT(webView));
939 g_signal_emit_by_name(webView, "load-committed", m_frame);
942 g_object_thaw_notify(G_OBJECT(m_frame));
945 void FrameLoaderClient::dispatchDidFinishDocumentLoad()
947 WebKitWebView* webView = getViewFromFrame(m_frame);
948 g_signal_emit_by_name(webView, "document-load-finished", m_frame);
951 void FrameLoaderClient::dispatchDidFirstLayout()
956 void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
958 if (m_loadingErrorPage)
961 notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT);
964 void FrameLoaderClient::dispatchShow()
966 WebKitWebView* webView = getViewFromFrame(m_frame);
967 webkit_web_view_notify_ready(webView);
970 void FrameLoaderClient::cancelPolicyCheck()
972 //FIXME Add support for more than one policy decision at once
973 if (m_policyDecision)
974 webkit_web_policy_decision_cancel(m_policyDecision);
977 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*)
982 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*)
984 m_hasRepresentation = true;
987 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*)
992 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l)
994 setTitle(l->title(), l->url());
997 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1003 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
1009 bool FrameLoaderClient::canShowMIMEType(const String& type) const
1011 return (MIMETypeRegistry::isSupportedImageMIMEType(type)
1012 || MIMETypeRegistry::isSupportedNonImageMIMEType(type)
1013 || MIMETypeRegistry::isSupportedMediaMIMEType(type)
1014 || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type));
1017 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const
1023 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const
1029 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader)
1031 if (!m_pluginView) {
1032 // This is necessary to create an empty document,
1033 // but it has to be skipped in the provisional phase.
1034 if (m_hasRepresentation)
1035 documentLoader->writer()->setEncoding("", false);
1037 m_pluginView->didFinishLoading();
1039 m_hasSentResponseToPlugin = false;
1044 void FrameLoaderClient::provisionalLoadStarted()
1049 void FrameLoaderClient::didFinishLoad() {
1053 void FrameLoaderClient::prepareForDataSourceReplacement()
1058 void FrameLoaderClient::setTitle(const String& title, const KURL& url)
1060 WebKitWebFramePrivate* frameData = m_frame->priv;
1061 g_free(frameData->title);
1062 frameData->title = g_strdup(title.utf8().data());
1065 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived)
1070 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier)
1072 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1074 WebKitWebView* webView = getViewFromFrame(m_frame);
1075 GOwnPtr<gchar> identifierString(toString(identifier));
1076 WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
1078 // A NULL WebResource means the load has been interrupted, and
1079 // replaced by another one while this resource was being loaded.
1083 const char* uri = webkit_web_resource_get_uri(webResource);
1084 RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri)));
1086 // If coreResource is NULL here, the resource failed to load,
1087 // unless it's the main resource.
1088 if (!coreResource && webResource != webkit_web_view_get_main_resource(webView))
1092 coreResource = loader->mainResource();
1094 webkit_web_resource_init_with_core_resource(webResource, coreResource.get());
1096 // FIXME: This function should notify the application that the resource
1097 // finished loading, maybe using a load-status property in the
1098 // WebKitWebResource object, similar to what we do for WebKitWebFrame'
1103 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
1105 static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1107 // FIXME: This function should notify the application that the resource failed
1108 // loading, maybe a 'load-error' signal in the WebKitWebResource object.
1112 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
1118 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
1120 dispatchDidFailLoad(error);
1123 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
1125 if (m_loadingErrorPage)
1128 notifyStatus(m_frame, WEBKIT_LOAD_FAILED);
1130 WebKitWebView* webView = getViewFromFrame(m_frame);
1131 GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()),
1133 error.localizedDescription().utf8().data());
1134 gboolean isHandled = false;
1135 g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled);
1138 g_error_free(webError);
1142 if (!shouldFallBack(error)) {
1143 g_error_free(webError);
1147 m_loadingErrorPage = true;
1150 gchar* fileContent = 0;
1151 gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL);
1152 GFile* errorFile = g_file_new_for_uri(errorURI);
1156 content = makeString("<html><body>", webError->message, "</body></html>");
1158 gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0);
1160 content = makeString("<html><body>", webError->message, "</body></html>");
1162 content = String::format(fileContent, error.failingURL().utf8().data(), webError->message);
1165 webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data());
1167 g_free(fileContent);
1170 g_object_unref(errorFile);
1172 g_error_free(webError);
1175 void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
1177 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1178 WebKitWebView* view = getViewFromFrame(m_frame);
1180 webkit_web_view_request_download(view, networkRequest.get(), response, handle);
1183 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request)
1185 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED,
1186 request.url().string(), _("Load request cancelled"));
1189 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request)
1191 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT,
1192 request.url().string(), _("Not allowed to use restricted network port"));
1195 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1197 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL,
1198 request.url().string(), _("URL cannot be shown"));
1201 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
1203 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE,
1204 request.url().string(), _("Frame load was interrupted"));
1207 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1209 return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE,
1210 response.url().string(), _("Content with the specified MIME type cannot be shown"));
1213 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1215 return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST,
1216 response.url().string(), _("File does not exist"));
1219 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1221 return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD,
1222 response.url().string(), _("Plugin will handle load"));
1225 bool FrameLoaderClient::shouldFallBack(const ResourceError& error)
1227 return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD);
1230 bool FrameLoaderClient::canCachePage() const
1235 Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&)
1237 WebKitWebView* webView = getViewFromFrame(m_frame);
1238 WebKitWebView* newWebView = 0;
1240 g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView);
1245 WebKitWebViewPrivate* privateData = newWebView->priv;
1246 return core(privateData->mainFrame);
1249 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&)
1254 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error)
1257 m_pluginView->didFail(error);
1259 m_hasSentResponseToPlugin = false;
1263 void FrameLoaderClient::startDownload(const ResourceRequest& request)
1265 GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1266 WebKitWebView* view = getViewFromFrame(m_frame);
1268 webkit_web_view_request_download(view, networkRequest.get());
1271 void FrameLoaderClient::updateGlobalHistory()
1276 void FrameLoaderClient::updateGlobalHistoryRedirectLinks()
1281 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1283 // We need to do this here in order to disconnect the scrollbars
1284 // that are being used by the frame that is being cached from the
1285 // adjustments, otherwise they will react to changes in the
1286 // adjustments, and bad things will happen.
1287 if (cachedFrame->view())
1288 cachedFrame->view()->setGtkAdjustments(0, 0);
1291 static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues)
1293 WebKitWebView* containingWindow = getViewFromFrame(frame);
1294 webkit_web_view_clear_resources(containingWindow);
1296 WebKitWebViewPrivate* priv = containingWindow->priv;
1297 view->setGtkAdjustments(priv->horizontalAdjustment.get(), priv->verticalAdjustment.get(), resetValues);
1299 // Invalidate the viewport attributes - they will only be valid
1300 // again if the page we're beginning to load now has an
1301 // appropriate viewport meta tag.
1302 containingWindow->priv->viewportAttributes->priv->isValid = FALSE;
1303 g_object_notify(G_OBJECT(containingWindow->priv->viewportAttributes.get()), "valid");
1305 if (priv->currentMenu) {
1306 gtk_widget_destroy(GTK_WIDGET(priv->currentMenu));
1307 priv->currentMenu = 0;
1310 // Do not allow click counting between main frame loads.
1311 priv->previousClickTime = 0;
1314 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1316 ASSERT(cachedFrame->view());
1318 Frame* frame = core(m_frame);
1319 if (frame != frame->page()->mainFrame())
1322 postCommitFrameViewSetup(m_frame, cachedFrame->view(), false);
1325 void FrameLoaderClient::transitionToCommittedForNewPage()
1327 WebKitWebView* containingWindow = getViewFromFrame(m_frame);
1328 GtkAllocation allocation;
1329 #if GTK_CHECK_VERSION(2, 18, 0)
1330 gtk_widget_get_allocation(GTK_WIDGET(containingWindow), &allocation);
1332 allocation = GTK_WIDGET(containingWindow)->allocation;
1334 IntSize size = IntSize(allocation.width, allocation.height);
1335 bool transparent = webkit_web_view_get_transparent(containingWindow);
1336 Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white;
1337 Frame* frame = core(m_frame);
1340 frame->createView(size, backgroundColor, transparent, IntSize(), false);
1342 // We need to do further manipulation on the FrameView if it was the mainFrame
1343 if (frame != frame->page()->mainFrame())
1346 postCommitFrameViewSetup(m_frame, frame->view(), true);
1349 void FrameLoaderClient::didSaveToPageCache()
1353 void FrameLoaderClient::didRestoreFromPageCache()
1357 void FrameLoaderClient::dispatchDidBecomeFrameset(bool)
1361 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext()
1363 return FrameNetworkingContextGtk::create(core(m_frame));