2011-02-04 Joone Hur <joone.hur@collabora.co.uk>
[WebKit.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  *
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.
14  *
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.
19  *
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
23  */
24
25 #include "config.h"
26 #include "FrameLoaderClientGtk.h"
27
28 #include "ArchiveResource.h"
29 #include "CachedFrame.h"
30 #include "Color.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"
39 #include "GOwnPtr.h"
40 #include "GRefPtr.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"
50 #include "Language.h"
51 #include "MIMETypeRegistry.h"
52 #include "MouseEvent.h"
53 #include "NotImplemented.h"
54 #include "Page.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"
61 #include "Settings.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>
84 #include <gio/gio.h>
85 #include <glib.h>
86 #include <glib/gi18n-lib.h>
87 #include <stdio.h>
88 #include <wtf/text/CString.h>
89 #include <wtf/text/StringConcatenate.h>
90
91 using namespace WebCore;
92
93 namespace WebKit {
94
95 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
96     : m_frame(frame)
97     , m_policyDecision(0)
98     , m_loadingErrorPage(false)
99     , m_pluginView(0)
100     , m_hasSentResponseToPlugin(false)
101     , m_hasRepresentation(false)
102 {
103     ASSERT(m_frame);
104 }
105
106 FrameLoaderClient::~FrameLoaderClient()
107 {
108     if (m_policyDecision)
109         g_object_unref(m_policyDecision);
110 }
111
112 static void initializeDomainsList(HashSet<String>& googleDomains)
113 {
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");
180 }
181
182 static bool isGoogleDomain(String host)
183 {
184     DEFINE_STATIC_LOCAL(HashSet<String>, googleDomains, ());
185     DEFINE_STATIC_LOCAL(Vector<String>, otherGoogleDomains, ());
186
187     if (googleDomains.isEmpty()) {
188         otherGoogleDomains.append("gmail.com");
189         otherGoogleDomains.append("youtube.com");
190         otherGoogleDomains.append("gstatic.com");
191         otherGoogleDomains.append("ytimg.com");
192
193         initializeDomainsList(googleDomains);
194     }
195
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."))))
199         return true;
200
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)))
204             return true;
205     }
206
207     return false;
208 }
209
210 String FrameLoaderClient::userAgent(const KURL& url)
211 {
212     WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame));
213
214     gboolean useQuirks;
215     g_object_get(settings, "enable-site-specific-quirks", &useQuirks, NULL);
216
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();
221
222     return String::fromUTF8(webkit_web_settings_get_user_agent(settings));
223 }
224
225 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
226 {
227     frame->priv->loadStatus = loadStatus;
228     g_object_notify(G_OBJECT(frame), "load-status");
229
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");
234     }
235 }
236
237 static void loadDone(WebKitWebFrame* frame, bool didSucceed)
238 {
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);
242 }
243
244 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
245 {
246     RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData);
247
248     GRefPtr<WebKitWebDataSource> webDataSource(adoptGRef(kitNew(loader.get())));
249     loader->setDataSource(webDataSource.get());
250
251     return loader.release();
252 }
253
254 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>)
255 {
256     // FIXME: This is surely too simple
257     ASSERT(policyFunction);
258     if (!policyFunction)
259         return;
260     (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
261 }
262
263 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
264 {
265     if (!m_pluginView) {
266         ASSERT(loader->frame());
267         loader->commitData(data, length);
268
269         Frame* coreFrame = loader->frame();
270         if (coreFrame && coreFrame->document()->isMediaDocument())
271             loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response()));
272     }
273
274     if (m_pluginView) {
275         if (!m_hasSentResponseToPlugin) {
276             m_pluginView->didReceiveResponse(loader->response());
277             m_hasSentResponseToPlugin = true;
278         }
279
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.
283         if (!m_pluginView)
284             return;
285
286         m_pluginView->didReceiveData(data, length);
287     }
288 }
289
290 bool
291 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long  identifier)
292 {
293     notImplemented();
294     return false;
295 }
296
297 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
298 {
299     notImplemented();
300 }
301
302 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
303 {
304     notImplemented();
305 }
306
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)
310 {
311     return g_strdup_printf("%ld", identifier);
312 }
313
314 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
315 {
316     GRefPtr<WebKitNetworkResponse> networkResponse(0);
317
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);
322     else
323         networkResponse = adoptGRef(kitNew(redirectResponse));
324
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)));
329
330     if (!redirectResponse.isNull()) {
331         // This is a redirect, so we need to update the WebResource's knowledge
332         // of the URI.
333         g_free(webResource->priv->uri);
334         webResource->priv->uri = g_strdup(request.url().string().utf8().data());
335     }
336     
337     g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get());
338
339     // Feed any changes back into the ResourceRequest object.
340     SoupMessage* message = webkit_network_request_get_message(networkRequest.get());
341     if (!message) {
342         request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get()))));
343         return;
344     }
345
346     request.updateFromSoupMessage(message);
347 }
348
349 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request)
350 {
351     GOwnPtr<gchar> identifierString(toString(identifier));
352
353     WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0));
354
355     if (loader == loader->frameLoader()->provisionalDocumentLoader()
356         && loader->frameLoader()->isLoadingMainFrame()) {
357         webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
358         return;
359     }
360
361     webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
362 }
363
364 void FrameLoaderClient::postProgressStartedNotification()
365 {
366     WebKitWebView* webView = getViewFromFrame(m_frame);
367     g_signal_emit_by_name(webView, "load-started", m_frame);
368
369     g_object_notify(G_OBJECT(webView), "progress");
370 }
371
372 void FrameLoaderClient::postProgressEstimateChangedNotification()
373 {
374     WebKitWebView* webView = getViewFromFrame(m_frame);
375     Page* corePage = core(webView);
376
377     g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100));
378
379     g_object_notify(G_OBJECT(webView), "progress");
380 }
381
382 void FrameLoaderClient::postProgressFinishedNotification()
383 {
384     WebKitWebView* webView = getViewFromFrame(m_frame);
385     WebKitWebViewPrivate* privateData = webView->priv;
386
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);
391 }
392
393 void FrameLoaderClient::frameLoaderDestroyed()
394 {
395     webkit_web_frame_core_frame_gone(m_frame);
396     g_object_unref(m_frame);
397     m_frame = 0;
398     delete this;
399 }
400
401 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long, const ResourceResponse& response)
402 {
403     // Update our knowledge of request soup flags - some are only set
404     // after the request is done.
405     loader->request().setSoupMessageFlags(response.soupMessageFlags());
406
407     m_response = response;
408 }
409
410 void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String& mimeType, const ResourceRequest& resourceRequest)
411 {
412     ASSERT(policyFunction);
413     if (!policyFunction)
414         return;
415
416     if (resourceRequest.isNull()) {
417         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
418         return;
419     }
420
421     WebKitWebView* page = getViewFromFrame(m_frame);
422     GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
423
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;
428
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);
431
432     if (isHandled)
433         return;
434
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);
440             return;
441         }
442     }
443
444     if (canShowMIMEType(mimeType))
445         webkit_web_policy_decision_use(policyDecision);
446     else
447         webkit_web_policy_decision_ignore(policyDecision);
448 }
449
450 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame)
451 {
452     gint button = -1;
453
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;
460     }
461
462     gint modifierFlags = 0;
463     UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event));
464     if (keyStateEvent) {
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;
473     }
474
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(),
478                                                      "button", button,
479                                                      "modifier-state", modifierFlags,
480                                                      "target-frame", targetFrame,
481                                                      NULL));
482 }
483
484 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName)
485 {
486     ASSERT(policyFunction);
487     if (!policyFunction)
488         return;
489
490     if (resourceRequest.isNull()) {
491         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
492         return;
493     }
494
495     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
496
497     if (m_policyDecision)
498         g_object_unref(m_policyDecision);
499     m_policyDecision = policyDecision;
500
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;
505
506     g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
507
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
510     if (!isHandled)
511         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
512 }
513
514 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>)
515 {
516     ASSERT(policyFunction);
517     if (!policyFunction)
518         return;
519
520     if (resourceRequest.isNull()) {
521         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
522         return;
523     }
524
525     WebKitWebView* webView = getViewFromFrame(m_frame);
526     GRefPtr<WebKitNetworkRequest> request(adoptGRef(kitNew(resourceRequest)));
527     WebKitNavigationResponse response;
528     /*
529      * We still support the deprecated navigation-requested signal, if the
530      * application doesn't ignore the navigation then the new signal is
531      * emitted.
532      * navigation-policy-decision-requested must be emitted after
533      * navigation-requested as the policy decision can be async.
534      */
535     g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response);
536
537     if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
538         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
539         return;
540     }
541
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;
546
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);
550
551     // FIXME Implement default behavior when we can query the backend what protocols it supports
552     if (!isHandled)
553         webkit_web_policy_decision_use(m_policyDecision);
554 }
555
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)
557 {
558     /* Check if we want to embed a GtkWidget, fallback to plugins later */
559     CString urlString = url.string().utf8();
560     CString mimeTypeString = mimeType.utf8();
561
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()));
568     }
569
570     GtkWidget* gtkWidget = 0;
571     g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget",
572                           mimeTypeString.data(), urlString.data(), hash.get(), &gtkWidget);
573     if (gtkWidget)
574         return adoptRef(new GtkPluginWidget(gtkWidget));
575
576     RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
577
578     if (pluginView->status() == PluginStatusLoadedSuccessfully)
579         return pluginView;
580
581     return 0;
582 }
583
584 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
585                                                  const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
586 {
587     ASSERT(m_frame);
588     Frame* parentFrame = core(m_frame);
589     WebKitWebView* webView = getViewFromFrame(m_frame);
590     WebCore::Page* page = core(webView);
591     ASSERT(page == parentFrame->page());
592
593     WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
594     WebKitWebFramePrivate* framePrivate = kitFrame->priv;
595     framePrivate->webView = webView;
596
597     RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame));
598     framePrivate->coreFrame = childFrame.get();
599
600     childFrame->tree()->setName(name);
601     parentFrame->tree()->appendChild(childFrame);
602     childFrame->init();
603
604     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
605     if (!childFrame->page())
606         return 0;
607
608     g_signal_emit_by_name(webView, "frame-created", kitFrame);
609
610     childFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
611
612     // The frame's onload handler may have removed it from the document.
613     if (!childFrame->tree()->parent())
614         return 0;
615
616     return childFrame.release();
617 }
618
619 void FrameLoaderClient::didTransferChildFrameToNewDocument(WebCore::Page*)
620 {
621     ASSERT(m_frame);
622
623     // Update the frame's webview to the new parent's webview.
624     Frame* coreFrame = core(m_frame);
625     WebKitWebView* webView = getViewFromFrame(m_frame);
626
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;
632
633     ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page());
634 }
635
636 void FrameLoaderClient::transferLoadingResourceFromPage(unsigned long identifier, WebCore::DocumentLoader* docLoader, const WebCore::ResourceRequest& request, WebCore::Page* oldPage)
637 {
638     ASSERT(oldPage != core(m_frame)->page());
639
640     GOwnPtr<gchar> identifierString(toString(identifier));
641     ASSERT(!webkit_web_view_get_resource(getViewFromFrame(m_frame), identifierString.get()));
642
643     assignIdentifierToInitialRequest(identifier, docLoader, request);
644
645     webkit_web_view_remove_resource(kit(oldPage), identifierString.get());
646 }
647
648 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
649 {
650     ASSERT(!m_pluginView);
651     m_pluginView = static_cast<PluginView*>(pluginWidget);
652     m_hasSentResponseToPlugin = false;
653 }
654
655 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues)
656 {
657     return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false);
658 }
659
660 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
661 {
662     return FrameLoader::defaultObjectContentType(url, mimeType);
663 }
664
665 String FrameLoaderClient::overrideMediaType() const
666 {
667     notImplemented();
668     return String();
669 }
670
671 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
672 {
673     if (world != mainThreadNormalWorld())
674         return;
675
676     // Is this obsolete now?
677     g_signal_emit_by_name(m_frame, "cleared");
678
679     Frame* coreFrame = core(m_frame);
680     ASSERT(coreFrame);
681
682     Settings* settings = coreFrame->settings();
683     if (!settings || !settings->isJavaScriptEnabled())
684         return;
685
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);
691
692     WebKitWebView* webView = getViewFromFrame(m_frame);
693     g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject);
694
695     // TODO: Re-attach debug clients if present.
696     // The Win port has an example of how we might do this.
697 }
698
699 void FrameLoaderClient::documentElementAvailable()
700 {
701 }
702
703 void FrameLoaderClient::didPerformFirstNavigation() const
704 {
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);
709 }
710
711 void FrameLoaderClient::registerForIconNotification(bool shouldRegister)
712 {
713     notImplemented();
714 }
715
716 void FrameLoaderClient::setMainFrameDocumentReady(bool ready)
717 {
718     if (!ready)
719         DOMObjectCache::clearByFrame(core(m_frame));
720 }
721
722 bool FrameLoaderClient::hasWebView() const
723 {
724     return getViewFromFrame(m_frame);
725 }
726
727 void FrameLoaderClient::dispatchDidFinishLoad()
728 {
729     if (m_loadingErrorPage) {
730         m_loadingErrorPage = false;
731         return;
732     }
733
734     loadDone(m_frame, true);
735 }
736
737 void FrameLoaderClient::frameLoadCompleted()
738 {
739     notImplemented();
740 }
741
742 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
743 {
744     notImplemented();
745 }
746
747 void FrameLoaderClient::restoreViewState()
748 {
749     notImplemented();
750 }
751
752 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
753 {
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.
757     return item != 0;
758 }
759
760 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
761 {
762 }
763
764 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
765 {
766 }
767
768 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const
769 {
770 }
771
772 void FrameLoaderClient::didDisplayInsecureContent()
773 {
774     notImplemented();
775 }
776
777 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&)
778 {
779     notImplemented();
780 }
781
782 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*)
783 {
784     m_hasRepresentation = true;
785 }
786
787 void FrameLoaderClient::forceLayout()
788 {
789     FrameView* view = core(m_frame)->view();
790     if (view)
791         view->forceLayout(true);
792 }
793
794 void FrameLoaderClient::forceLayoutForNonHTML()
795 {
796     notImplemented();
797 }
798
799 void FrameLoaderClient::setCopiesOnScroll()
800 {
801     notImplemented();
802 }
803
804 void FrameLoaderClient::detachedFromParent2()
805 {
806     notImplemented();
807 }
808
809 void FrameLoaderClient::detachedFromParent3()
810 {
811     notImplemented();
812 }
813
814 void FrameLoaderClient::dispatchDidHandleOnloadEvents()
815 {
816     g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame);
817 }
818
819 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
820 {
821     notImplemented();
822 }
823
824 void FrameLoaderClient::dispatchDidCancelClientRedirect()
825 {
826     notImplemented();
827 }
828
829 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double)
830 {
831     notImplemented();
832 }
833
834 void FrameLoaderClient::dispatchDidChangeLocationWithinPage()
835 {
836     WebKitWebFramePrivate* priv = m_frame->priv;
837     g_free(priv->uri);
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");
843 }
844
845 void FrameLoaderClient::dispatchDidPushStateWithinPage()
846 {
847     notImplemented();
848 }
849
850 void FrameLoaderClient::dispatchDidReplaceStateWithinPage()
851 {
852     notImplemented();
853 }
854
855 void FrameLoaderClient::dispatchDidPopStateWithinPage()
856 {
857     notImplemented();
858 }
859
860 void FrameLoaderClient::dispatchWillClose()
861 {
862     notImplemented();
863 }
864
865 void FrameLoaderClient::dispatchDidReceiveIcon()
866 {
867     if (m_loadingErrorPage)
868         return;
869
870     WebKitWebView* webView = getViewFromFrame(m_frame);
871
872     // Avoid reporting favicons for non-main frames.
873     if (m_frame != webkit_web_view_get_main_frame(webView))
874         return;
875
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));
878 }
879
880 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
881 {
882     if (m_loadingErrorPage)
883         return;
884
885     notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL);
886 }
887
888 void FrameLoaderClient::dispatchDidReceiveTitle(const String& title)
889 {
890     if (m_loadingErrorPage)
891         return;
892
893     WebKitWebFramePrivate* priv = m_frame->priv;
894     g_free(priv->title);
895     priv->title = g_strdup(title.utf8().data());
896
897     g_signal_emit_by_name(m_frame, "title-changed", priv->title);
898     g_object_notify(G_OBJECT(m_frame), "title");
899
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");
904     }
905 }
906
907 void FrameLoaderClient::dispatchDidChangeIcons()
908 {
909     notImplemented();
910 }
911
912 void FrameLoaderClient::dispatchDidCommitLoad()
913 {
914     if (m_loadingErrorPage)
915         return;
916
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.
919      */
920     g_object_freeze_notify(G_OBJECT(m_frame));
921
922     WebKitWebFramePrivate* priv = m_frame->priv;
923     g_free(priv->uri);
924     priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().prettyURL().utf8().data());
925     g_free(priv->title);
926     priv->title = NULL;
927     g_object_notify(G_OBJECT(m_frame), "uri");
928     g_object_notify(G_OBJECT(m_frame), "title");
929
930     g_signal_emit_by_name(m_frame, "load-committed");
931     notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED);
932
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);
940     }
941
942     g_object_thaw_notify(G_OBJECT(m_frame));
943 }
944
945 void FrameLoaderClient::dispatchDidFinishDocumentLoad()
946 {
947     WebKitWebView* webView = getViewFromFrame(m_frame);
948     g_signal_emit_by_name(webView, "document-load-finished", m_frame);
949 }
950
951 void FrameLoaderClient::dispatchDidFirstLayout()
952 {
953     notImplemented();
954 }
955
956 void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
957 {
958     if (m_loadingErrorPage)
959         return;
960
961     notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT);
962 }
963
964 void FrameLoaderClient::dispatchShow()
965 {
966     WebKitWebView* webView = getViewFromFrame(m_frame);
967     webkit_web_view_notify_ready(webView);
968 }
969
970 void FrameLoaderClient::cancelPolicyCheck()
971 {
972     //FIXME Add support for more than one policy decision at once
973     if (m_policyDecision)
974         webkit_web_policy_decision_cancel(m_policyDecision);
975 }
976
977 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*)
978 {
979     notImplemented();
980 }
981
982 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*)
983 {
984     m_hasRepresentation = true;
985 }
986
987 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*)
988 {
989     notImplemented();
990 }
991
992 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l)
993 {
994     setTitle(l->title(), l->url());
995 }
996
997 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const
998 {
999     notImplemented();
1000     return true;
1001 }
1002
1003 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
1004 {
1005     notImplemented();
1006     return false;
1007 }
1008
1009 bool FrameLoaderClient::canShowMIMEType(const String& type) const
1010 {
1011     return (MIMETypeRegistry::isSupportedImageMIMEType(type)
1012             || MIMETypeRegistry::isSupportedNonImageMIMEType(type)
1013             || MIMETypeRegistry::isSupportedMediaMIMEType(type)
1014             || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type));
1015 }
1016
1017 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const
1018 {
1019     notImplemented();
1020     return false;
1021 }
1022
1023 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const
1024 {
1025     notImplemented();
1026     return String();
1027 }
1028
1029 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader)
1030 {
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->frameLoader()->writer()->setEncoding("", false);
1036     } else {
1037         m_pluginView->didFinishLoading();
1038         m_pluginView = 0;
1039         m_hasSentResponseToPlugin = false;
1040     }
1041 }
1042
1043
1044 void FrameLoaderClient::provisionalLoadStarted()
1045 {
1046     notImplemented();
1047 }
1048
1049 void FrameLoaderClient::didFinishLoad() {
1050     notImplemented();
1051 }
1052
1053 void FrameLoaderClient::prepareForDataSourceReplacement() 
1054 {
1055     notImplemented();
1056 }
1057
1058 void FrameLoaderClient::setTitle(const String& title, const KURL& url)
1059 {
1060     WebKitWebFramePrivate* frameData = m_frame->priv;
1061     g_free(frameData->title);
1062     frameData->title = g_strdup(title.utf8().data());
1063 }
1064
1065 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived)
1066 {
1067     notImplemented();
1068 }
1069
1070 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier)
1071 {
1072     static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1073
1074     WebKitWebView* webView = getViewFromFrame(m_frame);
1075     GOwnPtr<gchar> identifierString(toString(identifier));
1076     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
1077
1078     // A NULL WebResource means the load has been interrupted, and
1079     // replaced by another one while this resource was being loaded.
1080     if (!webResource)
1081         return;
1082
1083     const char* uri = webkit_web_resource_get_uri(webResource);
1084     RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri)));
1085
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))
1089         return;
1090
1091     if (!coreResource)
1092         coreResource = loader->mainResource();
1093
1094     webkit_web_resource_init_with_core_resource(webResource, coreResource.get());
1095
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'
1099     // signal.
1100     notImplemented();
1101 }
1102
1103 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
1104 {
1105     static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1106
1107     // FIXME: This function should notify the application that the resource failed
1108     // loading, maybe a 'load-error' signal in the WebKitWebResource object.
1109     notImplemented();
1110 }
1111
1112 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
1113 {
1114     notImplemented();
1115     return false;
1116 }
1117
1118 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
1119 {
1120     dispatchDidFailLoad(error);
1121 }
1122
1123 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
1124 {
1125     if (m_loadingErrorPage)
1126         return;
1127
1128     notifyStatus(m_frame, WEBKIT_LOAD_FAILED);
1129
1130     WebKitWebView* webView = getViewFromFrame(m_frame);
1131     GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()),
1132                                            error.errorCode(),
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);
1136
1137     if (isHandled) {
1138         g_error_free(webError);
1139         return;
1140     }
1141
1142     if (!shouldFallBack(error)) {
1143         g_error_free(webError);
1144         return;
1145     }
1146
1147     m_loadingErrorPage = true;
1148
1149     String content;
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);
1153     g_free(errorURI);
1154
1155     if (!errorFile)
1156         content = makeString("<html><body>", webError->message, "</body></html>");
1157     else {
1158         gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0);
1159         if (!loaded)
1160             content = makeString("<html><body>", webError->message, "</body></html>");
1161         else
1162             content = String::format(fileContent, error.failingURL().utf8().data(), webError->message);
1163     }
1164
1165     webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data());
1166
1167     g_free(fileContent);
1168
1169     if (errorFile)
1170         g_object_unref(errorFile);
1171
1172     g_error_free(webError);
1173 }
1174
1175 void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
1176 {
1177     GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1178     WebKitWebView* view = getViewFromFrame(m_frame);
1179
1180     webkit_web_view_request_download(view, networkRequest.get(), response, handle);
1181 }
1182
1183 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request)
1184 {
1185     return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED,
1186                          request.url().string(), _("Load request cancelled"));
1187 }
1188
1189 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request)
1190 {
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"));
1193 }
1194
1195 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1196 {
1197     return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL,
1198                          request.url().string(), _("URL cannot be shown"));
1199 }
1200
1201 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
1202 {
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"));
1205 }
1206
1207 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1208 {
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"));
1211 }
1212
1213 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1214 {
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"));
1217 }
1218
1219 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1220 {
1221     return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD,
1222                          response.url().string(), _("Plugin will handle load"));
1223 }
1224
1225 bool FrameLoaderClient::shouldFallBack(const ResourceError& error)
1226 {
1227     return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD);
1228 }
1229
1230 bool FrameLoaderClient::canCachePage() const
1231 {
1232     return true;
1233 }
1234
1235 Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&)
1236 {
1237     WebKitWebView* webView = getViewFromFrame(m_frame);
1238     WebKitWebView* newWebView = 0;
1239
1240     g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView);
1241
1242     if (!newWebView)
1243         return 0;
1244
1245     WebKitWebViewPrivate* privateData = newWebView->priv;
1246     return core(privateData->mainFrame);
1247 }
1248
1249 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&)
1250 {
1251     notImplemented();
1252 }
1253
1254 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error)
1255 {
1256     if (m_pluginView) {
1257         m_pluginView->didFail(error);
1258         m_pluginView = 0;
1259         m_hasSentResponseToPlugin = false;
1260     }
1261 }
1262
1263 void FrameLoaderClient::startDownload(const ResourceRequest& request)
1264 {
1265     GRefPtr<WebKitNetworkRequest> networkRequest(adoptGRef(kitNew(request)));
1266     WebKitWebView* view = getViewFromFrame(m_frame);
1267
1268     webkit_web_view_request_download(view, networkRequest.get());
1269 }
1270
1271 void FrameLoaderClient::updateGlobalHistory()
1272 {
1273     notImplemented();
1274 }
1275
1276 void FrameLoaderClient::updateGlobalHistoryRedirectLinks()
1277 {
1278     notImplemented();
1279 }
1280
1281 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1282 {
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);
1289 }
1290
1291 static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues)
1292 {
1293     WebKitWebView* containingWindow = getViewFromFrame(frame);
1294     webkit_web_view_clear_resources(containingWindow);
1295
1296     WebKitWebViewPrivate* priv = containingWindow->priv;
1297     view->setGtkAdjustments(priv->horizontalAdjustment.get(), priv->verticalAdjustment.get(), resetValues);
1298
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");
1304
1305     if (priv->currentMenu) {
1306         gtk_widget_destroy(GTK_WIDGET(priv->currentMenu));
1307         priv->currentMenu = 0;
1308     }
1309
1310     // Do not allow click counting between main frame loads.
1311     priv->previousClickTime = 0;
1312 }
1313
1314 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1315 {
1316     ASSERT(cachedFrame->view());
1317
1318     Frame* frame = core(m_frame);
1319     if (frame != frame->page()->mainFrame())
1320         return;
1321
1322     postCommitFrameViewSetup(m_frame, cachedFrame->view(), false);
1323 }
1324
1325 void FrameLoaderClient::transitionToCommittedForNewPage()
1326 {
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);
1331 #else
1332     allocation = GTK_WIDGET(containingWindow)->allocation;
1333 #endif
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);
1338     ASSERT(frame);
1339
1340     frame->createView(size, backgroundColor, transparent, IntSize(), false);
1341
1342     // We need to do further manipulation on the FrameView if it was the mainFrame
1343     if (frame != frame->page()->mainFrame())
1344         return;
1345
1346     postCommitFrameViewSetup(m_frame, frame->view(), true);
1347 }
1348
1349 void FrameLoaderClient::didSaveToPageCache()
1350 {
1351 }
1352
1353 void FrameLoaderClient::didRestoreFromPageCache()
1354 {
1355 }
1356
1357 void FrameLoaderClient::dispatchDidBecomeFrameset(bool)
1358 {
1359 }
1360
1361 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext()
1362 {
1363     return FrameNetworkingContextGtk::create(core(m_frame));
1364 }
1365
1366 }