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