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