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>
10 * All rights reserved.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
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.
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.
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"
45 #include "MIMETypeRegistry.h"
46 #include "NotImplemented.h"
47 #include "PlatformString.h"
48 #include "ResourceRequest.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"
58 #include <JavaScriptCore/APICast.h>
61 #include <sys/utsname.h>
64 using namespace WebCore;
68 FrameLoaderClient::FrameLoaderClient(WebKitWebFrame* frame)
75 static String agentPlatform()
77 #ifdef GDK_WINDOWING_X11
79 #elif defined(GDK_WINDOWING_WIN32)
81 #elif defined(GDK_WINDOWING_QUARTZ)
83 #elif defined(GDK_WINDOWING_DIRECTFB)
91 static String agentOS()
95 return "Intel Mac OS X";
97 return "PPC Mac OS X";
101 if (uname(&name) != -1)
102 return String::format("%s %s", name.sysname, name.machine);
105 #elif PLATFORM(WIN_OS)
106 // FIXME: Compute the Windows version
114 static String composeUserAgent()
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
126 ua += agentPlatform(); // Platform
127 ua += "; U; "; // Security
128 ua += agentOS(); // OS-or-CPU
130 ua += defaultLanguage(); // Localization information
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;
144 ua += g_get_prgname();
149 String FrameLoaderClient::userAgent(const KURL&)
151 if (m_userAgent.isEmpty())
152 m_userAgent = composeUserAgent();
157 WTF::PassRefPtr<WebCore::DocumentLoader> FrameLoaderClient::createDocumentLoader(const WebCore::ResourceRequest& request, const SubstituteData& substituteData)
159 RefPtr<DocumentLoader> loader = new DocumentLoader(request, substituteData);
160 return loader.release();
163 void FrameLoaderClient::dispatchWillSubmitForm(FramePolicyFunction policyFunction, PassRefPtr<FormState>)
165 // FIXME: This is surely too simple
166 ASSERT(policyFunction);
169 (core(m_frame)->loader()->*policyFunction)(PolicyUse);
173 void FrameLoaderClient::committedLoad(DocumentLoader* loader, const char* data, int length)
175 FrameLoader *fl = loader->frameLoader();
176 fl->setEncoding(m_response.textEncodingName(), false);
177 fl->addData(data, length);
180 void FrameLoaderClient::dispatchDidReceiveAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
185 void FrameLoaderClient::dispatchDidCancelAuthenticationChallenge(DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
190 void FrameLoaderClient::dispatchWillSendRequest(DocumentLoader*, unsigned long, ResourceRequest&, const ResourceResponse&)
195 void FrameLoaderClient::assignIdentifierToInitialRequest(unsigned long identifier, DocumentLoader*, const ResourceRequest&)
200 void FrameLoaderClient::postProgressStartedNotification()
202 WebKitWebView* page = getViewFromFrame(m_frame);
203 g_signal_emit_by_name(page, "load_started", m_frame);
206 void FrameLoaderClient::postProgressEstimateChangedNotification()
208 WebKitWebView* kitPage = getViewFromFrame(m_frame);
209 Page* corePage = core(kitPage);
211 g_signal_emit_by_name(kitPage, "load_progress_changed", lround(corePage->progress()->estimatedProgress()*100));
214 void FrameLoaderClient::postProgressFinishedNotification()
216 WebKitWebView* page = getViewFromFrame(m_frame);
218 g_signal_emit_by_name(page, "load_finished", m_frame);
221 void FrameLoaderClient::frameLoaderDestroyed()
227 void FrameLoaderClient::dispatchDidReceiveResponse(DocumentLoader*, unsigned long, const ResourceResponse& response)
229 m_response = response;
232 void FrameLoaderClient::dispatchDecidePolicyForMIMEType(FramePolicyFunction policyFunction, const String&, const ResourceRequest&)
234 // FIXME: we need to call directly here (comment copied from Qt version)
235 ASSERT(policyFunction);
238 (core(m_frame)->loader()->*policyFunction)(PolicyUse);
241 void FrameLoaderClient::dispatchDecidePolicyForNewWindowAction(FramePolicyFunction policyFunction, const NavigationAction&, const ResourceRequest&, const String&)
243 ASSERT(policyFunction);
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);
251 void FrameLoaderClient::dispatchDecidePolicyForNavigationAction(FramePolicyFunction policyFunction, const NavigationAction& action, const ResourceRequest& resourceRequest)
253 ASSERT(policyFunction);
257 WebKitWebView* page = getViewFromFrame(m_frame);
258 WebKitNetworkRequest* request = webkit_network_request_new(resourceRequest.url().url().utf8().data());
259 WebKitNavigationResponse response;
261 g_signal_emit_by_name(page, "navigation_requested", m_frame, request, &response);
263 g_object_unref(request);
265 if (response == WEBKIT_NAVIGATION_RESPONSE_IGNORE) {
266 (core(m_frame)->loader()->*policyFunction)(PolicyIgnore);
270 (core(m_frame)->loader()->*policyFunction)(PolicyUse);
273 Widget* FrameLoaderClient::createPlugin(const IntSize&, Element*, const KURL&, const Vector<String>&, const Vector<String>&, const String&, bool)
279 PassRefPtr<Frame> FrameLoaderClient::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement,
280 const String& referrer, bool allowsScrolling, int marginWidth, int marginHeight)
282 Frame* coreFrame = core(webFrame());
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)));
288 coreFrame->tree()->appendChild(childFrame);
290 childFrame->tree()->setName(name);
292 childFrame->loader()->load(url, referrer, FrameLoadTypeRedirectWithLockedHistory, String(), 0, 0);
294 // The frame's onload handler may have removed it from the document.
295 if (!childFrame->tree()->parent())
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);
311 return childFrame.release();
314 void FrameLoaderClient::redirectDataToPlugin(Widget* pluginWidget)
320 Widget* FrameLoaderClient::createJavaAppletWidget(const IntSize&, Element*, const KURL& baseURL,
321 const Vector<String>& paramNames, const Vector<String>& paramValues)
327 ObjectContentType FrameLoaderClient::objectContentType(const KURL& url, const String& mimeType)
329 String type = mimeType;
331 type = MIMETypeRegistry::getMIMETypeForExtension(url.path().mid(url.path().findRev('.') + 1));
334 return WebCore::ObjectContentFrame;
336 if (MIMETypeRegistry::isSupportedImageMIMEType(type))
337 return WebCore::ObjectContentImage;
339 if (MIMETypeRegistry::isSupportedNonImageMIMEType(type))
340 return WebCore::ObjectContentFrame;
342 return WebCore::ObjectContentNone;
345 String FrameLoaderClient::overrideMediaType() const
351 void FrameLoaderClient::windowObjectCleared()
353 // Is this obsolete now?
354 g_signal_emit_by_name(m_frame, "cleared");
356 Frame* coreFrame = core(webFrame());
359 Settings* settings = coreFrame->settings();
360 if (!settings || !settings->isJavaScriptEnabled())
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()->interpreter()->globalExec());
366 JSObjectRef windowObject = toRef(KJS::Window::retrieve(coreFrame)->getObject());
367 ASSERT(windowObject);
369 WebKitWebView* page = getViewFromFrame(m_frame);
370 g_signal_emit_by_name(page, "window_object_cleared", m_frame, context, windowObject);
372 // TODO: Re-attach debug clients if present.
373 // The Win port has an example of how we might do this.
376 void FrameLoaderClient::didPerformFirstNavigation() const
380 void FrameLoaderClient::registerForIconNotification(bool)
385 void FrameLoaderClient::setMainFrameDocumentReady(bool)
387 // this is only interesting once we provide an external API for the DOM
390 bool FrameLoaderClient::hasWebView() const
396 bool FrameLoaderClient::hasFrameView() const
402 void FrameLoaderClient::dispatchDidFinishLoad()
404 g_signal_emit_by_name(m_frame, "load_done", true);
407 void FrameLoaderClient::frameLoadCompleted()
412 void FrameLoaderClient::saveViewStateToItem(HistoryItem*)
417 void FrameLoaderClient::restoreViewState()
422 bool FrameLoaderClient::shouldGoToHistoryItem(HistoryItem* item) const
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.
430 bool FrameLoaderClient::privateBrowsingEnabled() const { notImplemented(); return false; }
431 void FrameLoaderClient::makeDocumentView() { notImplemented(); }
432 void FrameLoaderClient::makeRepresentation(DocumentLoader*) { notImplemented(); }
433 void FrameLoaderClient::forceLayout() { notImplemented(); }
434 void FrameLoaderClient::forceLayoutForNonHTML() { notImplemented(); }
435 void FrameLoaderClient::setCopiesOnScroll() { notImplemented(); }
436 void FrameLoaderClient::detachedFromParent1() { notImplemented(); }
437 void FrameLoaderClient::detachedFromParent2() { notImplemented(); }
438 void FrameLoaderClient::detachedFromParent3() { notImplemented(); }
439 void FrameLoaderClient::detachedFromParent4() { notImplemented(); }
440 void FrameLoaderClient::loadedFromCachedPage() { notImplemented(); }
441 void FrameLoaderClient::dispatchDidHandleOnloadEvents() {notImplemented(); }
442 void FrameLoaderClient::dispatchDidReceiveServerRedirectForProvisionalLoad() { notImplemented(); }
443 void FrameLoaderClient::dispatchDidCancelClientRedirect() { notImplemented(); }
444 void FrameLoaderClient::dispatchWillPerformClientRedirect(const KURL&, double, double) { notImplemented(); }
445 void FrameLoaderClient::dispatchDidChangeLocationWithinPage() { notImplemented(); }
446 void FrameLoaderClient::dispatchWillClose() { notImplemented(); }
448 void FrameLoaderClient::dispatchDidReceiveIcon()
450 WebKitWebView* page = getViewFromFrame(m_frame);
452 g_signal_emit_by_name(page, "icon_loaded", m_frame);
455 void FrameLoaderClient::dispatchDidStartProvisionalLoad()
459 void FrameLoaderClient::dispatchDidReceiveTitle(const String& title)
464 void FrameLoaderClient::dispatchDidCommitLoad() { notImplemented(); }
465 void FrameLoaderClient::dispatchDidFinishDocumentLoad() { notImplemented(); }
466 void FrameLoaderClient::dispatchDidFirstLayout() { notImplemented(); }
467 void FrameLoaderClient::dispatchShow() { notImplemented(); }
468 void FrameLoaderClient::cancelPolicyCheck() { notImplemented(); }
469 void FrameLoaderClient::dispatchDidLoadMainResource(DocumentLoader*) { notImplemented(); }
470 void FrameLoaderClient::revertToProvisionalState(DocumentLoader*) { notImplemented(); }
471 void FrameLoaderClient::clearUnarchivingState(DocumentLoader*) { notImplemented(); }
472 void FrameLoaderClient::willChangeTitle(DocumentLoader*) { notImplemented(); }
473 void FrameLoaderClient::didChangeTitle(DocumentLoader *l) { setTitle(l->title(), l->URL()); }
474 void FrameLoaderClient::finalSetupForReplace(DocumentLoader*) { notImplemented(); }
475 void FrameLoaderClient::setDefersLoading(bool) { notImplemented(); }
476 bool FrameLoaderClient::isArchiveLoadPending(ResourceLoader*) const { notImplemented(); return false; }
477 void FrameLoaderClient::cancelPendingArchiveLoad(ResourceLoader*) { notImplemented(); }
478 void FrameLoaderClient::clearArchivedResources() { notImplemented(); }
479 bool FrameLoaderClient::canHandleRequest(const ResourceRequest&) const { notImplemented(); return true; }
480 bool FrameLoaderClient::canShowMIMEType(const String&) const { notImplemented(); return true; }
481 bool FrameLoaderClient::representationExistsForURLScheme(const String&) const { notImplemented(); return false; }
482 String FrameLoaderClient::generatedMIMETypeForURLScheme(const String&) const { notImplemented(); return String(); }
484 void FrameLoaderClient::finishedLoading(DocumentLoader* documentLoader)
486 ASSERT(documentLoader->frame());
487 // Setting the encoding on the frame loader is our way to get work done that is normally done
488 // when the first bit of data is received, even for the case of a document with no data (like about:blank).
489 String encoding = documentLoader->overrideEncoding();
490 bool userChosen = !encoding.isNull();
491 if (encoding.isNull())
492 encoding = documentLoader->response().textEncodingName();
493 documentLoader->frameLoader()->setEncoding(encoding, userChosen);
497 void FrameLoaderClient::provisionalLoadStarted()
502 void FrameLoaderClient::didFinishLoad() {
506 void FrameLoaderClient::prepareForDataSourceReplacement() { notImplemented(); }
508 void FrameLoaderClient::setTitle(const String& title, const KURL& url)
510 WebKitWebView* page = getViewFromFrame(m_frame);
512 CString titleString = title.utf8();
513 DeprecatedCString urlString = url.prettyURL().utf8();
514 g_signal_emit_by_name(m_frame, "title_changed", titleString.data(), urlString.data());
516 if (m_frame == webkit_web_view_get_main_frame(page))
517 g_signal_emit_by_name(page, "title_changed", titleString.data(), urlString.data());
520 void FrameLoaderClient::setDocumentViewFromCachedPage(WebCore::CachedPage*) { notImplemented(); }
521 void FrameLoaderClient::dispatchDidReceiveContentLength(DocumentLoader*, unsigned long identifier, int lengthReceived) { notImplemented(); }
522 void FrameLoaderClient::dispatchDidFinishLoading(DocumentLoader*, unsigned long identifier) { notImplemented(); }
523 void FrameLoaderClient::dispatchDidFailLoading(DocumentLoader*, unsigned long identifier, const ResourceError&) { notImplemented(); }
524 bool FrameLoaderClient::dispatchDidLoadResourceFromMemoryCache(DocumentLoader*, const ResourceRequest&, const ResourceResponse&, int length) { notImplemented(); return false; }
526 void FrameLoaderClient::dispatchDidFailProvisionalLoad(const ResourceError&)
528 g_signal_emit_by_name(m_frame, "load_done", false);
531 void FrameLoaderClient::dispatchDidFailLoad(const ResourceError&)
533 g_signal_emit_by_name(m_frame, "load_done", false);
536 void FrameLoaderClient::download(ResourceHandle*, const ResourceRequest&, const ResourceRequest&, const ResourceResponse&) { notImplemented(); }
537 ResourceError FrameLoaderClient::cancelledError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
538 ResourceError FrameLoaderClient::blockedError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
539 ResourceError FrameLoaderClient::cannotShowURLError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
540 ResourceError FrameLoaderClient::interruptForPolicyChangeError(const ResourceRequest&) { notImplemented(); return ResourceError(); }
541 ResourceError FrameLoaderClient::cannotShowMIMETypeError(const ResourceResponse&) { notImplemented(); return ResourceError(); }
542 ResourceError FrameLoaderClient::fileDoesNotExistError(const ResourceResponse&) { notImplemented(); return ResourceError(); }
543 bool FrameLoaderClient::shouldFallBack(const ResourceError&) { notImplemented(); return false; }
544 bool FrameLoaderClient::willUseArchive(ResourceLoader*, const ResourceRequest&, const KURL& originalURL) const { notImplemented(); return false; }
545 void FrameLoaderClient::saveDocumentViewToCachedPage(CachedPage*) { notImplemented(); }
546 bool FrameLoaderClient::canCachePage() const { notImplemented(); return false; }
547 Frame* FrameLoaderClient::dispatchCreatePage() { notImplemented(); return 0; }
548 void FrameLoaderClient::dispatchUnableToImplementPolicy(const ResourceError&) { notImplemented(); }
549 void FrameLoaderClient::setMainDocumentError(DocumentLoader*, const ResourceError&) { notImplemented(); }
550 void FrameLoaderClient::startDownload(const ResourceRequest&) { notImplemented(); }
551 void FrameLoaderClient::updateGlobalHistoryForStandardLoad(const KURL&) { notImplemented(); }
552 void FrameLoaderClient::updateGlobalHistoryForReload(const KURL&) { notImplemented(); }