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(), >kWidget);
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