• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  *  Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
3  *  Copyright (C) 2007, 2008, 2009 Holger Hans Peter Freyther
4  *  Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
5  *  Copyright (C) 2008, 2009 Collabora Ltd.  All rights reserved.
6  *  Copyright (C) 2009, 2010 Gustavo Noronha Silva <gns@gnome.org>
7  *  Copyright (C) Research In Motion Limited 2009. All rights reserved.
8  *  Copyright (C) 2010 Igalia S.L.
9  *  Copyright (C) 2011 Apple Inc. All rights reserved.
10  *
11  *  This library is free software; you can redistribute it and/or
12  *  modify it under the terms of the GNU Lesser General Public
13  *  License as published by the Free Software Foundation; either
14  *  version 2 of the License, or (at your option) any later version.
15  *
16  *  This library is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  *  Lesser General Public License for more details.
20  *
21  *  You should have received a copy of the GNU Lesser General Public
22  *  License along with this library; if not, write to the Free Software
23  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
24  */
25 
26 #include "config.h"
27 #include "FrameLoaderClientGtk.h"
28 
29 #include "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 
FrameLoaderClient(WebKitWebFrame * frame)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 
~FrameLoaderClient()111 FrameLoaderClient::~FrameLoaderClient()
112 {
113     if (m_policyDecision)
114         g_object_unref(m_policyDecision);
115 }
116 
initializeDomainsList(HashSet<String> & googleDomains)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 
isGoogleDomain(String host)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 
userAgent(const KURL & url)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 
notifyAccessibilityStatus(WebKitWebFrame * frame,WebKitLoadStatus loadStatus)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 
notifyStatus(WebKitWebFrame * frame,WebKitLoadStatus loadStatus)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 
loadDone(WebKitWebFrame * frame,bool didSucceed)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 
createDocumentLoader(const WebCore::ResourceRequest & request,const SubstituteData & substituteData)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 
dispatchWillSubmitForm(FramePolicyFunction policyFunction,PassRefPtr<FormState>)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 
committedLoad(WebCore::DocumentLoader * loader,const char * data,int length)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
shouldUseCredentialStorage(WebCore::DocumentLoader *,unsigned long identifier)344 FrameLoaderClient::shouldUseCredentialStorage(WebCore::DocumentLoader*, unsigned long  identifier)
345 {
346     notImplemented();
347     return false;
348 }
349 
dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader *,unsigned long identifier,const AuthenticationChallenge &)350 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(WebCore::DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
351 {
352     notImplemented();
353 }
354 
dispatchDidCancelAuthenticationChallenge(WebCore::DocumentLoader *,unsigned long identifier,const AuthenticationChallenge &)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.
toString(unsigned long identifier)362 static char* toString(unsigned long identifier)
363 {
364     return g_strdup_printf("%ld", identifier);
365 }
366 
dispatchWillSendRequest(WebCore::DocumentLoader * loader,unsigned long identifier,ResourceRequest & request,const ResourceResponse & redirectResponse)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 
assignIdentifierToInitialRequest(unsigned long identifier,WebCore::DocumentLoader * loader,const ResourceRequest & request)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 
postProgressStartedNotification()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 
postProgressEstimateChangedNotification()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 
postProgressFinishedNotification()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 
frameLoaderDestroyed()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 
dispatchDidReceiveResponse(WebCore::DocumentLoader * loader,unsigned long,const ResourceResponse & response)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 
dispatchDecidePolicyForResponse(FramePolicyFunction policyFunction,const ResourceResponse & response,const ResourceRequest & resourceRequest)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 
getNavigationAction(const NavigationAction & action,const char * targetFrame)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 
dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction,const NavigationAction & action,const ResourceRequest & resourceRequest,PassRefPtr<FormState>,const String & frameName)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 
dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction,const NavigationAction & action,const ResourceRequest & resourceRequest,PassRefPtr<FormState>)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 
createPlugin(const IntSize & pluginSize,HTMLPlugInElement * element,const KURL & url,const Vector<String> & paramNames,const Vector<String> & paramValues,const String & mimeType,bool loadManually)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 
createFrame(const KURL & url,const String & name,HTMLFrameOwnerElement * ownerElement,const String & referrer,bool allowsScrolling,int marginWidth,int marginHeight)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 
didTransferChildFrameToNewDocument(WebCore::Page *)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 
transferLoadingResourceFromPage(unsigned long identifier,WebCore::DocumentLoader * docLoader,const WebCore::ResourceRequest & request,WebCore::Page * oldPage)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 
redirectDataToPlugin(Widget * pluginWidget)703 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
704 {
705     ASSERT(!m_pluginView);
706     m_pluginView = static_cast<PluginView*>(pluginWidget);
707     m_hasSentResponseToPlugin = false;
708 }
709 
createJavaAppletWidget(const IntSize & pluginSize,HTMLAppletElement * element,const KURL & baseURL,const Vector<String> & paramNames,const Vector<String> & paramValues)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 
objectContentType(const KURL & url,const String & mimeType,bool shouldPreferPlugInsForImages)715 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType, bool shouldPreferPlugInsForImages)
716 {
717     return FrameLoader::defaultObjectContentType(url, mimeType, shouldPreferPlugInsForImages);
718 }
719 
overrideMediaType() const720 String FrameLoaderClient::overrideMediaType() const
721 {
722     notImplemented();
723     return String();
724 }
725 
dispatchDidClearWindowObjectInWorld(DOMWrapperWorld * world)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 
documentElementAvailable()754 void FrameLoaderClient::documentElementAvailable()
755 {
756 }
757 
didPerformFirstNavigation() const758 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 
registerForIconNotification(bool shouldRegister)766 void FrameLoaderClient::registerForIconNotification(bool shouldRegister)
767 {
768     notImplemented();
769 }
770 
setMainFrameDocumentReady(bool ready)771 void FrameLoaderClient::setMainFrameDocumentReady(bool ready)
772 {
773     if (!ready)
774         DOMObjectCache::clearByFrame(core(m_frame));
775 }
776 
hasWebView() const777 bool FrameLoaderClient::hasWebView() const
778 {
779     return getViewFromFrame(m_frame);
780 }
781 
dispatchDidFinishLoad()782 void FrameLoaderClient::dispatchDidFinishLoad()
783 {
784     if (m_loadingErrorPage) {
785         m_loadingErrorPage = false;
786         return;
787     }
788 
789     loadDone(m_frame, true);
790 }
791 
frameLoadCompleted()792 void FrameLoaderClient::frameLoadCompleted()
793 {
794     notImplemented();
795 }
796 
saveViewStateToItem(HistoryItem *)797 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
798 {
799     notImplemented();
800 }
801 
restoreViewState()802 void FrameLoaderClient::restoreViewState()
803 {
804     notImplemented();
805 }
806 
shouldGoToHistoryItem(HistoryItem * item) const807 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 
shouldStopLoadingForHistoryItem(HistoryItem * item) const815 bool FrameLoaderClient::shouldStopLoadingForHistoryItem(HistoryItem* item) const
816 {
817     return true;
818 }
819 
dispatchDidAddBackForwardItem(HistoryItem *) const820 void FrameLoaderClient::dispatchDidAddBackForwardItem(HistoryItem*) const
821 {
822 }
823 
dispatchDidRemoveBackForwardItem(HistoryItem *) const824 void FrameLoaderClient::dispatchDidRemoveBackForwardItem(HistoryItem*) const
825 {
826 }
827 
dispatchDidChangeBackForwardIndex() const828 void FrameLoaderClient::dispatchDidChangeBackForwardIndex() const
829 {
830 }
831 
didDisplayInsecureContent()832 void FrameLoaderClient::didDisplayInsecureContent()
833 {
834     notImplemented();
835 }
836 
didRunInsecureContent(SecurityOrigin *,const KURL &)837 void FrameLoaderClient::didRunInsecureContent(SecurityOrigin*, const KURL&)
838 {
839     notImplemented();
840 }
841 
makeRepresentation(WebCore::DocumentLoader *)842 void FrameLoaderClient::makeRepresentation(WebCore::DocumentLoader*)
843 {
844     m_hasRepresentation = true;
845 }
846 
forceLayout()847 void FrameLoaderClient::forceLayout()
848 {
849     FrameView* view = core(m_frame)->view();
850     if (view)
851         view->forceLayout(true);
852 }
853 
forceLayoutForNonHTML()854 void FrameLoaderClient::forceLayoutForNonHTML()
855 {
856     notImplemented();
857 }
858 
setCopiesOnScroll()859 void FrameLoaderClient::setCopiesOnScroll()
860 {
861     notImplemented();
862 }
863 
detachedFromParent2()864 void FrameLoaderClient::detachedFromParent2()
865 {
866     notImplemented();
867 }
868 
detachedFromParent3()869 void FrameLoaderClient::detachedFromParent3()
870 {
871     notImplemented();
872 }
873 
dispatchDidHandleOnloadEvents()874 void FrameLoaderClient::dispatchDidHandleOnloadEvents()
875 {
876     g_signal_emit_by_name(getViewFromFrame(m_frame), "onload-event", m_frame);
877 }
878 
dispatchDidReceiveServerRedirectForProvisionalLoad()879 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad()
880 {
881     notImplemented();
882 }
883 
dispatchDidCancelClientRedirect()884 void FrameLoaderClient::dispatchDidCancelClientRedirect()
885 {
886     notImplemented();
887 }
888 
dispatchWillPerformClientRedirect(const KURL &,double,double)889 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double)
890 {
891     notImplemented();
892 }
893 
dispatchDidChangeLocationWithinPage()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 
dispatchDidPushStateWithinPage()905 void FrameLoaderClient::dispatchDidPushStateWithinPage()
906 {
907     notImplemented();
908 }
909 
dispatchDidReplaceStateWithinPage()910 void FrameLoaderClient::dispatchDidReplaceStateWithinPage()
911 {
912     notImplemented();
913 }
914 
dispatchDidPopStateWithinPage()915 void FrameLoaderClient::dispatchDidPopStateWithinPage()
916 {
917     notImplemented();
918 }
919 
dispatchWillClose()920 void FrameLoaderClient::dispatchWillClose()
921 {
922     notImplemented();
923 }
924 
dispatchDidReceiveIcon()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 
dispatchDidStartProvisionalLoad()944 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
945 {
946     if (m_loadingErrorPage)
947         return;
948 
949     notifyStatus(m_frame, WEBKIT_LOAD_PROVISIONAL);
950 }
951 
dispatchDidReceiveTitle(const StringWithDirection & title)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 
dispatchDidChangeIcons()972 void FrameLoaderClient::dispatchDidChangeIcons()
973 {
974     notImplemented();
975 }
976 
dispatchDidCommitLoad()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 
dispatchDidFinishDocumentLoad()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 
dispatchDidFirstLayout()1016 void FrameLoaderClient::dispatchDidFirstLayout()
1017 {
1018     notImplemented();
1019 }
1020 
dispatchDidFirstVisuallyNonEmptyLayout()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 
dispatchShow()1029 void FrameLoaderClient::dispatchShow()
1030 {
1031     WebKitWebView* webView = getViewFromFrame(m_frame);
1032     webkit_web_view_notify_ready(webView);
1033 }
1034 
cancelPolicyCheck()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 
dispatchDidLoadMainResource(WebCore::DocumentLoader *)1042 void FrameLoaderClient::dispatchDidLoadMainResource(WebCore::DocumentLoader*)
1043 {
1044     notImplemented();
1045 }
1046 
revertToProvisionalState(WebCore::DocumentLoader *)1047 void FrameLoaderClient::revertToProvisionalState(WebCore::DocumentLoader*)
1048 {
1049     m_hasRepresentation = true;
1050 }
1051 
willChangeTitle(WebCore::DocumentLoader *)1052 void FrameLoaderClient::willChangeTitle(WebCore::DocumentLoader*)
1053 {
1054     notImplemented();
1055 }
1056 
didChangeTitle(WebCore::DocumentLoader * l)1057 void FrameLoaderClient::didChangeTitle(WebCore::DocumentLoader *l)
1058 {
1059     setTitle(l->title(), l->url());
1060 }
1061 
canHandleRequest(const ResourceRequest &) const1062 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const
1063 {
1064     notImplemented();
1065     return true;
1066 }
1067 
canShowMIMETypeAsHTML(const String & MIMEType) const1068 bool FrameLoaderClient::canShowMIMETypeAsHTML(const String& MIMEType) const
1069 {
1070     notImplemented();
1071     return false;
1072 }
1073 
canShowMIMEType(const String & type) const1074 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 
representationExistsForURLScheme(const String &) const1082 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const
1083 {
1084     notImplemented();
1085     return false;
1086 }
1087 
generatedMIMETypeForURLScheme(const String &) const1088 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const
1089 {
1090     notImplemented();
1091     return String();
1092 }
1093 
finishedLoading(WebCore::DocumentLoader * documentLoader)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 
provisionalLoadStarted()1109 void FrameLoaderClient::provisionalLoadStarted()
1110 {
1111     notImplemented();
1112 }
1113 
didFinishLoad()1114 void FrameLoaderClient::didFinishLoad() {
1115     notImplemented();
1116 }
1117 
prepareForDataSourceReplacement()1118 void FrameLoaderClient::prepareForDataSourceReplacement()
1119 {
1120     notImplemented();
1121 }
1122 
setTitle(const StringWithDirection & title,const KURL & url)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 
dispatchDidReceiveContentLength(WebCore::DocumentLoader *,unsigned long identifier,int dataLength)1131 void FrameLoaderClient::dispatchDidReceiveContentLength(WebCore::DocumentLoader*, unsigned long identifier, int dataLength)
1132 {
1133     notImplemented();
1134 }
1135 
dispatchDidFinishLoading(WebCore::DocumentLoader * loader,unsigned long identifier)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 
dispatchDidFailLoading(WebCore::DocumentLoader * loader,unsigned long identifier,const ResourceError & error)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 
dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader *,const ResourceRequest &,const ResourceResponse &,int length)1178 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(WebCore::DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length)
1179 {
1180     notImplemented();
1181     return false;
1182 }
1183 
dispatchDidFailProvisionalLoad(const ResourceError & error)1184 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError& error)
1185 {
1186     dispatchDidFailLoad(error);
1187 }
1188 
dispatchDidFailLoad(const ResourceError & error)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 
download(ResourceHandle * handle,const ResourceRequest & request,const ResourceRequest &,const ResourceResponse & response)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 
cancelledError(const ResourceRequest & request)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 
blockedError(const ResourceRequest & request)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 
cannotShowURLError(const ResourceRequest & request)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 
interruptForPolicyChangeError(const ResourceRequest & request)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 
cannotShowMIMETypeError(const ResourceResponse & response)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 
fileDoesNotExistError(const ResourceResponse & response)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 
pluginWillHandleLoadError(const ResourceResponse & response)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 
shouldFallBack(const ResourceError & error)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 
canCachePage() const1296 bool FrameLoaderClient::canCachePage() const
1297 {
1298     return true;
1299 }
1300 
dispatchCreatePage(const NavigationAction &)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 
dispatchUnableToImplementPolicy(const ResourceError &)1315 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&)
1316 {
1317     notImplemented();
1318 }
1319 
setMainDocumentError(WebCore::DocumentLoader *,const ResourceError & error)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 
startDownload(const ResourceRequest & request)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 
updateGlobalHistory()1337 void FrameLoaderClient::updateGlobalHistory()
1338 {
1339     notImplemented();
1340 }
1341 
updateGlobalHistoryRedirectLinks()1342 void FrameLoaderClient::updateGlobalHistoryRedirectLinks()
1343 {
1344     notImplemented();
1345 }
1346 
savePlatformDataToCachedFrame(CachedFrame * cachedFrame)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 
postCommitFrameViewSetup(WebKitWebFrame * frame,FrameView * view,bool resetValues)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 
transitionToCommittedFromCachedFrame(CachedFrame * cachedFrame)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 
transitionToCommittedForNewPage()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 
didSaveToPageCache()1415 void FrameLoaderClient::didSaveToPageCache()
1416 {
1417 }
1418 
didRestoreFromPageCache()1419 void FrameLoaderClient::didRestoreFromPageCache()
1420 {
1421 }
1422 
dispatchDidBecomeFrameset(bool)1423 void FrameLoaderClient::dispatchDidBecomeFrameset(bool)
1424 {
1425 }
1426 
createNetworkingContext()1427 PassRefPtr<FrameNetworkingContext> FrameLoaderClient::createNetworkingContext()
1428 {
1429     return FrameNetworkingContextGtk::create(core(m_frame));
1430 }
1431 
1432 }
1433