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