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