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