24652954287789a26fd8a6df61557ba2820b3eef
[WebKit-https.git] / Source / WebKit / gtk / WebCoreSupport / FrameLoaderClientGtk.cpp
1 /*
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.
10  *
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.
15  *
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.
20  *
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
24  */
25
26 #include "config.h"
27 #include "FrameLoaderClientGtk.h"
28
29 #include "ArchiveResource.h"
30 #include "CachedFrame.h"
31 #include "Color.h"
32 #include "DOMObjectCache.h"
33 #include "DocumentLoader.h"
34 #include "DocumentLoaderGtk.h"
35 #include "DumpRenderTreeSupportGtk.h"
36 #include "ErrorsGtk.h"
37 #include "FileSystem.h"
38 #include "FormState.h"
39 #include "FrameLoader.h"
40 #include "FrameNetworkingContextGtk.h"
41 #include "FrameTree.h"
42 #include "FrameView.h"
43 #include "GtkAuthenticationDialog.h"
44 #include "GtkPluginWidget.h"
45 #include "GtkUtilities.h"
46 #include "HTMLAppletElement.h"
47 #include "HTMLFormElement.h"
48 #include "HTMLFrameElement.h"
49 #include "HTMLFrameOwnerElement.h"
50 #include "HTMLNames.h"
51 #include "HTMLPlugInElement.h"
52 #include "JSDOMBinding.h"
53 #include "JSDOMWindow.h"
54 #include "Language.h"
55 #include "MIMETypeRegistry.h"
56 #include "MainResourceLoader.h"
57 #include "MouseEvent.h"
58 #include "NotImplemented.h"
59 #include "Page.h"
60 #include "PluginDatabase.h"
61 #include "ProgressTracker.h"
62 #include "RenderPart.h"
63 #include "RenderView.h"
64 #include "ResourceHandle.h"
65 #include "ResourceLoader.h"
66 #include "ResourceRequest.h"
67 #include "ScriptController.h"
68 #include "Settings.h"
69 #include "webkiterror.h"
70 #include "webkitfavicondatabase.h"
71 #include "webkitfavicondatabaseprivate.h"
72 #include "webkitglobals.h"
73 #include "webkitglobalsprivate.h"
74 #include "webkitnetworkrequest.h"
75 #include "webkitnetworkrequestprivate.h"
76 #include "webkitnetworkresponse.h"
77 #include "webkitnetworkresponseprivate.h"
78 #include "webkitsecurityoriginprivate.h"
79 #include "webkitviewportattributes.h"
80 #include "webkitviewportattributesprivate.h"
81 #include "webkitwebdatasourceprivate.h"
82 #include "webkitwebframe.h"
83 #include "webkitwebframeprivate.h"
84 #include "webkitwebnavigationaction.h"
85 #include "webkitwebnavigationactionprivate.h"
86 #include "webkitwebpolicydecision.h"
87 #include "webkitwebpolicydecisionprivate.h"
88 #include "webkitwebresource.h"
89 #include "webkitwebresourceprivate.h"
90 #include "webkitwebsettingsprivate.h"
91 #include "webkitwebview.h"
92 #include "webkitwebviewprivate.h"
93 #include <JavaScriptCore/APICast.h>
94 #include <gio/gio.h>
95 #include <glib.h>
96 #include <glib/gi18n-lib.h>
97 #include <stdio.h>
98 #include <wtf/gobject/GOwnPtr.h>
99 #include <wtf/gobject/GRefPtr.h>
100 #include <wtf/text/CString.h>
101 #include <wtf/text/StringConcatenate.h>
102
103 using namespace WebCore;
104
105 namespace WebKit {
106
107 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
108     : m_frame(frame)
109     , m_policyDecision(0)
110     , m_loadingErrorPage(false)
111     , m_pluginView(0)
112     , m_hasSentResponseToPlugin(false)
113 {
114     ASSERT(m_frame);
115 }
116
117 FrameLoaderClient::~FrameLoaderClient()
118 {
119     if (m_policyDecision)
120         g_object_unref(m_policyDecision);
121 }
122
123
124 String FrameLoaderClient::userAgent(const KURL& url)
125 {
126     WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame));
127     GOwnPtr<gchar> userAgentString(webkitWebSettingsUserAgentForURI(settings, url.string().utf8().data()));
128     return String::fromUTF8(userAgentString.get());
129 }
130
131 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
132 {
133     frame->priv->loadStatus = loadStatus;
134     g_object_notify(G_OBJECT(frame), "load-status");
135
136     WebKitWebView* webView = getViewFromFrame(frame);
137     if (frame == webkit_web_view_get_main_frame(webView)) {
138         webView->priv->loadStatus = loadStatus;
139         g_object_notify(G_OBJECT(webView), "load-status");
140     }
141 }
142
143 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
144 {
145     RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData);
146
147     GRefPtr<WebKitWebDataSource> webDataSource(adoptGRef(kitNew(loader.get())));
148     loader->setDataSource(webDataSource.get());
149
150     return loader.release();
151 }
152
153 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>)
154 {
155     // FIXME: This is surely too simple
156     ASSERT(policyFunction);
157     if (!policyFunction)
158         return;
159     (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
160 }
161
162 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
163 {
164     if (!m_pluginView) {
165         ASSERT(loader->frame());
166         loader->commitData(data, length);
167
168         Frame* coreFrame = loader->frame();
169         if (coreFrame && coreFrame->document()->isMediaDocument())
170             loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response()));
171     }
172
173     if (m_pluginView) {
174         if (!m_hasSentResponseToPlugin) {
175             m_pluginView->didReceiveResponse(loader->response());
176             m_hasSentResponseToPlugin = true;
177         }
178
179         // FIXME: We may want to investigate refactoring our plugin loading
180         // code to be similar to mac's.
181         // Also, see http://trac.webkit.org/changeset/24118.
182         if (!m_pluginView)
183             return;
184
185         m_pluginView->didReceiveData(data, length);
186     }
187 }
188
189 bool FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long  identifier)
190 {
191     return true;
192 }
193
194 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge& challenge)
195 {
196     if (DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled()) {
197         CString username;
198         CString password;
199         if (!DumpRenderTreeSupportGtk::s_authenticationCallback || !DumpRenderTreeSupportGtk::s_authenticationCallback(username, password)) {
200             challenge.authenticationClient()->receivedRequestToContinueWithoutCredential(challenge);
201             return;
202         }
203
204         challenge.authenticationClient()->receivedCredential(challenge, Credential(String::fromUTF8(username.data()), String::fromUTF8(password.data()), CredentialPersistenceForSession));
205         return;
206     }
207
208     WebKitWebView* view = webkit_web_frame_get_web_view(m_frame);
209     GtkAuthenticationDialog::CredentialStorageMode credentialStorageMode;
210
211     if (core(view)->settings()->privateBrowsingEnabled())
212         credentialStorageMode = GtkAuthenticationDialog::DisallowPersistentStorage;
213     else
214         credentialStorageMode = GtkAuthenticationDialog::AllowPersistentStorage;
215
216     GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(view));
217     GtkWindow* toplevelWindow = widgetIsOnscreenToplevelWindow(toplevel) ? GTK_WINDOW(toplevel) : 0;
218     GtkAuthenticationDialog* dialog = new GtkAuthenticationDialog(toplevelWindow, challenge, credentialStorageMode);
219     dialog->show();
220 }
221
222 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
223 {
224     notImplemented();
225 }
226
227 // We convert this to string because it's easier to use strings as
228 // keys in a GHashTable.
229 static char* toString(unsigned long identifier)
230 {
231     return g_strdup_printf("%ld", identifier);
232 }
233
234 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
235 {
236     GRefPtr<WebKitNetworkResponse> networkResponse(0);
237
238     // We are adding one more resource to the load, or maybe we are
239     // just redirecting a load.
240     if (redirectResponse.isNull())
241         static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier);
242     else
243         networkResponse = adoptGRef(kitNew(redirectResponse));
244
245     WebKitWebView* webView = getViewFromFrame(m_frame);
246     GOwnPtr<gchar> identifierString(toString(identifier));
247     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
248     GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
249
250     if (!redirectResponse.isNull()) {
251         // This is a redirect, so we need to update the WebResource's knowledge
252         // of the URI.
253         g_free(webResource->priv->uri);
254         webResource->priv->uri = g_strdup(request.url().string().utf8().data());
255     }
256
257     g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get());
258     g_signal_emit_by_name(m_frame, "resource-request-starting", webResource, networkRequest.get(), networkResponse.get());
259
260     // Feed any changes back into the ResourceRequest object.
261     SoupMessage* message = webkit_network_request_get_message(networkRequest.get());
262     if (!message) {
263         request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get()))));
264         return;
265     }
266
267     request.updateFromSoupMessage(message);
268 }
269
270 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request)
271 {
272     GOwnPtr<gchar> identifierString(toString(identifier));
273
274     WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0));
275
276     if (loader == loader->frameLoader()->provisionalDocumentLoader()
277         && loader->frameLoader()->isLoadingMainFrame()) {
278         webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
279         return;
280     }
281
282     webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
283 }
284
285 void FrameLoaderClient::postProgressStartedNotification()
286 {
287     WebKitWebView* webView = getViewFromFrame(m_frame);
288     g_signal_emit_by_name(webView, "load-started", m_frame);
289
290     g_object_notify(G_OBJECT(webView), "progress");
291 }
292
293 void FrameLoaderClient::postProgressEstimateChangedNotification()
294 {
295     WebKitWebView* webView = getViewFromFrame(m_frame);
296     Page* corePage = core(webView);
297
298     g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100));
299
300     g_object_notify(G_OBJECT(webView), "progress");
301 }
302
303 void FrameLoaderClient::postProgressFinishedNotification()
304 {
305     WebKitWebView* webView = getViewFromFrame(m_frame);
306     WebKitWebViewPrivate* privateData = webView->priv;
307
308     // We can get a stopLoad() from dispose when the object is being
309     // destroyed, don't emit the signal in that case.
310     if (!privateData->disposing)
311         g_signal_emit_by_name(webView, "load-finished", m_frame);
312 }
313
314 void FrameLoaderClient::frameLoaderDestroyed()
315 {
316     webkit_web_frame_core_frame_gone(m_frame);
317     g_object_unref(m_frame);
318     m_frame = 0;
319     delete this;
320 }
321
322 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceResponse& response)
323 {
324     // Update our knowledge of request soup flags - some are only set
325     // after the request is done.
326     loader->request().setSoupMessageFlags(response.soupMessageFlags());
327
328     m_response = response;
329
330     WebKitWebView* webView = getViewFromFrame(m_frame);
331     GOwnPtr<gchar> identifierString(toString(identifier));
332     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
333     GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(kitNew(response)));
334
335     g_signal_emit_by_name(webResource, "response-received", networkResponse.get());
336     g_signal_emit_by_name(m_frame, "resource-response-received", webResource, networkResponse.get());
337     g_signal_emit_by_name(webView, "resource-response-received", m_frame, webResource, networkResponse.get());
338 }
339
340 void FrameLoaderClient::dispatchDecidePolicyForResponse(FramePolicyFunction policyFunction, const ResourceResponse& response, const ResourceRequest& resourceRequest)
341 {
342     ASSERT(policyFunction);
343     if (!policyFunction)
344         return;
345
346     if (resourceRequest.isNull()) {
347         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
348         return;
349     }
350
351     WebKitWebView* page = getViewFromFrame(m_frame);
352     GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
353
354     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
355     if (m_policyDecision)
356         g_object_unref(m_policyDecision);
357     m_policyDecision = policyDecision;
358
359     String mimeType = response.mimeType();
360
361     gboolean isHandled = false;
362     g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled);
363
364     if (isHandled)
365         return;
366
367     GRefPtr<WebKitNetworkResponse> networkResponse(adoptGRef(webkit_web_frame_get_network_response(m_frame)));
368     if (networkResponse) {
369         ResourceResponse response = core(networkResponse.get());
370         if (response.isAttachment()) {
371             webkit_web_policy_decision_download(policyDecision);
372             return;
373         }
374     }
375
376     if (canShowMIMEType(mimeType))
377         webkit_web_policy_decision_use(policyDecision);
378     else
379         webkit_web_policy_decision_ignore(policyDecision);
380 }
381
382 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame)
383 {
384     gint button = -1;
385
386     const Event* event = action.event();
387     if (event && event->isMouseEvent()) {
388         const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event);
389         // DOM button values are 0, 1 and 2 for left, middle and right buttons.
390         // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent.
391         button = mouseEvent->button() + 1;
392     }
393
394     gint modifierFlags = 0;
395     UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event));
396     if (keyStateEvent) {
397         if (keyStateEvent->shiftKey())
398             modifierFlags |= GDK_SHIFT_MASK;
399         if (keyStateEvent->ctrlKey())
400             modifierFlags |= GDK_CONTROL_MASK;
401         if (keyStateEvent->altKey())
402             modifierFlags |= GDK_MOD1_MASK;
403         if (keyStateEvent->metaKey())
404             modifierFlags |= GDK_MOD2_MASK;
405     }
406
407     return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
408                                                      "reason", kit(action.type()),
409                                                      "original-uri", action.url().string().utf8().data(),
410                                                      "button", button,
411                                                      "modifier-state", modifierFlags,
412                                                      "target-frame", targetFrame,
413                                                      NULL));
414 }
415
416 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName)
417 {
418     ASSERT(policyFunction);
419     if (!policyFunction)
420         return;
421
422     if (resourceRequest.isNull()) {
423         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
424         return;
425     }
426
427     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
428
429     if (m_policyDecision)
430         g_object_unref(m_policyDecision);
431     m_policyDecision = policyDecision;
432
433     WebKitWebView* webView = getViewFromFrame(m_frame);
434     GRefPtr<WebKitNetworkRequest> request(adoptGRef(webkit_network_request_new(resourceRequest.url().string().utf8().data())));
435     GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, frameName.utf8().data())));
436     gboolean isHandled = false;
437
438     g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
439
440     // FIXME: I think Qt version marshals this to another thread so when we
441     // have multi-threaded download, we might need to do the same
442     if (!isHandled)
443         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
444 }
445
446 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>)
447 {
448     ASSERT(policyFunction);
449     if (!policyFunction)
450         return;
451
452     if (resourceRequest.isNull()) {
453         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
454         return;
455     }
456
457     WebKitWebView* webView = getViewFromFrame(m_frame);
458     GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
459     WebKitNavigationResponse response;
460     /*
461      * We still support the deprecated navigation-requested signal, if the
462      * application doesn't ignore the navigation then the new signal is
463      * emitted.
464      * navigation-policy-decision-requested must be emitted after
465      * navigation-requested as the policy decision can be async.
466      */
467     g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response);
468
469     if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
470         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
471         return;
472     }
473
474     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
475     if (m_policyDecision)
476         g_object_unref(m_policyDecision);
477     m_policyDecision = policyDecision;
478
479     GRefPtr<WebKitWebNavigationAction> navigationAction(adoptGRef(getNavigationAction(action, 0)));
480     gboolean isHandled = false;
481     g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
482
483     // FIXME Implement default behavior when we can query the backend what protocols it supports
484     if (!isHandled)
485         webkit_web_policy_decision_use(m_policyDecision);
486 }
487
488 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)
489 {
490     /* Check if we want to embed a GtkWidget, fallback to plugins later */
491     CString urlString = url.string().utf8();
492     CString mimeTypeString = mimeType.utf8();
493
494     ASSERT(paramNames.size() == paramValues.size());
495     GRefPtr<GHashTable> hash = adoptGRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free));
496     for (unsigned i = 0; i < paramNames.size(); ++i) {
497         g_hash_table_insert(hash.get(),
498                             g_strdup(paramNames[i].utf8().data()),
499                             g_strdup(paramValues[i].utf8().data()));
500     }
501
502     GtkWidget* gtkWidget = 0;
503     g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget",
504                           mimeTypeString.data(), urlString.data(), hash.get(), &gtkWidget);
505     if (gtkWidget) {
506         gtk_container_add(GTK_CONTAINER(getViewFromFrame(m_frame)), gtkWidget);
507         return adoptRef(new GtkPluginWidget(gtkWidget));
508     }
509
510     RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
511
512     if (pluginView->status() == PluginStatusLoadedSuccessfully)
513         return pluginView;
514
515     return 0;
516 }
517
518 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
519                                                  const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
520 {
521     ASSERT(m_frame);
522     Frame* parentFrame = core(m_frame);
523     WebKitWebView* webView = getViewFromFrame(m_frame);
524     WebCore::Page* page = core(webView);
525     ASSERT(page == parentFrame->page());
526
527     WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
528     WebKitWebFramePrivate* framePrivate = kitFrame->priv;
529     framePrivate->webView = webView;
530
531     RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame));
532     framePrivate->coreFrame = childFrame.get();
533
534     childFrame->tree()->setName(name);
535     parentFrame->tree()->appendChild(childFrame);
536     childFrame->init();
537
538     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
539     if (!childFrame->page())
540         return 0;
541
542     g_signal_emit_by_name(webView, "frame-created", kitFrame);
543
544     parentFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
545
546     // The frame's onload handler may have removed it from the document.
547     if (!childFrame->tree()->parent())
548         return 0;
549
550     return childFrame.release();
551 }
552
553 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
554 {
555     m_pluginView = static_cast<PluginView*>(pluginWidget);
556     if (pluginWidget)
557         m_hasSentResponseToPlugin = false;
558 }
559
560 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues)
561 {
562     return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false);
563 }
564
565 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages)
566 {
567     return FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages);
568 }
569
570 String FrameLoaderClient::overrideMediaType() const
571 {
572     notImplemented();
573     return String();
574 }
575
576 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
577 {
578     if (world != mainThreadNormalWorld())
579         return;
580
581     // Is this obsolete now?
582     g_signal_emit_by_name(m_frame, "cleared");
583
584     Frame* coreFrame = core(m_frame);
585     ASSERT(coreFrame);
586
587     Settings* settings = coreFrame->settings();
588     if (!settings || !settings->isScriptEnabled())
589         return;
590
591     // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead
592     // when there are no handlers.
593     JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
594     JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld()));
595     ASSERT(windowObject);
596
597     WebKitWebView* webView = getViewFromFrame(m_frame);
598     g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject);
599
600     // TODO: Re-attach debug clients if present.
601     // The Win port has an example of how we might do this.
602 }
603
604 void FrameLoaderClient::documentElementAvailable()
605 {
606 }
607
608 void FrameLoaderClient::didPerformFirstNavigation() const
609 {
610     WebKitCacheModel cacheModel = webkit_get_cache_model();
611     // If user agents do not determine the cache model, we use WEBKIT_CACHE_MODEL_WEB_BROWSER by default.
612     if (cacheModel == WEBKIT_CACHE_MODEL_DEFAULT)
613         webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER);
614 }
615
616 void FrameLoaderClient::registerForIconNotification(bool shouldRegister)
617 {
618     webkitWebViewRegisterForIconNotification(getViewFromFrame(m_frame), shouldRegister);
619 }
620
621 void FrameLoaderClient::setMainFrameDocumentReady(bool ready)
622 {
623     if (!ready)
624         DOMObjectCache::clearByFrame(core(m_frame));
625 }
626
627 bool FrameLoaderClient::hasWebView() const
628 {
629     return getViewFromFrame(m_frame);
630 }
631
632 void FrameLoaderClient::dispatchDidFinishLoad()
633 {
634     if (m_loadingErrorPage) {
635         m_loadingErrorPage = false;
636         return;
637     }
638     notifyStatus(m_frame, WEBKIT_LOAD_FINISHED);
639 }
640
641 void FrameLoaderClient::frameLoadCompleted()
642 {
643     notImplemented();
644 }
645
646 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
647 {
648     notImplemented();
649 }
650
651 void FrameLoaderClient::restoreViewState()
652 {
653     notImplemented();
654 }
655
656 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
657 {
658     // FIXME: This is a very simple implementation. More sophisticated
659     // implementation would delegate the decision to a PolicyDelegate.
660     // See mac implementation for example.
661     return item != 0;
662 }
663
664 bool FrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const
665 {
666     return true;
667 }
668
669 void FrameLoaderClient::didDisplayInsecureContent()
670 {
671     if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled() || !DumpRenderTreeSupportGtk::s_frameLoadEventCallback)
672         return;
673     DumpRenderTreeSupportGtk::s_frameLoadEventCallback(m_frame, DumpRenderTreeSupportGtk::DidDisplayInsecureContent, 0);
674 }
675
676 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin* coreOrigin, const KURL& url)
677 {
678     g_signal_emit_by_name(m_frame, "insecure-content-run", kit(coreOrigin), url.string().utf8().data());
679 }
680
681 void FrameLoaderClient::didDetectXSS(const KURL&, bool)
682 {
683     if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled() || !DumpRenderTreeSupportGtk::s_frameLoadEventCallback)
684         return;
685     DumpRenderTreeSupportGtk::s_frameLoadEventCallback(m_frame, DumpRenderTreeSupportGtk::DidDetectXSS, 0);
686 }
687
688 void FrameLoaderClient::forceLayout()
689 {
690     FrameView* view = core(m_frame)->view();
691     if (view)
692         view->forceLayout(true);
693 }
694
695 void FrameLoaderClient::forceLayoutForNonHTML()
696 {
697     notImplemented();
698 }
699
700 void FrameLoaderClient::setCopiesOnScroll()
701 {
702     notImplemented();
703 }
704
705 void FrameLoaderClient::detachedFromParent2()
706 {
707     notImplemented();
708 }
709
710 void FrameLoaderClient::detachedFromParent3()
711 {
712     notImplemented();
713 }
714
715 void FrameLoaderClient::dispatchDidHandleOnloadEvents()
716 {
717     g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame);
718 }
719
720 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
721 {
722     if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled() || !DumpRenderTreeSupportGtk::s_frameLoadEventCallback)
723         return;
724     DumpRenderTreeSupportGtk::s_frameLoadEventCallback(m_frame, DumpRenderTreeSupportGtk::DidReceiveServerRedirectForProvisionalLoad, 0);
725 }
726
727 void FrameLoaderClient::dispatchDidCancelClientRedirect()
728 {
729     if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled() || !DumpRenderTreeSupportGtk::s_frameLoadEventCallback)
730         return;
731     DumpRenderTreeSupportGtk::s_frameLoadEventCallback(m_frame, DumpRenderTreeSupportGtk::DidCancelClientRedirect, 0);
732 }
733
734 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL& url, double, double)
735 {
736     if (!DumpRenderTreeSupportGtk::dumpRenderTreeModeEnabled() || !DumpRenderTreeSupportGtk::s_frameLoadEventCallback)
737         return;
738     DumpRenderTreeSupportGtk::s_frameLoadEventCallback(m_frame, DumpRenderTreeSupportGtk::WillPerformClientRedirectToURL, url.string().utf8().data());
739 }
740
741 void FrameLoaderClient::dispatchDidChangeLocationWithinPage()
742 {
743     WebKitWebFramePrivate* priv = m_frame->priv;
744     g_free(priv->uri);
745     priv->uri = g_strdup(core(m_frame)->document()->url().string().utf8().data());
746     g_object_notify(G_OBJECT(m_frame), "uri");
747     WebKitWebView* webView = getViewFromFrame(m_frame);
748     if (m_frame == webkit_web_view_get_main_frame(webView))
749         g_object_notify(G_OBJECT(webView), "uri");
750 }
751
752 void FrameLoaderClient::dispatchDidNavigateWithinPage()
753 {
754     WebKitWebView* webView = getViewFromFrame(m_frame);
755     WebKitWebFrame* mainFrame = webView->priv->mainFrame;
756     WebKitWebDataSource* dataSource = webkit_web_frame_get_data_source(mainFrame);
757     bool loaderCompleted = !webkit_web_data_source_is_loading(dataSource);
758
759     if (!loaderCompleted)
760         return;
761
762     // No provisional load started, because:
763     // - It will break (no provisional data source at this point).
764     // - There's no provisional load going on anyway, the URI is being
765     //   programatically changed.
766     // FIXME: this is not ideal, but it seems safer than changing our
767     // current contract with the clients about provisional data
768     // sources not being '0' during the provisional load stage.
769     dispatchDidCommitLoad(true);
770     dispatchDidFinishLoad();
771 }
772
773 void FrameLoaderClient::dispatchDidPushStateWithinPage()
774 {
775     dispatchDidNavigateWithinPage();
776 }
777
778 void FrameLoaderClient::dispatchDidReplaceStateWithinPage()
779 {
780     dispatchDidNavigateWithinPage();
781 }
782
783 void FrameLoaderClient::dispatchDidPopStateWithinPage()
784 {
785     // No need to do anything, we already called
786     // dispatchDidNavigateWithinPage() in PushStateWithinPage().
787 }
788
789 void FrameLoaderClient::dispatchWillClose()
790 {
791     notImplemented();
792 }
793
794 void FrameLoaderClient::dispatchDidReceiveIcon()
795 {
796     if (m_loadingErrorPage)
797         return;
798
799     // IconController loads icons only for the main frame.
800     WebKitWebView* webView = getViewFromFrame(m_frame);
801     ASSERT(m_frame == webkit_web_view_get_main_frame(webView));
802
803     const char* frameURI = webkit_web_frame_get_uri(m_frame);
804     WebKitFaviconDatabase* database = webkit_get_favicon_database();
805     webkitFaviconDatabaseDispatchDidReceiveIcon(database, frameURI);
806     webkitWebViewIconLoaded(database, frameURI, webView);
807 }
808
809 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
810 {
811     if (m_loadingErrorPage)
812         return;
813
814     notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL);
815 }
816
817 void FrameLoaderClient::dispatchDidReceiveTitle(const StringWithDirection& title)
818 {
819     if (m_loadingErrorPage)
820         return;
821
822     WebKitWebFramePrivate* priv = m_frame->priv;
823     g_free(priv->title);
824     // FIXME: use direction of title.
825     priv->title = g_strdup(title.string().utf8().data());
826
827     g_signal_emit_by_name(m_frame, "title-changed", priv->title);
828     g_object_notify(G_OBJECT(m_frame), "title");
829
830     WebKitWebView* webView = getViewFromFrame(m_frame);
831     if (m_frame == webkit_web_view_get_main_frame(webView)) {
832         g_signal_emit_by_name(webView, "title-changed", m_frame, title.string().utf8().data());
833         g_object_notify(G_OBJECT(webView), "title");
834     }
835 }
836
837 void FrameLoaderClient::dispatchDidChangeIcons(WebCore::IconType)
838 {
839     notImplemented();
840 }
841
842 void FrameLoaderClient::dispatchDidCommitLoad()
843 {
844     FrameLoaderClient::dispatchDidCommitLoad(false);
845 }
846
847 void FrameLoaderClient::dispatchDidCommitLoad(bool isNavigatingWithinPage)
848 {
849     if (m_loadingErrorPage)
850         return;
851
852     /* Update the URI once first data has been received.
853      * This means the URI is valid and successfully identify the page that's going to be loaded.
854      */
855     g_object_freeze_notify(G_OBJECT(m_frame));
856
857     WebKitWebFramePrivate* priv = m_frame->priv;
858     g_free(priv->uri);
859     priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().string().utf8().data());
860     g_object_notify(G_OBJECT(m_frame), "uri");
861     if (!isNavigatingWithinPage) {
862         g_free(priv->title);
863         priv->title = 0;
864         g_object_notify(G_OBJECT(m_frame), "title");
865     }
866
867     g_signal_emit_by_name(m_frame, "load-committed");
868     notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED);
869
870     WebKitWebView* webView = getViewFromFrame(m_frame);
871     if (m_frame == webkit_web_view_get_main_frame(webView)) {
872         g_object_freeze_notify(G_OBJECT(webView));
873         g_object_notify(G_OBJECT(webView), "uri");
874         g_object_thaw_notify(G_OBJECT(webView));
875         if (!isNavigatingWithinPage)
876             g_object_notify(G_OBJECT(webView), "title");
877         g_signal_emit_by_name(webView, "load-committed", m_frame);
878     }
879
880     g_object_thaw_notify(G_OBJECT(m_frame));
881 }
882
883 void FrameLoaderClient::dispatchDidFinishDocumentLoad()
884 {
885     WebKitWebView* webView = getViewFromFrame(m_frame);
886     g_signal_emit_by_name(webView, "document-load-finished", m_frame);
887 }
888
889 void FrameLoaderClient::dispatchDidLayout(LayoutMilestones milestones)
890 {
891     if (m_loadingErrorPage)
892         return;
893
894     if (milestones & DidFirstVisuallyNonEmptyLayout)
895         notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT);
896 }
897
898 void FrameLoaderClient::dispatchShow()
899 {
900     WebKitWebView* webView = getViewFromFrame(m_frame);
901     webkit_web_view_notify_ready(webView);
902 }
903
904 void FrameLoaderClient::cancelPolicyCheck()
905 {
906     //FIXME Add support for more than one policy decision at once
907     if (m_policyDecision)
908         webkit_web_policy_decision_cancel(m_policyDecision);
909 }
910
911 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*)
912 {
913     notImplemented();
914 }
915
916 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l)
917 {
918     setTitle(l->title(), l->url());
919 }
920
921 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const
922 {
923     notImplemented();
924     return true;
925 }
926
927 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
928 {
929     notImplemented();
930     return false;
931 }
932
933 bool FrameLoaderClient::canShowMIMEType(const String& type) const
934 {
935     return (MIMETypeRegistry::canShowMIMEType(type)
936             || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type));
937 }
938
939 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const
940 {
941     notImplemented();
942     return false;
943 }
944
945 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const
946 {
947     notImplemented();
948     return String();
949 }
950
951 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader*)
952 {
953     if (m_pluginView) {
954         m_pluginView->didFinishLoading();
955         m_pluginView = 0;
956         m_hasSentResponseToPlugin = false;
957     }
958 }
959
960
961 void FrameLoaderClient::provisionalLoadStarted()
962 {
963     notImplemented();
964 }
965
966 void FrameLoaderClient::didFinishLoad() {
967     notImplemented();
968 }
969
970 void FrameLoaderClient::prepareForDataSourceReplacement() 
971 {
972     notImplemented();
973 }
974
975 void FrameLoaderClient::setTitle(const StringWithDirection& title, const KURL& url)
976 {
977     WebKitWebFramePrivate* frameData = m_frame->priv;
978     g_free(frameData->title);
979     // FIXME: use direction of title.
980     frameData->title = g_strdup(title.string().utf8().data());
981 }
982
983 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int dataLength)
984 {
985     WebKitWebView* webView = getViewFromFrame(m_frame);
986     GOwnPtr<gchar> identifierString(toString(identifier));
987     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
988
989     g_signal_emit_by_name(webResource, "content-length-received", dataLength);
990     g_signal_emit_by_name(m_frame, "resource-content-length-received", webResource, dataLength);
991     g_signal_emit_by_name(webView, "resource-content-length-received", m_frame, webResource, dataLength);
992 }
993
994 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier)
995 {
996     static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
997
998     WebKitWebView* webView = getViewFromFrame(m_frame);
999     GOwnPtr<gchar> identifierString(toString(identifier));
1000     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
1001
1002     // A NULL WebResource means the load has been interrupted, and
1003     // replaced by another one while this resource was being loaded.
1004     if (!webResource)
1005         return;
1006
1007     const char* uri = webkit_web_resource_get_uri(webResource);
1008     RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri)));
1009
1010     // If coreResource is NULL here, the resource failed to load,
1011     // unless it's the main resource.
1012     if (!coreResource && webResource != webkit_web_view_get_main_resource(webView))
1013         return;
1014
1015     if (!coreResource)
1016         coreResource = loader->mainResource();
1017
1018     webkit_web_resource_init_with_core_resource(webResource, coreResource.get());
1019
1020     g_signal_emit_by_name(webResource, "load-finished");
1021     g_signal_emit_by_name(m_frame, "resource-load-finished", webResource);
1022     g_signal_emit_by_name(webView, "resource-load-finished", m_frame, webResource);
1023 }
1024
1025 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
1026 {
1027     static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1028
1029     WebKitWebView* webView = getViewFromFrame(m_frame);
1030     GOwnPtr<gchar> identifierString(toString(identifier));
1031     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
1032
1033     // A NULL WebResource means the load has been interrupted, and
1034     // replaced by another one while this resource was being loaded.
1035     if (!webResource)
1036         return;
1037
1038     GOwnPtr<GError> webError(g_error_new_literal(g_quark_from_string(error.domain().utf8().data()),
1039                                                  error.errorCode(),
1040                                                  error.localizedDescription().utf8().data()));
1041
1042     g_signal_emit_by_name(webResource, "load-failed", webError.get());
1043     g_signal_emit_by_name(m_frame, "resource-load-failed", webResource, webError.get());
1044     g_signal_emit_by_name(webView, "resource-load-failed", m_frame, webResource, webError.get());
1045 }
1046
1047 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
1048 {
1049     notImplemented();
1050     return false;
1051 }
1052
1053 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
1054 {
1055     dispatchDidFailLoad(error);
1056 }
1057
1058 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
1059 {
1060     if (m_loadingErrorPage)
1061         return;
1062
1063     notifyStatus(m_frame, WEBKIT_LOAD_FAILED);
1064
1065     WebKitWebView* webView = getViewFromFrame(m_frame);
1066     GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()),
1067                                            error.errorCode(),
1068                                            error.localizedDescription().utf8().data());
1069     gboolean isHandled = false;
1070     g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled);
1071
1072     if (isHandled) {
1073         g_error_free(webError);
1074         return;
1075     }
1076
1077     if (!shouldFallBack(error)) {
1078         g_error_free(webError);
1079         return;
1080     }
1081
1082     m_loadingErrorPage = true;
1083
1084     String content;
1085     gchar* fileContent = 0;
1086     GOwnPtr<gchar> errorPath(g_build_filename(sharedResourcesPath().data(), "resources", "error.html", NULL));
1087     gchar* errorURI = g_filename_to_uri(errorPath.get(), 0, 0);
1088
1089     GFile* errorFile = g_file_new_for_uri(errorURI);
1090     g_free(errorURI);
1091
1092     if (!errorFile)
1093         content = makeString("<html><body>", webError->message, "</body></html>");
1094     else {
1095         gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0);
1096         if (!loaded)
1097             content = makeString("<html><body>", webError->message, "</body></html>");
1098         else
1099             content = String::format(fileContent, error.failingURL().utf8().data(), webError->message);
1100     }
1101
1102     webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data());
1103
1104     g_free(fileContent);
1105
1106     if (errorFile)
1107         g_object_unref(errorFile);
1108
1109     g_error_free(webError);
1110 }
1111
1112 void FrameLoaderClient::convertMainResourceLoadToDownload(MainResourceLoader* mainResourceLoader, const ResourceRequest& request, const ResourceResponse& response)
1113 {
1114     GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1115     WebKitWebView* view = getViewFromFrame(m_frame);
1116
1117     webkit_web_view_request_download(view, networkRequest.get(), response, mainResourceLoader->loader()->handle());
1118 }
1119
1120 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request)
1121 {
1122     return WebCore::cancelledError(request);
1123 }
1124
1125 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request)
1126 {
1127     return WebCore::blockedError(request);
1128 }
1129
1130 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1131 {
1132     return WebCore::cannotShowURLError(request);
1133 }
1134
1135 ResourceError FrameLoaderClient::interruptedForPolicyChangeError(const ResourceRequest& request)
1136 {
1137     return WebCore::interruptedForPolicyChangeError(request);
1138 }
1139
1140 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1141 {
1142     return WebCore::cannotShowMIMETypeError(response);
1143 }
1144
1145 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1146 {
1147     return WebCore::fileDoesNotExistError(response);
1148 }
1149
1150 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1151 {
1152     return WebCore::pluginWillHandleLoadError(response);
1153 }
1154
1155 bool FrameLoaderClient::shouldFallBack(const ResourceError& error)
1156 {
1157     return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD);
1158 }
1159
1160 bool FrameLoaderClient::canCachePage() const
1161 {
1162     return true;
1163 }
1164
1165 Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&)
1166 {
1167     WebKitWebView* webView = getViewFromFrame(m_frame);
1168     WebKitWebView* newWebView = 0;
1169
1170     g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView);
1171
1172     if (!newWebView)
1173         return 0;
1174
1175     WebKitWebViewPrivate* privateData = newWebView->priv;
1176     return core(privateData->mainFrame);
1177 }
1178
1179 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&)
1180 {
1181     notImplemented();
1182 }
1183
1184 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error)
1185 {
1186     if (m_pluginView) {
1187         m_pluginView->didFail(error);
1188         m_pluginView = 0;
1189         m_hasSentResponseToPlugin = false;
1190     }
1191 }
1192
1193 void FrameLoaderClient::startDownload(const ResourceRequest& request, const String& /* suggestedName */)
1194 {
1195     GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1196     WebKitWebView* view = getViewFromFrame(m_frame);
1197
1198     webkit_web_view_request_download(view, networkRequest.get());
1199 }
1200
1201 void FrameLoaderClient::updateGlobalHistory()
1202 {
1203     notImplemented();
1204 }
1205
1206 void FrameLoaderClient::updateGlobalHistoryRedirectLinks()
1207 {
1208     notImplemented();
1209 }
1210
1211 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1212 {
1213 }
1214
1215 static void postCommitFrameViewSetup(WebKitWebFrame *frame)
1216 {
1217     WebKitWebView* containingWindow = getViewFromFrame(frame);
1218     webkit_web_view_clear_resources(containingWindow);
1219
1220     // Invalidate the viewport attributes - they will only be valid
1221     // again if the page we're beginning to load now has an
1222     // appropriate viewport meta tag.
1223     WebKitWebViewPrivate* priv = containingWindow->priv;
1224     priv->viewportAttributes->priv->isValid = FALSE;
1225     g_object_notify(G_OBJECT(priv->viewportAttributes.get()), "valid");
1226
1227     if (priv->currentMenu) {
1228         gtk_widget_destroy(GTK_WIDGET(priv->currentMenu));
1229         priv->currentMenu = 0;
1230     }
1231
1232     // Do not allow click counting between main frame loads.
1233     priv->clickCounter.reset();
1234 }
1235
1236 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1237 {
1238     ASSERT(cachedFrame->view());
1239
1240     Frame* frame = core(m_frame);
1241     if (frame != frame->page()->mainFrame())
1242         return;
1243
1244     postCommitFrameViewSetup(m_frame);
1245 }
1246
1247 void FrameLoaderClient::transitionToCommittedForNewPage()
1248 {
1249     WebKitWebView* containingWindow = getViewFromFrame(m_frame);
1250     GtkAllocation allocation;
1251 #if GTK_CHECK_VERSION(2, 18, 0)
1252     gtk_widget_get_allocation(GTK_WIDGET(containingWindow), &allocation);
1253 #else
1254     allocation = GTK_WIDGET(containingWindow)->allocation;
1255 #endif
1256     IntSize size = IntSize(allocation.width, allocation.height);
1257     bool transparent = webkit_web_view_get_transparent(containingWindow);
1258     Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white;
1259     Frame* frame = core(m_frame);
1260     ASSERT(frame);
1261
1262     frame->createView(size, backgroundColor, transparent);
1263
1264     // We need to do further manipulation on the FrameView if it was the mainFrame
1265     if (frame != frame->page()->mainFrame())
1266         return;
1267
1268     postCommitFrameViewSetup(m_frame);
1269 }
1270
1271 void FrameLoaderClient::didSaveToPageCache()
1272 {
1273 }
1274
1275 void FrameLoaderClient::didRestoreFromPageCache()
1276 {
1277 }
1278
1279 void FrameLoaderClient::dispatchDidBecomeFrameset(bool)
1280 {
1281 }
1282
1283 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext()
1284 {
1285     return FrameNetworkingContextGtk::create(core(m_frame));
1286 }
1287
1288 }