5a2c6df2d99ee815d34b1e3a631315babb2d4e77
[WebKit-https.git] / WebKit / gtk / WebCoreSupport / FrameLoaderClientGtk.cpp
1 /*
2  * Copyright (C) 2006 Don Gibson <dgibson77@gmail.com>
3  * Copyright (C) 2006 Zack Rusin <zack@kde.org>
4  * Copyright (C) 2006, 2007 Apple Computer, Inc.  All rights reserved.
5  * Copyright (C) 2007 Trolltech ASA
6  * Copyright (C) 2007 Alp Toker <alp.toker@collabora.co.uk>
7  * Copyright (C) 2007 Holger Hans Peter Freyther
8  * Copyright (C) 2007 Christian Dywan <christian@twotoasts.de>
9  *
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
25  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
29  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
33
34 #include "config.h"
35 #include "FrameLoaderClientGtk.h"
36 #include "DocumentLoader.h"
37 #include "FrameLoader.h"
38 #include "FrameView.h"
39 #include "FrameTree.h"
40 #include "HTMLFormElement.h"
41 #include "HTMLFrameElement.h"
42 #include "HTMLFrameOwnerElement.h"
43 #include "HTMLNames.h"
44 #include "Language.h"
45 #include "MIMETypeRegistry.h"
46 #include "NotImplemented.h"
47 #include "PlatformString.h"
48 #include "ResourceRequest.h"
49 #include "CString.h"
50 #include "ProgressTracker.h"
51 #include "kjs_binding.h"
52 #include "kjs_proxy.h"
53 #include "kjs_window.h"
54 #include "webkitwebview.h"
55 #include "webkitwebframe.h"
56 #include "webkitprivate.h"
57
58 #include <JavaScriptCore/APICast.h>
59 #include <stdio.h>
60 #if PLATFORM(UNIX)
61 #include <sys/utsname.h>
62 #endif
63
64 using namespace WebCore;
65
66 namespace WebKit {
67
68 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
69     : m_frame(frame)
70     , m_userAgent("")
71 {
72     ASSERT(m_frame);
73 }
74
75 static String agentPlatform()
76 {
77 #ifdef GDK_WINDOWING_X11
78     return "X11";
79 #elif defined(GDK_WINDOWING_WIN32)
80     return "Windows";
81 #elif defined(GDK_WINDOWING_QUARTZ)
82     return "Macintosh";
83 #elif defined(GDK_WINDOWING_DIRECTFB)
84     return "DirectFB";
85 #else
86     notImplemented();
87     return "Unknown";
88 #endif
89 }
90
91 static String agentOS()
92 {
93 #if PLATFORM(DARWIN)
94 #if PLATFORM(X86)
95     return "Intel Mac OS X";
96 #else
97     return "PPC Mac OS X";
98 #endif
99 #elif PLATFORM(UNIX)
100     struct utsname name;
101     if (uname(&name) != -1)
102         return String::format("%s %s", name.sysname, name.machine);
103     else
104         return "Unknown";
105 #elif PLATFORM(WIN_OS)
106     // FIXME: Compute the Windows version
107     return "Windows";
108 #else
109     notImplemented();
110     return "Unknown";
111 #endif
112 }
113
114 static String composeUserAgent()
115 {
116     // This is a liberal interpretation of http://www.mozilla.org/build/revised-user-agent-strings.html
117     // See also http://developer.apple.com/internet/safari/faq.html#anchor2
118
119     String ua;
120
121     // Product
122     ua += "Mozilla/5.0";
123
124     // Comment
125     ua += " (";
126     ua += agentPlatform(); // Platform
127     ua += "; U; "; // Security
128     ua += agentOS(); // OS-or-CPU
129     ua += "; ";
130     ua += defaultLanguage(); // Localization information
131     ua += ") ";
132
133     // WebKit Product
134     // FIXME: The WebKit version is hardcoded
135     static const String webKitVersion = "525.1+";
136     ua += "AppleWebKit/" + webKitVersion;
137     ua += " (KHTML, like Gecko, ";
138     // We mention Safari since many broken sites check for it (OmniWeb does this too)
139     // We re-use the WebKit version, though it doesn't seem to matter much in practice
140     ua += "Safari/" + webKitVersion;
141     ua += ") ";
142
143     // Vendor Product
144     ua += g_get_prgname();
145
146     return ua;
147 }
148
149 String FrameLoaderClient::userAgent(const KURL&)
150 {
151     if (m_userAgent.isEmpty())
152         m_userAgent = composeUserAgent();
153
154     return m_userAgent;
155 }
156
157 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
158 {
159     RefPtr<DocumentLoader> loader = new DocumentLoader(request, substituteData);
160     return loader.release();
161 }
162
163 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction,  PassRefPtr<FormState>)
164 {
165     // FIXME: This is surely too simple
166     ASSERT(policyFunction);
167     if (!policyFunction)
168         return;
169     (core(m_frame)->loader()->*policyFunction)(PolicyUse);
170 }
171
172
173 void FrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
174 {
175     FrameLoader *fl = loader->frameLoader();
176     fl->setEncoding(m_response.textEncodingName(), false);
177     fl->addData(data, length);
178 }
179
180 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
181 {
182     notImplemented();
183 }
184
185 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long  identifier, const AuthenticationChallenge&)
186 {
187     notImplemented();
188 }
189
190 void FrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long, ResourceRequest&, const ResourceResponse&)
191 {
192     notImplemented();
193 }
194
195 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&)
196 {
197     notImplemented();
198 }
199
200 void FrameLoaderClient::postProgressStartedNotification()
201 {
202     WebKitWebView* page = getViewFromFrame(m_frame);
203     g_signal_emit_by_name(page, "load-started", m_frame);
204 }
205
206 void FrameLoaderClient::postProgressEstimateChangedNotification()
207 {
208     WebKitWebView* kitPage = getViewFromFrame(m_frame);
209     Page* corePage = core(kitPage);
210
211     g_signal_emit_by_name(kitPage, "load-progress-changed", lround(corePage->progress()->estimatedProgress()*100));
212 }
213
214 void FrameLoaderClient::postProgressFinishedNotification()
215 {
216     WebKitWebView* page = getViewFromFrame(m_frame);
217
218     g_signal_emit_by_name(page, "load-finished", m_frame);
219 }
220
221 void FrameLoaderClient::frameLoaderDestroyed()
222 {
223     m_frame = 0;
224     delete this;
225 }
226
227 void FrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long, const ResourceResponse& response)
228 {
229     m_response = response;
230 }
231
232 void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String&, const ResourceRequest&)
233 {
234     // FIXME: we need to call directly here (comment copied from Qt version)
235     ASSERT(policyFunction);
236     if (!policyFunction)
237         return;
238     (core(m_frame)->loader()->*policyFunction)(PolicyUse);
239 }
240
241 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction&, const ResourceRequest&, const String&)
242 {
243     ASSERT(policyFunction);
244     if (!policyFunction)
245         return;
246     // FIXME: I think Qt version marshals this to another thread so when we
247     // have multi-threaded download, we might need to do the same
248     (core(m_frame)->loader()->*policyFunction)(PolicyIgnore);
249 }
250
251 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest)
252 {
253     ASSERT(policyFunction);
254     if (!policyFunction)
255         return;
256
257     WebKitWebView* page = getViewFromFrame(m_frame);
258     WebKitNetworkRequest* request = webkit_network_request_new(resourceRequest.url().string().utf8().data());
259     WebKitNavigationResponse response;
260
261     g_signal_emit_by_name(page, "navigation-requested", m_frame, request, &response);
262
263     g_object_unref(request);
264
265     if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
266         (core(m_frame)->loader()->*policyFunction)(PolicyIgnore);
267         return;
268     }
269
270     (core(m_frame)->loader()->*policyFunction)(PolicyUse);
271 }
272
273 Widget* FrameLoaderClient::createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool)
274 {
275     notImplemented();
276     return 0;
277 }
278
279 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
280                                                  const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
281 {
282     Frame* coreFrame = core(webFrame());
283
284     ASSERT(core(getViewFromFrame(webFrame())) == coreFrame->page());
285     WebKitWebFrame* gtkFrame = WEBKIT_WEB_FRAME(webkit_web_frame_init_with_web_view(getViewFromFrame(webFrame()), ownerElement));
286     RefPtr<Frame> childFrame(adoptRef(core(gtkFrame)));
287
288     coreFrame->tree()->appendChild(childFrame);
289
290     childFrame->tree()->setName(name);
291     childFrame->init();
292     childFrame->loader()->load(url, referrer, FrameLoadTypeRedirectWithLockedHistory, String(), 0, 0);
293
294     // The frame's onload handler may have removed it from the document.
295     if (!childFrame->tree()->parent())
296         return 0;
297
298     // Propagate the marginwidth/height and scrolling modes to the view.
299     if (ownerElement->hasTagName(HTMLNames::frameTag) || ownerElement->hasTagName(HTMLNames::iframeTag)) {
300         HTMLFrameElement* frameElt = static_cast<HTMLFrameElement*>(ownerElement);
301         if (frameElt->scrollingMode() == ScrollbarAlwaysOff)
302             childFrame->view()->setScrollbarsMode(ScrollbarAlwaysOff);
303         int marginWidth = frameElt->getMarginWidth();
304         int marginHeight = frameElt->getMarginHeight();
305         if (marginWidth != -1)
306             childFrame->view()->setMarginWidth(marginWidth);
307         if (marginHeight != -1)
308             childFrame->view()->setMarginHeight(marginHeight);
309     }
310
311     return childFrame.release();
312 }
313
314 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
315 {
316     notImplemented();
317     return;
318 }
319
320 Widget* FrameLoaderClient::createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL,
321                                                   const Vector<String>& paramNames, const Vector<String>& paramValues)
322 {
323     notImplemented();
324     return 0;
325 }
326
327 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
328 {
329     String type = mimeType;
330     if (type.isEmpty())
331         type = MIMETypeRegistry::getMIMETypeForExtension(url.path().mid(url.path().findRev('.') + 1));
332
333     if (type.isEmpty())
334         return WebCore::ObjectContentFrame;
335
336     if (MIMETypeRegistry::isSupportedImageMIMEType(type))
337         return WebCore::ObjectContentImage;
338
339     if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
340         return WebCore::ObjectContentFrame;
341
342     return WebCore::ObjectContentNone;
343 }
344
345 String FrameLoaderClient::overrideMediaType() const
346 {
347     notImplemented();
348     return String();
349 }
350
351 void FrameLoaderClient::windowObjectCleared()
352 {
353     // Is this obsolete now?
354     g_signal_emit_by_name(m_frame, "cleared");
355
356     Frame* coreFrame = core(webFrame());
357     ASSERT(coreFrame);
358
359     Settings* settings = coreFrame->settings();
360     if (!settings || !settings->isJavaScriptEnabled())
361         return;
362
363     // TODO: Consider using g_signal_has_handler_pending() to avoid the overhead
364     // when there are no handlers.
365     JSGlobalContextRef context = toGlobalRef(coreFrame->scriptProxy()->globalObject()->globalExec());
366     JSObjectRef windowObject = toRef(KJS::Window::retrieve(coreFrame)->getObject());
367     ASSERT(windowObject);
368
369     WebKitWebView* page = getViewFromFrame(m_frame);
370     g_signal_emit_by_name(page, "window-object-cleared", m_frame, context, windowObject);
371
372     // TODO: Re-attach debug clients if present.
373     // The Win port has an example of how we might do this.
374 }
375
376 void FrameLoaderClient::didPerformFirstNavigation() const
377 {
378 }
379
380 void FrameLoaderClient::registerForIconNotification(bool)
381 {
382     notImplemented();
383 }
384
385 void FrameLoaderClient::setMainFrameDocumentReady(bool)
386 {
387     // this is only interesting once we provide an external API for the DOM
388 }
389
390 bool FrameLoaderClient::hasWebView() const
391 {
392     notImplemented();
393     return true;
394 }
395
396 bool FrameLoaderClient::hasFrameView() const
397 {
398     notImplemented();
399     return true;
400 }
401
402 void FrameLoaderClient::dispatchDidFinishLoad()
403 {
404     g_signal_emit_by_name(m_frame, "load-done", true);
405 }
406
407 void FrameLoaderClient::frameLoadCompleted()
408 {
409     notImplemented();
410 }
411
412 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
413 {
414     notImplemented();
415 }
416
417 void FrameLoaderClient::restoreViewState()
418 {
419     notImplemented();
420 }
421
422 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
423 {
424     // FIXME: This is a very simple implementation. More sophisticated
425     // implementation would delegate the decision to a PolicyDelegate.
426     // See mac implementation for example.
427     return item != 0;
428 }
429
430 void FrameLoaderClient::makeDocumentView() { notImplemented(); }
431 void FrameLoaderClient::makeRepresentation(DocumentLoader*) { notImplemented(); }
432 void FrameLoaderClient::forceLayout() { notImplemented(); }
433 void FrameLoaderClient::forceLayoutForNonHTML() { notImplemented(); }
434 void FrameLoaderClient::setCopiesOnScroll() { notImplemented(); }
435 void FrameLoaderClient::detachedFromParent1() { notImplemented(); }
436 void FrameLoaderClient::detachedFromParent2() { notImplemented(); }
437 void FrameLoaderClient::detachedFromParent3() { notImplemented(); }
438 void FrameLoaderClient::detachedFromParent4() { notImplemented(); }
439 void FrameLoaderClient::loadedFromCachedPage() { notImplemented(); }
440 void FrameLoaderClient::dispatchDidHandleOnloadEvents() {notImplemented(); }
441 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() { notImplemented(); }
442 void FrameLoaderClient::dispatchDidCancelClientRedirect() { notImplemented(); }
443 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double) { notImplemented(); }
444 void FrameLoaderClient::dispatchDidChangeLocationWithinPage() { notImplemented(); }
445 void FrameLoaderClient::dispatchWillClose() { notImplemented(); }
446
447 void FrameLoaderClient::dispatchDidReceiveIcon()
448 {
449     WebKitWebView* page = getViewFromFrame(m_frame);
450
451     g_signal_emit_by_name(page, "icon-loaded", m_frame);
452 }
453
454 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
455 {
456 }
457
458 void FrameLoaderClient::dispatchDidReceiveTitle(const String& title)
459 {
460     notImplemented();
461 }
462
463 void FrameLoaderClient::dispatchDidCommitLoad() { notImplemented(); }
464 void FrameLoaderClient::dispatchDidFinishDocumentLoad() { notImplemented(); }
465 void FrameLoaderClient::dispatchDidFirstLayout() { notImplemented(); }
466 void FrameLoaderClient::dispatchShow() { notImplemented(); }
467 void FrameLoaderClient::cancelPolicyCheck() { notImplemented(); }
468 void FrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*) { notImplemented(); }
469 void FrameLoaderClient::revertToProvisionalState(DocumentLoader*) { notImplemented(); }
470 void FrameLoaderClient::clearUnarchivingState(DocumentLoader*) { notImplemented(); }
471 void FrameLoaderClient::willChangeTitle(DocumentLoader*) { notImplemented(); }
472 void FrameLoaderClient::didChangeTitle(DocumentLoader *l) { setTitle(l->title(), l->URL()); }
473 void FrameLoaderClient::finalSetupForReplace(DocumentLoader*) { notImplemented(); }
474 void FrameLoaderClient::setDefersLoading(bool) { notImplemented(); }
475 bool FrameLoaderClient::isArchiveLoadPending(ResourceLoader*) const { notImplemented(); return false; }
476 void FrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader*) { notImplemented(); }
477 void FrameLoaderClient::clearArchivedResources() { notImplemented(); }
478 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const { notImplemented(); return true; }
479 bool FrameLoaderClient::canShowMIMEType(const String&) const { notImplemented(); return true; }
480 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const { notImplemented(); return false; }
481 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const { notImplemented(); return String(); }
482
483 void FrameLoaderClient::finishedLoading(DocumentLoader* documentLoader)
484 {
485     ASSERT(documentLoader->frame());
486     // Setting the encoding on the frame loader is our way to get work done that is normally done
487     // when the first bit of data is received, even for the case of a document with no data (like about:blank).
488     String encoding = documentLoader->overrideEncoding();
489     bool userChosen = !encoding.isNull();
490     if (encoding.isNull())
491         encoding = documentLoader->response().textEncodingName();
492     documentLoader->frameLoader()->setEncoding(encoding, userChosen);
493 }
494
495
496 void FrameLoaderClient::provisionalLoadStarted()
497 {
498     notImplemented();
499 }
500
501 void FrameLoaderClient::didFinishLoad() {
502     notImplemented();
503 }
504
505 void FrameLoaderClient::prepareForDataSourceReplacement() { notImplemented(); }
506
507 void FrameLoaderClient::setTitle(const String& title, const KURL& url)
508 {
509     WebKitWebView* page = getViewFromFrame(m_frame);
510
511     CString titleString = title.utf8();
512     DeprecatedCString urlString = url.prettyURL().utf8();
513     g_signal_emit_by_name(m_frame, "title-changed", titleString.data(), urlString.data());
514
515     if (m_frame == webkit_web_view_get_main_frame(page))
516         g_signal_emit_by_name(page, "title-changed", titleString.data(), urlString.data());
517 }
518
519 void FrameLoaderClient::setDocumentViewFromCachedPage(WebCore::CachedPage*) { notImplemented(); }
520 void FrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long  identifier, int lengthReceived) { notImplemented(); }
521 void FrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long  identifier) { notImplemented(); }
522 void FrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long  identifier, const ResourceError&) { notImplemented(); }
523 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) { notImplemented(); return false; }
524
525 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError&)
526 {
527     g_signal_emit_by_name(m_frame, "load-done", false);
528 }
529
530 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError&)
531 {
532     g_signal_emit_by_name(m_frame, "load-done", false);
533 }
534
535 void FrameLoaderClient::download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) { notImplemented(); }
536 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
537 ResourceError FrameLoaderClient::blockedError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
538 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
539 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
540 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse&) { notImplemented(); return ResourceError(); }
541 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse&) { notImplemented(); return ResourceError(); }
542 bool FrameLoaderClient::shouldFallBack(const ResourceError&) { notImplemented(); return false; }
543 bool FrameLoaderClient::willUseArchive(ResourceLoader*, const ResourceRequest&, const KURL& originalURL) const { notImplemented(); return false; }
544 void FrameLoaderClient::saveDocumentViewToCachedPage(CachedPage*) { notImplemented(); }
545 bool FrameLoaderClient::canCachePage() const { notImplemented(); return false; }
546 Frame* FrameLoaderClient::dispatchCreatePage() { notImplemented(); return 0; }
547 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&) { notImplemented(); }
548 void FrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError&) { notImplemented(); }
549 void FrameLoaderClient::startDownload(const ResourceRequest&) { notImplemented(); }
550 void FrameLoaderClient::updateGlobalHistoryForStandardLoad(const KURL&) { notImplemented(); }
551 void FrameLoaderClient::updateGlobalHistoryForReload(const KURL&) { notImplemented(); }
552
553 }