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