5302257d2cb00c4b27298a4ce6e5d4179e75a3e7
[WebKit-https.git] / 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 {
102     ASSERT(m_frame);
103 }
104
105 FrameLoaderClient::~FrameLoaderClient()
106 {
107     if (m_policyDecision)
108         g_object_unref(m_policyDecision);
109 }
110
111 static void initializeDomainsList(HashSet<String>& googleDomains)
112 {
113     // Google search domains.
114     googleDomains.add("biz");
115     googleDomains.add("com");
116     googleDomains.add("net");
117     googleDomains.add("org");
118     googleDomains.add("ae");
119     googleDomains.add("ag");
120     googleDomains.add("am");
121     googleDomains.add("at");
122     googleDomains.add("az");
123     googleDomains.add("be");
124     googleDomains.add("bi");
125     googleDomains.add("ca");
126     googleDomains.add("cc");
127     googleDomains.add("cd");
128     googleDomains.add("cg");
129     googleDomains.add("ch");
130     googleDomains.add("cl");
131     googleDomains.add("com.br");
132     googleDomains.add("co.uk");
133     googleDomains.add("co.kr");
134     googleDomains.add("co.jp");
135     googleDomains.add("de");
136     googleDomains.add("dj");
137     googleDomains.add("dk");
138     googleDomains.add("es");
139     googleDomains.add("fi");
140     googleDomains.add("fm");
141     googleDomains.add("fr");
142     googleDomains.add("gg");
143     googleDomains.add("gl");
144     googleDomains.add("gm");
145     googleDomains.add("gs");
146     googleDomains.add("hn");
147     googleDomains.add("hu");
148     googleDomains.add("ie");
149     googleDomains.add("it");
150     googleDomains.add("je");
151     googleDomains.add("kz");
152     googleDomains.add("li");
153     googleDomains.add("lt");
154     googleDomains.add("lu");
155     googleDomains.add("lv");
156     googleDomains.add("ma");
157     googleDomains.add("ms");
158     googleDomains.add("mu");
159     googleDomains.add("mw");
160     googleDomains.add("nl");
161     googleDomains.add("no");
162     googleDomains.add("nu");
163     googleDomains.add("pl");
164     googleDomains.add("pn");
165     googleDomains.add("pt");
166     googleDomains.add("ru");
167     googleDomains.add("rw");
168     googleDomains.add("sh");
169     googleDomains.add("sk");
170     googleDomains.add("sm");
171     googleDomains.add("st");
172     googleDomains.add("td");
173     googleDomains.add("tk");
174     googleDomains.add("tp");
175     googleDomains.add("tv");
176     googleDomains.add("us");
177     googleDomains.add("uz");
178     googleDomains.add("ws");
179 }
180
181 static bool isGoogleDomain(String host)
182 {
183     DEFINE_STATIC_LOCAL(HashSet<String>, googleDomains, ());
184     DEFINE_STATIC_LOCAL(Vector<String>, otherGoogleDomains, ());
185
186     if (googleDomains.isEmpty()) {
187         otherGoogleDomains.append("gmail.com");
188         otherGoogleDomains.append("youtube.com");
189         otherGoogleDomains.append("gstatic.com");
190         otherGoogleDomains.append("ytimg.com");
191
192         initializeDomainsList(googleDomains);
193     }
194
195     // First check if this is one of the various google.com international domains.
196     int position = host.find(".google.");
197     if (position > 0 && googleDomains.contains(host.substring(position + sizeof(".google."))))
198         return true;
199
200     // Then we check the possibility of it being one of the other, .com-only google domains.
201     for (unsigned int i = 0; i < otherGoogleDomains.size(); i++) {
202         if (host.endsWith(otherGoogleDomains.at(i)))
203             return true;
204     }
205
206     return false;
207 }
208
209 String FrameLoaderClient::userAgent(const KURL& url)
210 {
211     WebKitWebSettings* settings = webkit_web_view_get_settings(getViewFromFrame(m_frame));
212
213     gboolean useQuirks;
214     g_object_get(settings, "enable-site-specific-quirks", &useQuirks, NULL);
215
216     // For Google domains, drop the browser's custom User Agent string, and use the standard
217     // WebKit/Safari one, so they don't give us a broken experience.
218     if (useQuirks && isGoogleDomain(url.host()))
219         return webkitUserAgent();
220
221     return String::fromUTF8(webkit_web_settings_get_user_agent(settings));
222 }
223
224 static void notifyStatus(WebKitWebFrame* frame, WebKitLoadStatus loadStatus)
225 {
226     frame->priv->loadStatus = loadStatus;
227     g_object_notify(G_OBJECT(frame), "load-status");
228
229     WebKitWebView* webView = getViewFromFrame(frame);
230     if (frame == webkit_web_view_get_main_frame(webView)) {
231         webView->priv->loadStatus = loadStatus;
232         g_object_notify(G_OBJECT(webView), "load-status");
233     }
234 }
235
236 static void loadDone(WebKitWebFrame* frame, bool didSucceed)
237 {
238     // FIXME: load-done is deprecated. Please remove when signal's been removed.
239     g_signal_emit_by_name(frame, "load-done", didSucceed);
240     notifyStatus(frame, WEBKIT_LOAD_FINISHED);
241 }
242
243 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
244 {
245     RefPtr<WebKit::DocumentLoader> loader = WebKit::DocumentLoader::create(request, substituteData);
246
247     PlatformRefPtr<WebKitWebDataSource> webDataSource(adoptPlatformRef(kitNew(loader.get())));
248     loader->setDataSource(webDataSource.get());
249
250     return loader.release();
251 }
252
253 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>)
254 {
255     // FIXME: This is surely too simple
256     ASSERT(policyFunction);
257     if (!policyFunction)
258         return;
259     (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
260 }
261
262 void FrameLoaderClient::committedLoad(WebCore::DocumentLoader* loader, const char* data, int length)
263 {
264     if (!m_pluginView) {
265         ASSERT(loader->frame());
266         loader->commitData(data, length);
267
268         Frame* coreFrame = loader->frame();
269         if (coreFrame && coreFrame->document()->isMediaDocument())
270             loader->cancelMainResourceLoad(coreFrame->loader()->client()->pluginWillHandleLoadError(loader->response()));
271     }
272
273     if (m_pluginView) {
274         if (!m_hasSentResponseToPlugin) {
275             m_pluginView->didReceiveResponse(loader->response());
276             m_hasSentResponseToPlugin = true;
277         }
278
279         // FIXME: We may want to investigate refactoring our plugin loading
280         // code to be similar to mac's.
281         // Also, see http://trac.webkit.org/changeset/24118.
282         if (!m_pluginView)
283             return;
284
285         m_pluginView->didReceiveData(data, length);
286     }
287 }
288
289 bool
290 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long  identifier)
291 {
292     notImplemented();
293     return false;
294 }
295
296 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
297 {
298     notImplemented();
299 }
300
301 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
302 {
303     notImplemented();
304 }
305
306 // We convert this to string because it's easier to use strings as
307 // keys in a GHashTable.
308 static char* toString(unsigned long identifier)
309 {
310     return g_strdup_printf("%ld", identifier);
311 }
312
313 void FrameLoaderClient::dispatchWillSendRequest(WebCore::DocumentLoader* loader, unsigned long identifier, ResourceRequest& request, const ResourceResponse& redirectResponse)
314 {
315     PlatformRefPtr<WebKitNetworkResponse> networkResponse(0);
316
317     // We are adding one more resource to the load, or maybe we are
318     // just redirecting a load.
319     if (redirectResponse.isNull())
320         static_cast<WebKit::DocumentLoader*>(loader)->increaseLoadCount(identifier);
321     else
322         networkResponse = adoptPlatformRef(kitNew(redirectResponse));
323
324     WebKitWebView* webView = getViewFromFrame(m_frame);
325     GOwnPtr<gchar> identifierString(toString(identifier));
326     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
327     PlatformRefPtr<WebKitNetworkRequest> networkRequest(adoptPlatformRef(kitNew(request)));
328
329     if (!redirectResponse.isNull()) {
330         // This is a redirect, so we need to update the WebResource's knowledge
331         // of the URI.
332         g_free(webResource->priv->uri);
333         webResource->priv->uri = g_strdup(request.url().string().utf8().data());
334     }
335     
336     g_signal_emit_by_name(webView, "resource-request-starting", m_frame, webResource, networkRequest.get(), networkResponse.get());
337
338     // Feed any changes back into the ResourceRequest object.
339     SoupMessage* message = webkit_network_request_get_message(networkRequest.get());
340     if (!message) {
341         request.setURL(KURL(KURL(), String::fromUTF8(webkit_network_request_get_uri(networkRequest.get()))));
342         return;
343     }
344
345     request.updateFromSoupMessage(message);
346 }
347
348 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, WebCore::DocumentLoader* loader, const ResourceRequest& request)
349 {
350     GOwnPtr<gchar> identifierString(toString(identifier));
351
352     WebKitWebResource* webResource = WEBKIT_WEB_RESOURCE(g_object_new(WEBKIT_TYPE_WEB_RESOURCE, "uri", request.url().string().utf8().data(), 0));
353
354     if (loader == loader->frameLoader()->provisionalDocumentLoader()
355         && loader->frameLoader()->isLoadingMainFrame()) {
356         webkit_web_view_add_main_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
357         return;
358     }
359
360     webkit_web_view_add_resource(getViewFromFrame(m_frame), identifierString.get(), webResource);
361 }
362
363 void FrameLoaderClient::postProgressStartedNotification()
364 {
365     WebKitWebView* webView = getViewFromFrame(m_frame);
366     g_signal_emit_by_name(webView, "load-started", m_frame);
367
368     g_object_notify(G_OBJECT(webView), "progress");
369 }
370
371 void FrameLoaderClient::postProgressEstimateChangedNotification()
372 {
373     WebKitWebView* webView = getViewFromFrame(m_frame);
374     Page* corePage = core(webView);
375
376     g_signal_emit_by_name(webView, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100));
377
378     g_object_notify(G_OBJECT(webView), "progress");
379 }
380
381 void FrameLoaderClient::postProgressFinishedNotification()
382 {
383     WebKitWebView* webView = getViewFromFrame(m_frame);
384     WebKitWebViewPrivate* privateData = webView->priv;
385
386     // We can get a stopLoad() from dispose when the object is being
387     // destroyed, don't emit the signal in that case.
388     if (!privateData->disposing)
389         g_signal_emit_by_name(webView, "load-finished", m_frame);
390 }
391
392 void FrameLoaderClient::frameLoaderDestroyed()
393 {
394     webkit_web_frame_core_frame_gone(m_frame);
395     g_object_unref(m_frame);
396     m_frame = 0;
397     delete this;
398 }
399
400 void FrameLoaderClient::dispatchDidReceiveResponse(WebCore::DocumentLoader* loader, unsigned long, const ResourceResponse& response)
401 {
402     // Update our knowledge of request soup flags - some are only set
403     // after the request is done.
404     loader->request().setSoupMessageFlags(response.soupMessageFlags());
405
406     m_response = response;
407 }
408
409 void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String& mimeType, const ResourceRequest& resourceRequest)
410 {
411     ASSERT(policyFunction);
412     if (!policyFunction)
413         return;
414
415     if (resourceRequest.isNull()) {
416         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
417         return;
418     }
419
420     WebKitWebView* page = getViewFromFrame(m_frame);
421     PlatformRefPtr<WebKitNetworkRequest> request(adoptPlatformRef(kitNew(resourceRequest)));
422
423     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
424     if (m_policyDecision)
425         g_object_unref(m_policyDecision);
426     m_policyDecision = policyDecision;
427
428     gboolean isHandled = false;
429     g_signal_emit_by_name(page, "mime-type-policy-decision-requested", m_frame, request.get(), mimeType.utf8().data(), policyDecision, &isHandled);
430
431     if (isHandled)
432         return;
433
434     PlatformRefPtr<WebKitNetworkResponse> networkResponse(adoptPlatformRef(webkit_web_frame_get_network_response(m_frame)));
435     if (networkResponse) {
436         ResourceResponse response = core(networkResponse.get());
437         if (response.isAttachment()) {
438             webkit_web_policy_decision_download(policyDecision);
439             return;
440         }
441     }
442
443     if (canShowMIMEType(mimeType))
444         webkit_web_policy_decision_use(policyDecision);
445     else
446         webkit_web_policy_decision_ignore(policyDecision);
447 }
448
449 static WebKitWebNavigationAction* getNavigationAction(const NavigationAction& action, const char* targetFrame)
450 {
451     gint button = -1;
452
453     const Event* event = action.event();
454     if (event && event->isMouseEvent()) {
455         const MouseEvent* mouseEvent = static_cast<const MouseEvent*>(event);
456         // DOM button values are 0, 1 and 2 for left, middle and right buttons.
457         // GTK+ uses 1, 2 and 3, so let's add 1 to remain consistent.
458         button = mouseEvent->button() + 1;
459     }
460
461     gint modifierFlags = 0;
462     UIEventWithKeyState* keyStateEvent = findEventWithKeyState(const_cast<Event*>(event));
463     if (keyStateEvent) {
464         if (keyStateEvent->shiftKey())
465             modifierFlags |= GDK_SHIFT_MASK;
466         if (keyStateEvent->ctrlKey())
467             modifierFlags |= GDK_CONTROL_MASK;
468         if (keyStateEvent->altKey())
469             modifierFlags |= GDK_MOD1_MASK;
470         if (keyStateEvent->metaKey())
471             modifierFlags |= GDK_MOD2_MASK;
472     }
473
474     return WEBKIT_WEB_NAVIGATION_ACTION(g_object_new(WEBKIT_TYPE_WEB_NAVIGATION_ACTION,
475                                                      "reason", kit(action.type()),
476                                                      "original-uri", action.url().string().utf8().data(),
477                                                      "button", button,
478                                                      "modifier-state", modifierFlags,
479                                                      "target-frame", targetFrame,
480                                                      NULL));
481 }
482
483 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>, const String& frameName)
484 {
485     ASSERT(policyFunction);
486     if (!policyFunction)
487         return;
488
489     if (resourceRequest.isNull()) {
490         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
491         return;
492     }
493
494     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
495
496     if (m_policyDecision)
497         g_object_unref(m_policyDecision);
498     m_policyDecision = policyDecision;
499
500     WebKitWebView* webView = getViewFromFrame(m_frame);
501     PlatformRefPtr<WebKitNetworkRequest> request(adoptPlatformRef(webkit_network_request_new(resourceRequest.url().string().utf8().data())));
502     PlatformRefPtr<WebKitWebNavigationAction> navigationAction(adoptPlatformRef(getNavigationAction(action, frameName.utf8().data())));
503     gboolean isHandled = false;
504
505     g_signal_emit_by_name(webView, "new-window-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
506
507     // FIXME: I think Qt version marshals this to another thread so when we
508     // have multi-threaded download, we might need to do the same
509     if (!isHandled)
510         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyUse);
511 }
512
513 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest, PassRefPtr<FormState>)
514 {
515     ASSERT(policyFunction);
516     if (!policyFunction)
517         return;
518
519     if (resourceRequest.isNull()) {
520         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
521         return;
522     }
523
524     WebKitWebView* webView = getViewFromFrame(m_frame);
525     PlatformRefPtr<WebKitNetworkRequest> request(adoptPlatformRef(kitNew(resourceRequest)));
526     WebKitNavigationResponse response;
527     /*
528      * We still support the deprecated navigation-requested signal, if the
529      * application doesn't ignore the navigation then the new signal is
530      * emitted.
531      * navigation-policy-decision-requested must be emitted after
532      * navigation-requested as the policy decision can be async.
533      */
534     g_signal_emit_by_name(webView, "navigation-requested", m_frame, request.get(), &response);
535
536     if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
537         (core(m_frame)->loader()->policyChecker()->*policyFunction)(PolicyIgnore);
538         return;
539     }
540
541     WebKitWebPolicyDecision* policyDecision = webkit_web_policy_decision_new(m_frame, policyFunction);
542     if (m_policyDecision)
543         g_object_unref(m_policyDecision);
544     m_policyDecision = policyDecision;
545
546     PlatformRefPtr<WebKitWebNavigationAction> navigationAction(adoptPlatformRef(getNavigationAction(action, 0)));
547     gboolean isHandled = false;
548     g_signal_emit_by_name(webView, "navigation-policy-decision-requested", m_frame, request.get(), navigationAction.get(), policyDecision, &isHandled);
549
550     // FIXME Implement default behavior when we can query the backend what protocols it supports
551     if (!isHandled)
552         webkit_web_policy_decision_use(m_policyDecision);
553 }
554
555 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)
556 {
557     /* Check if we want to embed a GtkWidget, fallback to plugins later */
558     CString urlString = url.string().utf8();
559     CString mimeTypeString = mimeType.utf8();
560
561     ASSERT(paramNames.size() == paramValues.size());
562     PlatformRefPtr<GHashTable> hash = adoptPlatformRef(g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free));
563     for (unsigned i = 0; i < paramNames.size(); ++i) {
564         g_hash_table_insert(hash.get(),
565                             g_strdup(paramNames[i].utf8().data()),
566                             g_strdup(paramValues[i].utf8().data()));
567     }
568
569     GtkWidget* gtkWidget = 0;
570     g_signal_emit_by_name(getViewFromFrame(m_frame), "create-plugin-widget",
571                           mimeTypeString.data(), urlString.data(), hash.get(), &gtkWidget);
572     if (gtkWidget)
573         return adoptRef(new GtkPluginWidget(gtkWidget));
574
575     RefPtr<PluginView> pluginView = PluginView::create(core(m_frame), pluginSize, element, url, paramNames, paramValues, mimeType, loadManually);
576
577     if (pluginView->status() == PluginStatusLoadedSuccessfully)
578         return pluginView;
579
580     return 0;
581 }
582
583 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
584                                                  const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
585 {
586     ASSERT(m_frame);
587     Frame* parentFrame = core(m_frame);
588     WebKitWebView* webView = getViewFromFrame(m_frame);
589     WebCore::Page* page = core(webView);
590     ASSERT(page == parentFrame->page());
591
592     WebKitWebFrame* kitFrame = WEBKIT_WEB_FRAME(g_object_new(WEBKIT_TYPE_WEB_FRAME, NULL));
593     WebKitWebFramePrivate* framePrivate = kitFrame->priv;
594     framePrivate->webView = webView;
595
596     RefPtr<Frame> childFrame = Frame::create(page, ownerElement, new FrameLoaderClient(kitFrame));
597     framePrivate->coreFrame = childFrame.get();
598
599     childFrame->tree()->setName(name);
600     parentFrame->tree()->appendChild(childFrame);
601     childFrame->init();
602
603     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
604     if (!childFrame->page())
605         return 0;
606
607     g_signal_emit_by_name(webView, "frame-created", kitFrame);
608
609     childFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
610
611     // The frame's onload handler may have removed it from the document.
612     if (!childFrame->tree()->parent())
613         return 0;
614
615     return childFrame.release();
616 }
617
618 void FrameLoaderClient::didTransferChildFrameToNewDocument(WebCore::Page*)
619 {
620     ASSERT(m_frame);
621
622     // Update the frame's webview to the new parent's webview.
623     Frame* coreFrame = core(m_frame);
624     WebKitWebView* webView = getViewFromFrame(m_frame);
625
626     Frame* parentCoreFrame = coreFrame->tree()->parent();
627     WebKitWebFrame* parentKitFrame = kit(parentCoreFrame);
628     WebKitWebView* parentWebView = getViewFromFrame(parentKitFrame);
629     if (webView != parentWebView)
630         m_frame->priv->webView = parentWebView;
631
632     ASSERT(core(getViewFromFrame(m_frame)) == coreFrame->page());
633 }
634
635 void FrameLoaderClient::transferLoadingResourceFromPage(unsigned long identifier, WebCore::DocumentLoader* docLoader, const WebCore::ResourceRequest& request, WebCore::Page* oldPage)
636 {
637     ASSERT(oldPage != core(m_frame)->page());
638
639     GOwnPtr<gchar> identifierString(toString(identifier));
640     ASSERT(!webkit_web_view_get_resource(getViewFromFrame(m_frame), identifierString.get()));
641
642     assignIdentifierToInitialRequest(identifier, docLoader, request);
643
644     webkit_web_view_remove_resource(kit(oldPage), identifierString.get());
645 }
646
647 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
648 {
649     ASSERT(!m_pluginView);
650     m_pluginView = static_cast<PluginView*>(pluginWidget);
651     m_hasSentResponseToPlugin = false;
652 }
653
654 PassRefPtr<Widget> FrameLoaderClient::createJavaAppletWidget(const IntSize& pluginSize, HTMLAppletElement* element, const KURL& baseURL, const Vector<String>& paramNames, const Vector<String>& paramValues)
655 {
656     return FrameLoaderClient::createPlugin(pluginSize, element, baseURL, paramNames, paramValues, "application/x-java-applet", false);
657 }
658
659 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
660 {
661     return FrameLoader::defaultObjectContentType(url, mimeType);
662 }
663
664 String FrameLoaderClient::overrideMediaType() const
665 {
666     notImplemented();
667     return String();
668 }
669
670 void FrameLoaderClient::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld* world)
671 {
672     if (world != mainThreadNormalWorld())
673         return;
674
675     // Is this obsolete now?
676     g_signal_emit_by_name(m_frame, "cleared");
677
678     Frame* coreFrame = core(m_frame);
679     ASSERT(coreFrame);
680
681     Settings* settings = coreFrame->settings();
682     if (!settings || !settings->isJavaScriptEnabled())
683         return;
684
685     // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead
686     // when there are no handlers.
687     JSGlobalContextRef context = toGlobalRef(coreFrame->script()->globalObject(mainThreadNormalWorld())->globalExec());
688     JSObjectRef windowObject = toRef(coreFrame->script()->globalObject(mainThreadNormalWorld()));
689     ASSERT(windowObject);
690
691     WebKitWebView* webView = getViewFromFrame(m_frame);
692     g_signal_emit_by_name(webView, "window-object-cleared", m_frame, context, windowObject);
693
694     // TODO: Re-attach debug clients if present.
695     // The Win port has an example of how we might do this.
696 }
697
698 void FrameLoaderClient::documentElementAvailable()
699 {
700 }
701
702 void FrameLoaderClient::didPerformFirstNavigation() const
703 {
704     WebKitCacheModel cacheModel = webkit_get_cache_model();
705     // If user agents do not determine the cache model, we use WEBKIT_CACHE_MODEL_WEB_BROWSER by default.
706     if (cacheModel == WEBKIT_CACHE_MODEL_DEFAULT)
707         webkit_set_cache_model(WEBKIT_CACHE_MODEL_WEB_BROWSER);
708 }
709
710 void FrameLoaderClient::registerForIconNotification(bool shouldRegister)
711 {
712     notImplemented();
713 }
714
715 void FrameLoaderClient::setMainFrameDocumentReady(bool ready)
716 {
717     if (!ready)
718         DOMObjectCache::clearByFrame(core(m_frame));
719 }
720
721 bool FrameLoaderClient::hasWebView() const
722 {
723     return getViewFromFrame(m_frame);
724 }
725
726 void FrameLoaderClient::dispatchDidFinishLoad()
727 {
728     if (m_loadingErrorPage) {
729         m_loadingErrorPage = false;
730         return;
731     }
732
733     loadDone(m_frame, true);
734 }
735
736 void FrameLoaderClient::frameLoadCompleted()
737 {
738     notImplemented();
739 }
740
741 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
742 {
743     notImplemented();
744 }
745
746 void FrameLoaderClient::restoreViewState()
747 {
748     notImplemented();
749 }
750
751 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
752 {
753     // FIXME: This is a very simple implementation. More sophisticated
754     // implementation would delegate the decision to a PolicyDelegate.
755     // See mac implementation for example.
756     return item != 0;
757 }
758
759 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
760 {
761 }
762
763 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
764 {
765 }
766
767 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const
768 {
769 }
770
771 void FrameLoaderClient::didDisplayInsecureContent()
772 {
773     notImplemented();
774 }
775
776 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*)
777 {
778     notImplemented();
779 }
780
781 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*)
782 {
783     notImplemented();
784 }
785
786 void FrameLoaderClient::forceLayout()
787 {
788     FrameView* view = core(m_frame)->view();
789     if (view)
790         view->forceLayout(true);
791 }
792
793 void FrameLoaderClient::forceLayoutForNonHTML()
794 {
795     notImplemented();
796 }
797
798 void FrameLoaderClient::setCopiesOnScroll()
799 {
800     notImplemented();
801 }
802
803 void FrameLoaderClient::detachedFromParent2()
804 {
805     notImplemented();
806 }
807
808 void FrameLoaderClient::detachedFromParent3()
809 {
810     notImplemented();
811 }
812
813 void FrameLoaderClient::dispatchDidHandleOnloadEvents()
814 {
815     g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame);
816 }
817
818 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
819 {
820     notImplemented();
821 }
822
823 void FrameLoaderClient::dispatchDidCancelClientRedirect()
824 {
825     notImplemented();
826 }
827
828 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double)
829 {
830     notImplemented();
831 }
832
833 void FrameLoaderClient::dispatchDidChangeLocationWithinPage()
834 {
835     WebKitWebFramePrivate* priv = m_frame->priv;
836     g_free(priv->uri);
837     priv->uri = g_strdup(core(m_frame)->loader()->url().prettyURL().utf8().data());
838     g_object_notify(G_OBJECT(m_frame), "uri");
839     WebKitWebView* webView = getViewFromFrame(m_frame);
840     if (m_frame == webkit_web_view_get_main_frame(webView))
841         g_object_notify(G_OBJECT(webView), "uri");
842 }
843
844 void FrameLoaderClient::dispatchDidPushStateWithinPage()
845 {
846     notImplemented();
847 }
848
849 void FrameLoaderClient::dispatchDidReplaceStateWithinPage()
850 {
851     notImplemented();
852 }
853
854 void FrameLoaderClient::dispatchDidPopStateWithinPage()
855 {
856     notImplemented();
857 }
858
859 void FrameLoaderClient::dispatchWillClose()
860 {
861     notImplemented();
862 }
863
864 void FrameLoaderClient::dispatchDidReceiveIcon()
865 {
866     if (m_loadingErrorPage)
867         return;
868
869     WebKitWebView* webView = getViewFromFrame(m_frame);
870
871     // Avoid reporting favicons for non-main frames.
872     if (m_frame != webkit_web_view_get_main_frame(webView))
873         return;
874
875     g_object_notify(G_OBJECT(webView), "icon-uri");
876     g_signal_emit_by_name(webView, "icon-loaded", webkit_web_view_get_icon_uri(webView));
877 }
878
879 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
880 {
881     if (m_loadingErrorPage)
882         return;
883
884     notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL);
885 }
886
887 void FrameLoaderClient::dispatchDidReceiveTitle(const String& title)
888 {
889     if (m_loadingErrorPage)
890         return;
891
892     WebKitWebFramePrivate* priv = m_frame->priv;
893     g_free(priv->title);
894     priv->title = g_strdup(title.utf8().data());
895
896     g_signal_emit_by_name(m_frame, "title-changed", priv->title);
897     g_object_notify(G_OBJECT(m_frame), "title");
898
899     WebKitWebView* webView = getViewFromFrame(m_frame);
900     if (m_frame == webkit_web_view_get_main_frame(webView)) {
901         g_signal_emit_by_name(webView, "title-changed", m_frame, title.utf8().data());
902         g_object_notify(G_OBJECT(webView), "title");
903     }
904 }
905
906 void FrameLoaderClient::dispatchDidChangeIcons()
907 {
908     notImplemented();
909 }
910
911 void FrameLoaderClient::dispatchDidCommitLoad()
912 {
913     if (m_loadingErrorPage)
914         return;
915
916     /* Update the URI once first data has been received.
917      * This means the URI is valid and successfully identify the page that's going to be loaded.
918      */
919     g_object_freeze_notify(G_OBJECT(m_frame));
920
921     WebKitWebFramePrivate* priv = m_frame->priv;
922     g_free(priv->uri);
923     priv->uri = g_strdup(core(m_frame)->loader()->activeDocumentLoader()->url().prettyURL().utf8().data());
924     g_free(priv->title);
925     priv->title = NULL;
926     g_object_notify(G_OBJECT(m_frame), "uri");
927     g_object_notify(G_OBJECT(m_frame), "title");
928
929     g_signal_emit_by_name(m_frame, "load-committed");
930     notifyStatus(m_frame, WEBKIT_LOAD_COMMITTED);
931
932     WebKitWebView* webView = getViewFromFrame(m_frame);
933     if (m_frame == webkit_web_view_get_main_frame(webView)) {
934         g_object_freeze_notify(G_OBJECT(webView));
935         g_object_notify(G_OBJECT(webView), "uri");
936         g_object_notify(G_OBJECT(webView), "title");
937         g_object_thaw_notify(G_OBJECT(webView));
938         g_signal_emit_by_name(webView, "load-committed", m_frame);
939     }
940
941     g_object_thaw_notify(G_OBJECT(m_frame));
942 }
943
944 void FrameLoaderClient::dispatchDidFinishDocumentLoad()
945 {
946     WebKitWebView* webView = getViewFromFrame(m_frame);
947     g_signal_emit_by_name(webView, "document-load-finished", m_frame);
948 }
949
950 void FrameLoaderClient::dispatchDidFirstLayout()
951 {
952     notImplemented();
953 }
954
955 void FrameLoaderClient::dispatchDidFirstVisuallyNonEmptyLayout()
956 {
957     if (m_loadingErrorPage)
958         return;
959
960     notifyStatus(m_frame, WEBKIT_LOAD_FIRST_VISUALLY_NON_EMPTY_LAYOUT);
961 }
962
963 void FrameLoaderClient::dispatchShow()
964 {
965     WebKitWebView* webView = getViewFromFrame(m_frame);
966     webkit_web_view_notify_ready(webView);
967 }
968
969 void FrameLoaderClient::cancelPolicyCheck()
970 {
971     //FIXME Add support for more than one policy decision at once
972     if (m_policyDecision)
973         webkit_web_policy_decision_cancel(m_policyDecision);
974 }
975
976 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*)
977 {
978     notImplemented();
979 }
980
981 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*)
982 {
983     notImplemented();
984 }
985
986 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*)
987 {
988     notImplemented();
989 }
990
991 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l)
992 {
993     setTitle(l->title(), l->url());
994 }
995
996 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const
997 {
998     notImplemented();
999     return true;
1000 }
1001
1002 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
1003 {
1004     notImplemented();
1005     return false;
1006 }
1007
1008 bool FrameLoaderClient::canShowMIMEType(const String& type) const
1009 {
1010     return (MIMETypeRegistry::isSupportedImageMIMEType(type)
1011             || MIMETypeRegistry::isSupportedNonImageMIMEType(type)
1012             || MIMETypeRegistry::isSupportedMediaMIMEType(type)
1013             || PluginDatabase::installedPlugins()->isMIMETypeRegistered(type));
1014 }
1015
1016 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const
1017 {
1018     notImplemented();
1019     return false;
1020 }
1021
1022 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const
1023 {
1024     notImplemented();
1025     return String();
1026 }
1027
1028 void FrameLoaderClient::finishedLoading(WebCore::DocumentLoader* documentLoader)
1029 {
1030     if (!m_pluginView) {
1031         FrameLoader* loader = documentLoader->frameLoader();
1032         loader->writer()->setEncoding(m_response.textEncodingName(), false);
1033     } else {
1034         m_pluginView->didFinishLoading();
1035         m_pluginView = 0;
1036         m_hasSentResponseToPlugin = false;
1037     }
1038 }
1039
1040
1041 void FrameLoaderClient::provisionalLoadStarted()
1042 {
1043     notImplemented();
1044 }
1045
1046 void FrameLoaderClient::didFinishLoad() {
1047     notImplemented();
1048 }
1049
1050 void FrameLoaderClient::prepareForDataSourceReplacement() 
1051 {
1052     notImplemented();
1053 }
1054
1055 void FrameLoaderClient::setTitle(const String& title, const KURL& url)
1056 {
1057     WebKitWebFramePrivate* frameData = m_frame->priv;
1058     g_free(frameData->title);
1059     frameData->title = g_strdup(title.utf8().data());
1060 }
1061
1062 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int lengthReceived)
1063 {
1064     notImplemented();
1065 }
1066
1067 void FrameLoaderClient::dispatchDidFinishLoading(WebCore::DocumentLoader* loader, unsigned long identifier)
1068 {
1069     static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1070
1071     WebKitWebView* webView = getViewFromFrame(m_frame);
1072     GOwnPtr<gchar> identifierString(toString(identifier));
1073     WebKitWebResource* webResource = webkit_web_view_get_resource(webView, identifierString.get());
1074
1075     // A NULL WebResource means the load has been interrupted, and
1076     // replaced by another one while this resource was being loaded.
1077     if (!webResource)
1078         return;
1079
1080     const char* uri = webkit_web_resource_get_uri(webResource);
1081     RefPtr<ArchiveResource> coreResource(loader->subresource(KURL(KURL(), uri)));
1082
1083     // If coreResource is NULL here, the resource failed to load,
1084     // unless it's the main resource.
1085     if (!coreResource && webResource != webkit_web_view_get_main_resource(webView))
1086         return;
1087
1088     if (!coreResource)
1089         coreResource = loader->mainResource();
1090
1091     webkit_web_resource_init_with_core_resource(webResource, coreResource.get());
1092
1093     // FIXME: This function should notify the application that the resource
1094     // finished loading, maybe using a load-status property in the
1095     // WebKitWebResource object, similar to what we do for WebKitWebFrame'
1096     // signal.
1097     notImplemented();
1098 }
1099
1100 void FrameLoaderClient::dispatchDidFailLoading(WebCore::DocumentLoader* loader, unsigned long identifier, const ResourceError& error)
1101 {
1102     static_cast<WebKit::DocumentLoader*>(loader)->decreaseLoadCount(identifier);
1103
1104     // FIXME: This function should notify the application that the resource failed
1105     // loading, maybe a 'load-error' signal in the WebKitWebResource object.
1106     notImplemented();
1107 }
1108
1109 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
1110 {
1111     notImplemented();
1112     return false;
1113 }
1114
1115 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
1116 {
1117     dispatchDidFailLoad(error);
1118 }
1119
1120 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError& error)
1121 {
1122     if (m_loadingErrorPage)
1123         return;
1124
1125     notifyStatus(m_frame, WEBKIT_LOAD_FAILED);
1126
1127     WebKitWebView* webView = getViewFromFrame(m_frame);
1128     GError* webError = g_error_new_literal(g_quark_from_string(error.domain().utf8().data()),
1129                                            error.errorCode(),
1130                                            error.localizedDescription().utf8().data());
1131     gboolean isHandled = false;
1132     g_signal_emit_by_name(webView, "load-error", m_frame, error.failingURL().utf8().data(), webError, &isHandled);
1133
1134     if (isHandled) {
1135         g_error_free(webError);
1136         return;
1137     }
1138
1139     if (!shouldFallBack(error)) {
1140         g_error_free(webError);
1141         return;
1142     }
1143
1144     m_loadingErrorPage = true;
1145
1146     String content;
1147     gchar* fileContent = 0;
1148     gchar* errorURI = g_filename_to_uri(DATA_DIR"/webkit-1.0/resources/error.html", NULL, NULL);
1149     GFile* errorFile = g_file_new_for_uri(errorURI);
1150     g_free(errorURI);
1151
1152     if (!errorFile)
1153         content = makeString("<html><body>", webError->message, "</body></html>");
1154     else {
1155         gboolean loaded = g_file_load_contents(errorFile, 0, &fileContent, 0, 0, 0);
1156         if (!loaded)
1157             content = makeString("<html><body>", webError->message, "</body></html>");
1158         else
1159             content = String::format(fileContent, error.failingURL().utf8().data(), webError->message);
1160     }
1161
1162     webkit_web_frame_load_alternate_string(m_frame, content.utf8().data(), 0, error.failingURL().utf8().data());
1163
1164     g_free(fileContent);
1165
1166     if (errorFile)
1167         g_object_unref(errorFile);
1168
1169     g_error_free(webError);
1170 }
1171
1172 void FrameLoaderClient::download(ResourceHandle* handle, const ResourceRequest& request, const ResourceRequest&, const ResourceResponse& response)
1173 {
1174     PlatformRefPtr<WebKitNetworkRequest> networkRequest(adoptPlatformRef(kitNew(request)));
1175     WebKitWebView* view = getViewFromFrame(m_frame);
1176
1177     webkit_web_view_request_download(view, networkRequest.get(), response, handle);
1178 }
1179
1180 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest& request)
1181 {
1182     return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_CANCELLED,
1183                          request.url().string(), _("Load request cancelled"));
1184 }
1185
1186 ResourceError FrameLoaderClient::blockedError(const ResourceRequest& request)
1187 {
1188     return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_USE_RESTRICTED_PORT,
1189                          request.url().string(), _("Not allowed to use restricted network port"));
1190 }
1191
1192 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest& request)
1193 {
1194     return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_URL,
1195                          request.url().string(), _("URL cannot be shown"));
1196 }
1197
1198 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest& request)
1199 {
1200     return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE,
1201                          request.url().string(), _("Frame load was interrupted"));
1202 }
1203
1204 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse& response)
1205 {
1206     return ResourceError(g_quark_to_string(WEBKIT_POLICY_ERROR), WEBKIT_POLICY_ERROR_CANNOT_SHOW_MIME_TYPE,
1207                          response.url().string(), _("Content with the specified MIME type cannot be shown"));
1208 }
1209
1210 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse& response)
1211 {
1212     return ResourceError(g_quark_to_string(WEBKIT_NETWORK_ERROR), WEBKIT_NETWORK_ERROR_FILE_DOES_NOT_EXIST,
1213                          response.url().string(), _("File does not exist"));
1214 }
1215
1216 ResourceError FrameLoaderClient::pluginWillHandleLoadError(const ResourceResponse& response)
1217 {
1218     return ResourceError(g_quark_to_string(WEBKIT_PLUGIN_ERROR), WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD,
1219                          response.url().string(), _("Plugin will handle load"));
1220 }
1221
1222 bool FrameLoaderClient::shouldFallBack(const ResourceError& error)
1223 {
1224     return !(error.isCancellation() || error.errorCode() == WEBKIT_POLICY_ERROR_FRAME_LOAD_INTERRUPTED_BY_POLICY_CHANGE || error.errorCode() == WEBKIT_PLUGIN_ERROR_WILL_HANDLE_LOAD);
1225 }
1226
1227 bool FrameLoaderClient::canCachePage() const
1228 {
1229     return true;
1230 }
1231
1232 Frame* FrameLoaderClient::dispatchCreatePage(const NavigationAction&)
1233 {
1234     WebKitWebView* webView = getViewFromFrame(m_frame);
1235     WebKitWebView* newWebView = 0;
1236
1237     g_signal_emit_by_name(webView, "create-web-view", m_frame, &newWebView);
1238
1239     if (!newWebView)
1240         return 0;
1241
1242     WebKitWebViewPrivate* privateData = newWebView->priv;
1243     return core(privateData->mainFrame);
1244 }
1245
1246 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&)
1247 {
1248     notImplemented();
1249 }
1250
1251 void FrameLoaderClient::setMainDocumentError(WebCore::DocumentLoader*, const ResourceError& error)
1252 {
1253     if (m_pluginView) {
1254         m_pluginView->didFail(error);
1255         m_pluginView = 0;
1256         m_hasSentResponseToPlugin = false;
1257     }
1258 }
1259
1260 void FrameLoaderClient::startDownload(const ResourceRequest& request)
1261 {
1262     PlatformRefPtr<WebKitNetworkRequest> networkRequest(adoptPlatformRef(kitNew(request)));
1263     WebKitWebView* view = getViewFromFrame(m_frame);
1264
1265     webkit_web_view_request_download(view, networkRequest.get());
1266 }
1267
1268 void FrameLoaderClient::updateGlobalHistory()
1269 {
1270     notImplemented();
1271 }
1272
1273 void FrameLoaderClient::updateGlobalHistoryRedirectLinks()
1274 {
1275     notImplemented();
1276 }
1277
1278 void FrameLoaderClient::savePlatformDataToCachedFrame(CachedFrame* cachedFrame)
1279 {
1280     // We need to do this here in order to disconnect the scrollbars
1281     // that are being used by the frame that is being cached from the
1282     // adjustments, otherwise they will react to changes in the
1283     // adjustments, and bad things will happen.
1284     if (cachedFrame->view())
1285         cachedFrame->view()->setGtkAdjustments(0, 0);
1286 }
1287
1288 static void postCommitFrameViewSetup(WebKitWebFrame *frame, FrameView *view, bool resetValues)
1289 {
1290     WebKitWebView* containingWindow = getViewFromFrame(frame);
1291     webkit_web_view_clear_resources(containingWindow);
1292
1293     WebKitWebViewPrivate* priv = containingWindow->priv;
1294     view->setGtkAdjustments(priv->horizontalAdjustment.get(), priv->verticalAdjustment.get(), resetValues);
1295
1296     // Invalidate the viewport attributes - they will only be valid
1297     // again if the page we're beginning to load now has an
1298     // appropriate viewport meta tag.
1299     containingWindow->priv->viewportAttributes->priv->isValid = FALSE;
1300     g_object_notify(G_OBJECT(containingWindow->priv->viewportAttributes.get()), "valid");
1301
1302     if (priv->currentMenu) {
1303         PlatformRefPtr<GtkMenu> menu(priv->currentMenu);
1304         priv->currentMenu.clear();
1305         gtk_menu_popdown(menu.get());
1306     }
1307
1308     // Do not allow click counting between main frame loads.
1309     priv->previousClickTime = 0;
1310 }
1311
1312 void FrameLoaderClient::transitionToCommittedFromCachedFrame(CachedFrame* cachedFrame)
1313 {
1314     ASSERT(cachedFrame->view());
1315
1316     Frame* frame = core(m_frame);
1317     if (frame != frame->page()->mainFrame())
1318         return;
1319
1320     postCommitFrameViewSetup(m_frame, cachedFrame->view(), false);
1321 }
1322
1323 void FrameLoaderClient::transitionToCommittedForNewPage()
1324 {
1325     WebKitWebView* containingWindow = getViewFromFrame(m_frame);
1326     GtkAllocation allocation;
1327 #if GTK_CHECK_VERSION(2, 18, 0)
1328     gtk_widget_get_allocation(GTK_WIDGET(containingWindow), &allocation);
1329 #else
1330     allocation = GTK_WIDGET(containingWindow)->allocation;
1331 #endif
1332     IntSize size = IntSize(allocation.width, allocation.height);
1333     bool transparent = webkit_web_view_get_transparent(containingWindow);
1334     Color backgroundColor = transparent ? WebCore::Color::transparent : WebCore::Color::white;
1335     Frame* frame = core(m_frame);
1336     ASSERT(frame);
1337
1338     frame->createView(size, backgroundColor, transparent, IntSize(), false);
1339
1340     // We need to do further manipulation on the FrameView if it was the mainFrame
1341     if (frame != frame->page()->mainFrame())
1342         return;
1343
1344     postCommitFrameViewSetup(m_frame, frame->view(), true);
1345 }
1346
1347 void FrameLoaderClient::didSaveToPageCache()
1348 {
1349 }
1350
1351 void FrameLoaderClient::didRestoreFromPageCache()
1352 {
1353 }
1354
1355 void FrameLoaderClient::dispatchDidBecomeFrameset(bool)
1356 {
1357 }
1358
1359 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext()
1360 {
1361     return FrameNetworkingContextGtk::create(core(m_frame));
1362 }
1363
1364 }