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