2 * Copyright (C) 2009 Google Inc. All rights reserved.
3 * Copyright (C) 2011 Apple Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 #include "FrameLoaderClientImpl.h"
35 #include "BackForwardListChromium.h"
38 #include "DocumentLoader.h"
39 #include "FormState.h"
40 #include "FrameLoader.h"
41 #include "FrameLoadRequest.h"
42 #include "FrameNetworkingContextImpl.h"
43 #include "FrameView.h"
44 #include "HTTPParsers.h"
45 #include "HistoryItem.h"
46 #include "HitTestResult.h"
47 #include "HTMLAppletElement.h"
48 #include "HTMLFormElement.h" // needed by FormState.h
49 #include "HTMLNames.h"
50 #include "MIMETypeRegistry.h"
51 #include "MouseEvent.h"
53 #include "PlatformString.h"
54 #include "PluginData.h"
55 #include "PluginDataChromium.h"
56 #include "ProgressTracker.h"
57 #include "ResourceHandleInternal.h"
58 #include "ResourceLoader.h"
60 #include "StringExtras.h"
61 #include "WebDataSourceImpl.h"
62 #include "WebDevToolsAgentPrivate.h"
63 #include "WebDocument.h"
64 #include "WebFormElement.h"
65 #include "WebFrameClient.h"
66 #include "WebFrameImpl.h"
68 #include "WebKitPlatformSupport.h"
69 #include "WebMimeRegistry.h"
71 #include "WebPermissionClient.h"
72 #include "WebPlugin.h"
73 #include "WebPluginContainerImpl.h"
74 #include "WebPluginLoadObserver.h"
75 #include "WebPluginParams.h"
76 #include "WebSecurityOrigin.h"
78 #include "WebURLError.h"
79 #include "WebVector.h"
80 #include "WebViewClient.h"
81 #include "WebViewImpl.h"
82 #include "WindowFeatures.h"
83 #include "WrappedResourceRequest.h"
84 #include "WrappedResourceResponse.h"
85 #include <wtf/text/CString.h>
91 using namespace WebCore;
95 // Domain for internal error codes.
96 static const char internalErrorDomain[] = "WebKit";
98 // An internal error code. Used to note a policy change error resulting from
99 // dispatchDecidePolicyForMIMEType not passing the PolicyUse option.
101 PolicyChangeError = -10000,
104 FrameLoaderClientImpl::FrameLoaderClientImpl(WebFrameImpl* frame)
106 , m_hasRepresentation(false)
107 , m_sentInitialResponseToPlugin(false)
108 , m_nextNavigationPolicy(WebNavigationPolicyIgnore)
112 FrameLoaderClientImpl::~FrameLoaderClientImpl()
116 void FrameLoaderClientImpl::frameLoaderDestroyed()
118 // When the WebFrame was created, it had an extra reference given to it on
119 // behalf of the Frame. Since the WebFrame owns us, this extra ref also
120 // serves to keep us alive until the FrameLoader is done with us. The
121 // FrameLoader calls this method when it's going away. Therefore, we balance
122 // out that extra reference, which may cause 'this' to be deleted.
123 m_webFrame->closing();
127 void FrameLoaderClientImpl::dispatchDidClearWindowObjectInWorld(DOMWrapperWorld*)
129 if (m_webFrame->client())
130 m_webFrame->client()->didClearWindowObject(m_webFrame);
132 WebViewImpl* webview = m_webFrame->viewImpl();
133 if (webview->devToolsAgentPrivate())
134 webview->devToolsAgentPrivate()->didClearWindowObject(m_webFrame);
137 void FrameLoaderClientImpl::documentElementAvailable()
139 if (m_webFrame->client())
140 m_webFrame->client()->didCreateDocumentElement(m_webFrame);
144 void FrameLoaderClientImpl::didCreateScriptContext(v8::Handle<v8::Context> context, int worldId)
146 if (m_webFrame->client())
147 m_webFrame->client()->didCreateScriptContext(m_webFrame, context, worldId);
150 void FrameLoaderClientImpl::willReleaseScriptContext(v8::Handle<v8::Context> context, int worldId)
152 if (m_webFrame->client())
153 m_webFrame->client()->willReleaseScriptContext(m_webFrame, context, worldId);
157 bool FrameLoaderClientImpl::allowScriptExtension(const String& extensionName,
160 WebViewImpl* webview = m_webFrame->viewImpl();
161 if (webview && webview->permissionClient())
162 return webview->permissionClient()->allowScriptExtension(m_webFrame, extensionName, extensionGroup);
167 void FrameLoaderClientImpl::didPerformFirstNavigation() const
171 void FrameLoaderClientImpl::registerForIconNotification(bool)
175 void FrameLoaderClientImpl::didChangeScrollOffset()
177 if (m_webFrame->client())
178 m_webFrame->client()->didChangeScrollOffset(m_webFrame);
181 bool FrameLoaderClientImpl::allowScript(bool enabledPerSettings)
183 WebViewImpl* webview = m_webFrame->viewImpl();
184 if (webview && webview->permissionClient())
185 return webview->permissionClient()->allowScript(m_webFrame, enabledPerSettings);
187 return enabledPerSettings;
190 bool FrameLoaderClientImpl::allowScriptFromSource(bool enabledPerSettings, const KURL& scriptURL)
192 WebViewImpl* webview = m_webFrame->viewImpl();
193 if (webview && webview->permissionClient())
194 return webview->permissionClient()->allowScriptFromSource(m_webFrame, enabledPerSettings, scriptURL);
196 return enabledPerSettings;
199 bool FrameLoaderClientImpl::allowPlugins(bool enabledPerSettings)
201 WebViewImpl* webview = m_webFrame->viewImpl();
202 if (webview && webview->permissionClient())
203 return webview->permissionClient()->allowPlugins(m_webFrame, enabledPerSettings);
205 return enabledPerSettings;
208 bool FrameLoaderClientImpl::allowImage(bool enabledPerSettings, const KURL& imageURL)
210 WebViewImpl* webview = m_webFrame->viewImpl();
211 if (webview && webview->permissionClient())
212 return webview->permissionClient()->allowImage(m_webFrame, enabledPerSettings, imageURL);
214 return enabledPerSettings;
217 bool FrameLoaderClientImpl::allowDisplayingInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
219 WebViewImpl* webview = m_webFrame->viewImpl();
220 if (webview && webview->permissionClient())
221 return webview->permissionClient()->allowDisplayingInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));
223 return enabledPerSettings;
226 bool FrameLoaderClientImpl::allowRunningInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
228 WebViewImpl* webview = m_webFrame->viewImpl();
229 if (webview && webview->permissionClient())
230 return webview->permissionClient()->allowRunningInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));
232 return enabledPerSettings;
235 void FrameLoaderClientImpl::didNotAllowScript()
237 WebViewImpl* webview = m_webFrame->viewImpl();
238 if (webview && webview->permissionClient())
239 webview->permissionClient()->didNotAllowScript(m_webFrame);
242 void FrameLoaderClientImpl::didNotAllowPlugins()
244 WebViewImpl* webview = m_webFrame->viewImpl();
245 if (webview && webview->permissionClient())
246 webview->permissionClient()->didNotAllowPlugins(m_webFrame);
250 bool FrameLoaderClientImpl::hasWebView() const
252 return m_webFrame->viewImpl();
255 bool FrameLoaderClientImpl::hasFrameView() const
257 // The Mac port has this notion of a WebFrameView, which seems to be
258 // some wrapper around an NSView. Since our equivalent is HWND, I guess
259 // we have a "frameview" whenever we have the toplevel HWND.
260 return m_webFrame->viewImpl();
263 void FrameLoaderClientImpl::makeDocumentView()
265 m_webFrame->createFrameView();
268 void FrameLoaderClientImpl::makeRepresentation(DocumentLoader*)
270 m_hasRepresentation = true;
273 void FrameLoaderClientImpl::forceLayout()
278 void FrameLoaderClientImpl::forceLayoutForNonHTML()
283 void FrameLoaderClientImpl::setCopiesOnScroll()
288 void FrameLoaderClientImpl::detachedFromParent2()
290 // Nothing to do here.
293 void FrameLoaderClientImpl::detachedFromParent3()
295 // If we were reading data into a plugin, drop our reference to it. If we
296 // don't do this then it may end up out-living the rest of the page, which
297 // leads to problems if the plugin's destructor tries to script things.
300 // Close down the proxy. The purpose of this change is to make the
301 // call to ScriptController::clearWindowShell a no-op when called from
302 // Frame::pageDestroyed. Without this change, this call to clearWindowShell
303 // will cause a crash. If you remove/modify this, just ensure that you can
304 // go to a page and then navigate to a new page without getting any asserts
306 m_webFrame->frame()->script()->proxy()->clearForClose();
308 // Alert the client that the frame is being detached. This is the last
309 // chance we have to communicate with the client.
310 if (m_webFrame->client())
311 m_webFrame->client()->frameDetached(m_webFrame);
313 // Stop communicating with the WebFrameClient at this point since we are no
314 // longer associated with the Page.
315 m_webFrame->setClient(0);
318 // This function is responsible for associating the |identifier| with a given
319 // subresource load. The following functions that accept an |identifier| are
320 // called for each subresource, so they should not be dispatched to the
322 void FrameLoaderClientImpl::assignIdentifierToInitialRequest(
323 unsigned long identifier, DocumentLoader* loader,
324 const ResourceRequest& request)
326 if (m_webFrame->client()) {
327 WrappedResourceRequest webreq(request);
328 m_webFrame->client()->assignIdentifierToRequest(
329 m_webFrame, identifier, webreq);
333 // If the request being loaded by |loader| is a frame, update the ResourceType.
334 // A subresource in this context is anything other than a frame --
335 // this includes images and xmlhttp requests. It is important to note that a
336 // subresource is NOT limited to stuff loaded through the frame's subresource
337 // loader. Synchronous xmlhttp requests for example, do not go through the
338 // subresource loader, but we still label them as TargetIsSubresource.
340 // The important edge cases to consider when modifying this function are
341 // how synchronous resource loads are treated during load/unload threshold.
342 static void setTargetTypeFromLoader(ResourceRequest& request, DocumentLoader* loader)
344 if (loader == loader->frameLoader()->provisionalDocumentLoader()) {
345 ResourceRequest::TargetType type;
346 if (loader->frameLoader()->isLoadingMainFrame())
347 type = ResourceRequest::TargetIsMainFrame;
349 type = ResourceRequest::TargetIsSubframe;
350 request.setTargetType(type);
354 void FrameLoaderClientImpl::dispatchWillSendRequest(
355 DocumentLoader* loader, unsigned long identifier, ResourceRequest& request,
356 const ResourceResponse& redirectResponse)
359 // We want to distinguish between a request for a document to be loaded into
360 // the main frame, a sub-frame, or the sub-objects in that document.
361 setTargetTypeFromLoader(request, loader);
363 // Avoid repeating a form submission when navigating back or forward.
364 if (loader == loader->frameLoader()->provisionalDocumentLoader()
365 && request.httpMethod() == "POST"
366 && isBackForwardLoadType(loader->frameLoader()->loadType()))
367 request.setCachePolicy(ReturnCacheDataDontLoad);
370 // FrameLoader::loadEmptyDocumentSynchronously() creates an empty document
371 // with no URL. We don't like that, so we'll rename it to about:blank.
372 if (request.url().isEmpty())
373 request.setURL(KURL(ParsedURLString, "about:blank"));
374 if (request.firstPartyForCookies().isEmpty())
375 request.setFirstPartyForCookies(KURL(ParsedURLString, "about:blank"));
377 // Give the WebFrameClient a crack at the request.
378 if (m_webFrame->client()) {
379 WrappedResourceRequest webreq(request);
380 WrappedResourceResponse webresp(redirectResponse);
381 m_webFrame->client()->willSendRequest(
382 m_webFrame, identifier, webreq, webresp);
386 bool FrameLoaderClientImpl::shouldUseCredentialStorage(
387 DocumentLoader*, unsigned long identifier)
390 // Intended to pass through to a method on the resource load delegate.
391 // If implemented, that method controls whether the browser should ask the
392 // networking layer for a stored default credential for the page (say from
393 // the Mac OS keychain). If the method returns false, the user should be
394 // presented with an authentication challenge whether or not the networking
395 // layer has a credential stored.
396 // This returns true for backward compatibility: the ability to override the
397 // system credential store is new. (Actually, not yet fully implemented in
398 // WebKit, as of this writing.)
402 void FrameLoaderClientImpl::dispatchDidReceiveAuthenticationChallenge(
403 DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
408 void FrameLoaderClientImpl::dispatchDidCancelAuthenticationChallenge(
409 DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
414 void FrameLoaderClientImpl::dispatchDidReceiveResponse(DocumentLoader* loader,
415 unsigned long identifier,
416 const ResourceResponse& response)
418 if (m_webFrame->client()) {
419 WrappedResourceResponse webresp(response);
420 m_webFrame->client()->didReceiveResponse(m_webFrame, identifier, webresp);
424 void FrameLoaderClientImpl::dispatchDidReceiveContentLength(
425 DocumentLoader* loader,
426 unsigned long identifier,
431 // Called when a particular resource load completes
432 void FrameLoaderClientImpl::dispatchDidFinishLoading(DocumentLoader* loader,
433 unsigned long identifier)
435 if (m_webFrame->client())
436 m_webFrame->client()->didFinishResourceLoad(m_webFrame, identifier);
439 void FrameLoaderClientImpl::dispatchDidFailLoading(DocumentLoader* loader,
440 unsigned long identifier,
441 const ResourceError& error)
443 if (m_webFrame->client())
444 m_webFrame->client()->didFailResourceLoad(m_webFrame, identifier, error);
447 void FrameLoaderClientImpl::dispatchDidFinishDocumentLoad()
449 if (m_webFrame->client())
450 m_webFrame->client()->didFinishDocumentLoad(m_webFrame);
453 bool FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
454 DocumentLoader* loader,
455 const ResourceRequest& request,
456 const ResourceResponse& response,
459 if (m_webFrame->client()) {
460 WrappedResourceRequest webreq(request);
461 WrappedResourceResponse webresp(response);
462 m_webFrame->client()->didLoadResourceFromMemoryCache(
463 m_webFrame, webreq, webresp);
465 return false; // Do not suppress remaining notifications
468 void FrameLoaderClientImpl::dispatchDidHandleOnloadEvents()
470 if (m_webFrame->client())
471 m_webFrame->client()->didHandleOnloadEvents(m_webFrame);
476 // We want to keep track of the chain of redirects that occur during page
477 // loading. There are two types of redirects, server redirects which are HTTP
478 // response codes, and client redirects which are document.location= and meta
481 // This outlines the callbacks that we get in different redirect situations,
482 // and how each call modifies the redirect chain.
486 // dispatchDidStartProvisionalLoad() -> adds URL to the redirect list
487 // dispatchDidCommitLoad() -> DISPATCHES & clears list
489 // Server redirect (success)
490 // -------------------------
491 // dispatchDidStartProvisionalLoad() -> adds source URL
492 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL
493 // dispatchDidCommitLoad() -> DISPATCHES
495 // Client redirect (success)
496 // -------------------------
498 // dispatchWillPerformClientRedirect() -> saves expected redirect
499 // dispatchDidStartProvisionalLoad() -> appends redirect source (since
500 // it matches the expected redirect)
501 // and the current page as the dest)
502 // dispatchDidCancelClientRedirect() -> clears expected redirect
503 // dispatchDidCommitLoad() -> DISPATCHES
505 // Client redirect (cancelled)
506 // (e.g meta-refresh trumped by manual doc.location change, or just cancelled
507 // because a link was clicked that requires the meta refresh to be rescheduled
508 // (the SOURCE URL may have changed).
509 // ---------------------------
510 // dispatchDidCancelClientRedirect() -> clears expected redirect
511 // dispatchDidStartProvisionalLoad() -> adds only URL to redirect list
512 // dispatchDidCommitLoad() -> DISPATCHES & clears list
513 // rescheduled ? dispatchWillPerformClientRedirect() -> saves expected redirect
516 // Client redirect (failure)
517 // -------------------------
519 // dispatchWillPerformClientRedirect() -> saves expected redirect
520 // dispatchDidStartProvisionalLoad() -> appends redirect source (since
521 // it matches the expected redirect)
522 // and the current page as the dest)
523 // dispatchDidCancelClientRedirect()
524 // dispatchDidFailProvisionalLoad()
526 // Load 1 -> Server redirect to 2 -> client redirect to 3 -> server redirect to 4
527 // ------------------------------------------------------------------------------
528 // dispatchDidStartProvisionalLoad() -> adds source URL 1
529 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL 2
530 // dispatchDidCommitLoad() -> DISPATCHES 1+2
531 // -- begin client redirect and NEW DATA SOURCE
532 // dispatchWillPerformClientRedirect() -> saves expected redirect
533 // dispatchDidStartProvisionalLoad() -> appends URL 2 and URL 3
534 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> appends destination URL 4
535 // dispatchDidCancelClientRedirect() -> clears expected redirect
536 // dispatchDidCommitLoad() -> DISPATCHES
538 // Interesting case with multiple location changes involving anchors.
539 // Load page 1 containing future client-redirect (back to 1, e.g meta refresh) > Click
540 // on a link back to the same page (i.e an anchor href) >
541 // client-redirect finally fires (with new source, set to 1#anchor)
542 // -----------------------------------------------------------------------------
543 // dispatchWillPerformClientRedirect(non-zero 'interval' param) -> saves expected redirect
544 // -- click on anchor href
545 // dispatchDidCancelClientRedirect() -> clears expected redirect
546 // dispatchDidStartProvisionalLoad() -> adds 1#anchor source
547 // dispatchDidCommitLoad() -> DISPATCHES 1#anchor
548 // dispatchWillPerformClientRedirect() -> saves exp. source (1#anchor)
549 // -- redirect timer fires
550 // dispatchDidStartProvisionalLoad() -> appends 1#anchor (src) and 1 (dest)
551 // dispatchDidCancelClientRedirect() -> clears expected redirect
552 // dispatchDidCommitLoad() -> DISPATCHES 1#anchor + 1
554 void FrameLoaderClientImpl::dispatchDidReceiveServerRedirectForProvisionalLoad()
556 WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
558 // Got a server redirect when there is no provisional DS!
559 ASSERT_NOT_REACHED();
563 // The server redirect may have been blocked.
564 if (ds->request().isNull())
567 // A provisional load should have started already, which should have put an
568 // entry in our redirect chain.
569 ASSERT(ds->hasRedirectChain());
571 // The URL of the destination is on the provisional data source. We also need
572 // to update the redirect chain to account for this addition (we do this
573 // before the callback so the callback can look at the redirect chain to see
575 ds->appendRedirect(ds->request().url());
577 if (m_webFrame->client())
578 m_webFrame->client()->didReceiveServerRedirectForProvisionalLoad(m_webFrame);
581 // Called on both success and failure of a client redirect.
582 void FrameLoaderClientImpl::dispatchDidCancelClientRedirect()
584 // No longer expecting a client redirect.
585 if (m_webFrame->client()) {
586 m_expectedClientRedirectSrc = KURL();
587 m_expectedClientRedirectDest = KURL();
588 m_webFrame->client()->didCancelClientRedirect(m_webFrame);
591 // No need to clear the redirect chain, since that data source has already
592 // been deleted by the time this function is called.
595 void FrameLoaderClientImpl::dispatchWillPerformClientRedirect(
600 // Tells dispatchDidStartProvisionalLoad that if it sees this item it is a
601 // redirect and the source item should be added as the start of the chain.
602 m_expectedClientRedirectSrc = m_webFrame->document().url();
603 m_expectedClientRedirectDest = url;
605 // FIXME: bug 1135512. Webkit does not properly notify us of cancelling
606 // http > file client redirects. Since the FrameLoader's policy is to never
607 // carry out such a navigation anyway, the best thing we can do for now to
608 // not get confused is ignore this notification.
609 if (m_expectedClientRedirectDest.isLocalFile()
610 && m_expectedClientRedirectSrc.protocolInHTTPFamily()) {
611 m_expectedClientRedirectSrc = KURL();
612 m_expectedClientRedirectDest = KURL();
616 if (m_webFrame->client()) {
617 m_webFrame->client()->willPerformClientRedirect(
619 m_expectedClientRedirectSrc,
620 m_expectedClientRedirectDest,
621 static_cast<unsigned int>(interval),
622 static_cast<unsigned int>(fireDate));
626 void FrameLoaderClientImpl::dispatchDidNavigateWithinPage()
628 // Anchor fragment navigations are not normal loads, so we need to synthesize
629 // some events for our delegate.
630 WebViewImpl* webView = m_webFrame->viewImpl();
632 // Flag of whether frame loader is completed. Generate didStartLoading and
633 // didStopLoading only when loader is completed so that we don't fire
634 // them for fragment redirection that happens in window.onload handler.
635 // See https://bugs.webkit.org/show_bug.cgi?id=31838
636 bool loaderCompleted =
637 !webView->page()->mainFrame()->loader()->activeDocumentLoader()->isLoadingInAPISense();
639 // Generate didStartLoading if loader is completed.
640 if (webView->client() && loaderCompleted)
641 webView->client()->didStartLoading();
643 // We need to classify some hash changes as client redirects.
644 // FIXME: It seems wrong that the currentItem can sometimes be null.
645 HistoryItem* currentItem = m_webFrame->frame()->loader()->history()->currentItem();
646 bool isHashChange = !currentItem || !currentItem->stateObject();
648 WebDataSourceImpl* ds = m_webFrame->dataSourceImpl();
649 ASSERT(ds); // Should not be null when navigating to a reference fragment!
651 KURL url = ds->request().url();
653 if (ds->hasRedirectChain()) {
654 chainEnd = ds->endOfRedirectChain();
655 ds->clearRedirectChain();
659 // Figure out if this location change is because of a JS-initiated
660 // client redirect (e.g onload/setTimeout document.location.href=).
661 // FIXME: (b/1085325, b/1046841) We don't get proper redirect
662 // performed/cancelled notifications across anchor navigations, so the
663 // other redirect-tracking code in this class (see
664 // dispatch*ClientRedirect() and dispatchDidStartProvisionalLoad) is
665 // insufficient to catch and properly flag these transitions. Once a
666 // proper fix for this bug is identified and applied the following
667 // block may no longer be required.
669 // FIXME: Why do we call isProcessingUserGesture here but none of
670 // the other ports do?
671 bool wasClientRedirect =
672 (url == m_expectedClientRedirectDest && chainEnd == m_expectedClientRedirectSrc)
673 || !m_webFrame->isProcessingUserGesture();
675 if (wasClientRedirect) {
676 if (m_webFrame->client())
677 m_webFrame->client()->didCompleteClientRedirect(m_webFrame, chainEnd);
678 ds->appendRedirect(chainEnd);
679 // Make sure we clear the expected redirect since we just effectively
681 m_expectedClientRedirectSrc = KURL();
682 m_expectedClientRedirectDest = KURL();
686 // Regardless of how we got here, we are navigating to a URL so we need to
687 // add it to the redirect chain.
688 ds->appendRedirect(url);
691 bool isNewNavigation;
692 webView->didCommitLoad(&isNewNavigation);
693 if (m_webFrame->client())
694 m_webFrame->client()->didNavigateWithinPage(m_webFrame, isNewNavigation);
696 // Generate didStopLoading if loader is completed.
697 if (webView->client() && loaderCompleted)
698 webView->client()->didStopLoading();
701 void FrameLoaderClientImpl::dispatchDidChangeLocationWithinPage()
704 m_webFrame->client()->didChangeLocationWithinPage(m_webFrame);
707 void FrameLoaderClientImpl::dispatchDidPushStateWithinPage()
709 dispatchDidNavigateWithinPage();
712 void FrameLoaderClientImpl::dispatchDidReplaceStateWithinPage()
714 dispatchDidNavigateWithinPage();
717 void FrameLoaderClientImpl::dispatchDidPopStateWithinPage()
719 // Ignored since dispatchDidNavigateWithinPage was already called.
722 void FrameLoaderClientImpl::dispatchWillClose()
724 if (m_webFrame->client())
725 m_webFrame->client()->willClose(m_webFrame);
728 void FrameLoaderClientImpl::dispatchDidReceiveIcon()
730 // The icon database is disabled, so this should never be called.
731 ASSERT_NOT_REACHED();
734 void FrameLoaderClientImpl::dispatchDidStartProvisionalLoad()
736 // In case a redirect occurs, we need this to be set so that the redirect
737 // handling code can tell where the redirect came from. Server redirects
738 // will occur on the provisional load, so we need to keep track of the most
739 // recent provisional load URL.
740 // See dispatchDidReceiveServerRedirectForProvisionalLoad.
741 WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
743 ASSERT_NOT_REACHED();
746 KURL url = ds->request().url();
748 // Since the provisional load just started, we should have not gotten
749 // any redirects yet.
750 ASSERT(!ds->hasRedirectChain());
752 // If this load is what we expected from a client redirect, treat it as a
753 // redirect from that original page. The expected redirect urls will be
754 // cleared by DidCancelClientRedirect.
755 bool completingClientRedirect = false;
756 if (m_expectedClientRedirectSrc.isValid()) {
757 // m_expectedClientRedirectDest could be something like
758 // "javascript:history.go(-1)" thus we need to exclude url starts with
759 // "javascript:". See bug: 1080873
760 if (m_expectedClientRedirectDest.protocolIs("javascript")
761 || m_expectedClientRedirectDest == url) {
762 ds->appendRedirect(m_expectedClientRedirectSrc);
763 completingClientRedirect = true;
765 // Any pending redirect is no longer in progress. This can happen
766 // if the navigation was canceled with PolicyIgnore, or if the
767 // redirect was scheduled on the wrong frame (e.g., due to a form
768 // submission targeted to _blank, as in http://webkit.org/b/44079).
769 m_expectedClientRedirectSrc = KURL();
770 m_expectedClientRedirectDest = KURL();
773 ds->appendRedirect(url);
775 if (m_webFrame->client()) {
776 // Whatever information didCompleteClientRedirect contains should only
777 // be considered relevant until the next provisional load has started.
778 // So we first tell the client that the load started, and then tell it
779 // about the client redirect the load is responsible for completing.
780 m_webFrame->client()->didStartProvisionalLoad(m_webFrame);
781 if (completingClientRedirect) {
782 m_webFrame->client()->didCompleteClientRedirect(
783 m_webFrame, m_expectedClientRedirectSrc);
788 void FrameLoaderClientImpl::dispatchDidReceiveTitle(const StringWithDirection& title)
790 if (m_webFrame->client())
791 m_webFrame->client()->didReceiveTitle(m_webFrame, title.string(), title.direction() == LTR ? WebTextDirectionLeftToRight : WebTextDirectionRightToLeft);
794 void FrameLoaderClientImpl::dispatchDidChangeIcons(WebCore::IconType type)
796 if (m_webFrame->client())
797 m_webFrame->client()->didChangeIcon(m_webFrame, static_cast<WebIconURL::Type>(type));
800 void FrameLoaderClientImpl::dispatchDidCommitLoad()
802 WebViewImpl* webview = m_webFrame->viewImpl();
803 bool isNewNavigation;
804 webview->didCommitLoad(&isNewNavigation);
806 if (m_webFrame->client())
807 m_webFrame->client()->didCommitProvisionalLoad(m_webFrame, isNewNavigation);
810 void FrameLoaderClientImpl::dispatchDidFailProvisionalLoad(
811 const ResourceError& error)
814 // If a policy change occured, then we do not want to inform the plugin
815 // delegate. See http://b/907789 for details. FIXME: This means the
816 // plugin won't receive NPP_URLNotify, which seems like it could result in
817 // a memory leak in the plugin!!
818 if (error.domain() == internalErrorDomain
819 && error.errorCode() == PolicyChangeError) {
820 m_webFrame->didFail(cancelledError(error.failingURL()), true);
824 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
825 m_webFrame->didFail(error, true);
827 observer->didFailLoading(error);
830 void FrameLoaderClientImpl::dispatchDidFailLoad(const ResourceError& error)
832 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
833 m_webFrame->didFail(error, false);
835 observer->didFailLoading(error);
837 // Don't clear the redirect chain, this will happen in the middle of client
838 // redirects, and we need the context. The chain will be cleared when the
839 // provisional load succeeds or fails, not the "real" one.
842 void FrameLoaderClientImpl::dispatchDidFinishLoad()
844 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
846 if (m_webFrame->client())
847 m_webFrame->client()->didFinishLoad(m_webFrame);
850 observer->didFinishLoading();
852 // Don't clear the redirect chain, this will happen in the middle of client
853 // redirects, and we need the context. The chain will be cleared when the
854 // provisional load succeeds or fails, not the "real" one.
857 void FrameLoaderClientImpl::dispatchDidFirstLayout()
859 if (m_webFrame->client())
860 m_webFrame->client()->didFirstLayout(m_webFrame);
863 void FrameLoaderClientImpl::dispatchDidFirstVisuallyNonEmptyLayout()
865 if (m_webFrame->client())
866 m_webFrame->client()->didFirstVisuallyNonEmptyLayout(m_webFrame);
869 Frame* FrameLoaderClientImpl::dispatchCreatePage(const NavigationAction& action)
871 struct WindowFeatures features;
872 Page* newPage = m_webFrame->frame()->page()->chrome()->createWindow(
873 m_webFrame->frame(), FrameLoadRequest(m_webFrame->frame()->document()->securityOrigin()),
876 // Make sure that we have a valid disposition. This should have been set in
877 // the preceeding call to dispatchDecidePolicyForNewWindowAction.
878 ASSERT(m_nextNavigationPolicy != WebNavigationPolicyIgnore);
879 WebNavigationPolicy policy = m_nextNavigationPolicy;
880 m_nextNavigationPolicy = WebNavigationPolicyIgnore;
882 // createWindow can return null (e.g., popup blocker denies the window).
886 WebViewImpl::fromPage(newPage)->setInitialNavigationPolicy(policy);
887 return newPage->mainFrame();
890 void FrameLoaderClientImpl::dispatchShow()
892 WebViewImpl* webView = m_webFrame->viewImpl();
893 if (webView && webView->client())
894 webView->client()->show(webView->initialNavigationPolicy());
897 void FrameLoaderClientImpl::dispatchDecidePolicyForResponse(
898 FramePolicyFunction function,
899 const ResourceResponse& response,
900 const ResourceRequest&)
904 int statusCode = response.httpStatusCode();
905 if (statusCode == 204 || statusCode == 205) {
906 // The server does not want us to replace the page contents.
907 action = PolicyIgnore;
908 } else if (WebCore::contentDispositionType(response.httpHeaderField("Content-Disposition")) == WebCore::ContentDispositionAttachment) {
909 // The server wants us to download instead of replacing the page contents.
910 // Downloading is handled by the embedder, but we still get the initial
911 // response so that we can ignore it and clean up properly.
912 action = PolicyIgnore;
913 } else if (!canShowMIMEType(response.mimeType())) {
914 // Make sure that we can actually handle this type internally.
915 action = PolicyIgnore;
917 // OK, we will render this page.
921 // NOTE: PolicyChangeError will be generated when action is not PolicyUse.
922 (m_webFrame->frame()->loader()->policyChecker()->*function)(action);
925 void FrameLoaderClientImpl::dispatchDecidePolicyForNewWindowAction(
926 FramePolicyFunction function,
927 const NavigationAction& action,
928 const ResourceRequest& request,
929 PassRefPtr<FormState> formState,
930 const String& frameName)
932 WebNavigationPolicy navigationPolicy;
933 if (!actionSpecifiesNavigationPolicy(action, &navigationPolicy))
934 navigationPolicy = WebNavigationPolicyNewForegroundTab;
936 PolicyAction policyAction;
937 if (navigationPolicy == WebNavigationPolicyDownload)
938 policyAction = PolicyDownload;
940 policyAction = PolicyUse;
942 // Remember the disposition for when dispatchCreatePage is called. It is
943 // unfortunate that WebCore does not provide us with any context when
944 // creating or showing the new window that would allow us to avoid having
945 // to keep this state.
946 m_nextNavigationPolicy = navigationPolicy;
948 (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
951 void FrameLoaderClientImpl::dispatchDecidePolicyForNavigationAction(
952 FramePolicyFunction function,
953 const NavigationAction& action,
954 const ResourceRequest& request,
955 PassRefPtr<FormState> formState) {
956 PolicyAction policyAction = PolicyIgnore;
958 // It is valid for this function to be invoked in code paths where the
959 // webview is closed.
960 // The null check here is to fix a crash that seems strange
961 // (see - https://bugs.webkit.org/show_bug.cgi?id=23554).
962 if (m_webFrame->client() && !request.url().isNull()) {
963 WebNavigationPolicy navigationPolicy = WebNavigationPolicyCurrentTab;
964 actionSpecifiesNavigationPolicy(action, &navigationPolicy);
966 // Give the delegate a chance to change the navigation policy.
967 const WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
969 KURL url = ds->request().url();
970 ASSERT(!url.protocolIs(backForwardNavigationScheme));
972 bool isRedirect = ds->isRedirect();
974 WebNavigationType webnavType =
975 WebDataSourceImpl::toWebNavigationType(action.type());
978 for (const Event* event = action.event(); event; event = event->underlyingEvent()) {
979 if (event->isMouseEvent()) {
980 const MouseEvent* mouseEvent =
981 static_cast<const MouseEvent*>(event);
982 node = m_webFrame->frame()->eventHandler()->hitTestResultAtPoint(
983 mouseEvent->absoluteLocation(), false).innerNonSharedNode();
987 WebNode originatingNode(node);
989 navigationPolicy = m_webFrame->client()->decidePolicyForNavigation(
990 m_webFrame, ds->request(), webnavType, originatingNode,
991 navigationPolicy, isRedirect);
994 if (navigationPolicy == WebNavigationPolicyCurrentTab)
995 policyAction = PolicyUse;
996 else if (navigationPolicy == WebNavigationPolicyDownload)
997 policyAction = PolicyDownload;
999 if (navigationPolicy != WebNavigationPolicyIgnore) {
1000 WrappedResourceRequest webreq(request);
1001 m_webFrame->client()->loadURLExternally(m_webFrame, webreq, navigationPolicy);
1003 policyAction = PolicyIgnore;
1007 (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
1010 void FrameLoaderClientImpl::cancelPolicyCheck()
1015 void FrameLoaderClientImpl::dispatchUnableToImplementPolicy(const ResourceError& error)
1017 m_webFrame->client()->unableToImplementPolicyWithError(m_webFrame, error);
1020 void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(HTMLFormElement* form)
1022 if (m_webFrame->client())
1023 m_webFrame->client()->willSendSubmitEvent(m_webFrame, WebFormElement(form));
1026 void FrameLoaderClientImpl::dispatchWillSubmitForm(FramePolicyFunction function,
1027 PassRefPtr<FormState> formState)
1029 if (m_webFrame->client())
1030 m_webFrame->client()->willSubmitForm(m_webFrame, WebFormElement(formState->form()));
1031 (m_webFrame->frame()->loader()->policyChecker()->*function)(PolicyUse);
1034 void FrameLoaderClientImpl::dispatchDidLoadMainResource(DocumentLoader*)
1039 void FrameLoaderClientImpl::revertToProvisionalState(DocumentLoader*)
1041 m_hasRepresentation = true;
1044 void FrameLoaderClientImpl::setMainDocumentError(DocumentLoader*,
1045 const ResourceError& error)
1047 if (m_pluginWidget) {
1048 if (m_sentInitialResponseToPlugin) {
1049 m_pluginWidget->didFailLoading(error);
1050 m_sentInitialResponseToPlugin = false;
1056 void FrameLoaderClientImpl::postProgressStartedNotification()
1058 WebViewImpl* webview = m_webFrame->viewImpl();
1059 if (webview && webview->client())
1060 webview->client()->didStartLoading();
1063 void FrameLoaderClientImpl::postProgressEstimateChangedNotification()
1065 WebViewImpl* webview = m_webFrame->viewImpl();
1066 if (webview && webview->client()) {
1067 webview->client()->didChangeLoadProgress(
1068 m_webFrame, m_webFrame->frame()->page()->progress()->estimatedProgress());
1073 void FrameLoaderClientImpl::postProgressFinishedNotification()
1075 // FIXME: why might the webview be null? http://b/1234461
1076 WebViewImpl* webview = m_webFrame->viewImpl();
1077 if (webview && webview->client())
1078 webview->client()->didStopLoading();
1081 void FrameLoaderClientImpl::setMainFrameDocumentReady(bool ready)
1086 // Creates a new connection and begins downloading from that (contrast this
1087 // with |download|).
1088 void FrameLoaderClientImpl::startDownload(const ResourceRequest& request, const String& suggestedName)
1090 if (m_webFrame->client()) {
1091 WrappedResourceRequest webreq(request);
1092 m_webFrame->client()->loadURLExternally(
1093 m_webFrame, webreq, WebNavigationPolicyDownload, suggestedName);
1097 void FrameLoaderClientImpl::willChangeTitle(DocumentLoader*)
1102 void FrameLoaderClientImpl::didChangeTitle(DocumentLoader*)
1107 // Called whenever data is received.
1108 void FrameLoaderClientImpl::committedLoad(DocumentLoader* loader, const char* data, int length)
1110 if (!m_pluginWidget) {
1111 if (m_webFrame->client()) {
1112 bool preventDefault = false;
1113 m_webFrame->client()->didReceiveDocumentData(m_webFrame, data, length, preventDefault);
1114 if (!preventDefault)
1115 m_webFrame->commitDocumentData(data, length);
1119 // If we are sending data to MediaDocument, we should stop here
1120 // and cancel the request.
1121 if (m_webFrame->frame()->document()->isMediaDocument())
1122 loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1124 // The plugin widget could have been created in the m_webFrame->DidReceiveData
1126 if (m_pluginWidget) {
1127 if (!m_sentInitialResponseToPlugin) {
1128 m_sentInitialResponseToPlugin = true;
1129 m_pluginWidget->didReceiveResponse(
1130 m_webFrame->frame()->loader()->activeDocumentLoader()->response());
1133 // It's possible that the above call removed the pointer to the plugin, so
1134 // check before calling it.
1136 m_pluginWidget->didReceiveData(data, length);
1140 void FrameLoaderClientImpl::finishedLoading(DocumentLoader* dl)
1142 if (m_pluginWidget) {
1143 m_pluginWidget->didFinishLoading();
1145 m_sentInitialResponseToPlugin = false;
1147 // This is necessary to create an empty document. See bug 634004.
1148 // However, we only want to do this if makeRepresentation has been called, to
1149 // match the behavior on the Mac.
1150 if (m_hasRepresentation)
1151 dl->writer()->setEncoding("", false);
1155 void FrameLoaderClientImpl::updateGlobalHistory()
1159 void FrameLoaderClientImpl::updateGlobalHistoryRedirectLinks()
1163 bool FrameLoaderClientImpl::shouldGoToHistoryItem(HistoryItem* item) const
1165 const KURL& url = item->url();
1166 if (!url.protocolIs(backForwardNavigationScheme))
1169 // Else, we'll punt this history navigation to the embedder. It is
1170 // necessary that we intercept this here, well before the FrameLoader
1171 // has made any state changes for this history traversal.
1174 int offset = url.lastPathComponent().toIntStrict(&ok);
1176 ASSERT_NOT_REACHED();
1180 WebViewImpl* webview = m_webFrame->viewImpl();
1181 if (webview->client())
1182 webview->client()->navigateBackForwardSoon(offset);
1187 bool FrameLoaderClientImpl::shouldStopLoadingForHistoryItem(HistoryItem* targetItem) const
1189 // Don't stop loading for pseudo-back-forward URLs, since they will get
1190 // translated and then pass through again.
1191 const KURL& url = targetItem->url();
1192 return !url.protocolIs(backForwardNavigationScheme);
1195 void FrameLoaderClientImpl::didDisplayInsecureContent()
1197 if (m_webFrame->client())
1198 m_webFrame->client()->didDisplayInsecureContent(m_webFrame);
1201 void FrameLoaderClientImpl::didRunInsecureContent(SecurityOrigin* origin, const KURL& insecureURL)
1203 if (m_webFrame->client())
1204 m_webFrame->client()->didRunInsecureContent(m_webFrame, WebSecurityOrigin(origin), insecureURL);
1207 void FrameLoaderClientImpl::didDetectXSS(const KURL& insecureURL, bool didBlockEntirePage)
1209 if (m_webFrame->client())
1210 m_webFrame->client()->didDetectXSS(m_webFrame, insecureURL, didBlockEntirePage);
1213 ResourceError FrameLoaderClientImpl::blockedError(const ResourceRequest&)
1216 return ResourceError();
1219 ResourceError FrameLoaderClientImpl::cancelledError(const ResourceRequest& request)
1221 if (!m_webFrame->client())
1222 return ResourceError();
1224 return m_webFrame->client()->cancelledError(
1225 m_webFrame, WrappedResourceRequest(request));
1228 ResourceError FrameLoaderClientImpl::cannotShowURLError(const ResourceRequest& request)
1230 if (!m_webFrame->client())
1231 return ResourceError();
1233 return m_webFrame->client()->cannotHandleRequestError(
1234 m_webFrame, WrappedResourceRequest(request));
1237 ResourceError FrameLoaderClientImpl::interruptedForPolicyChangeError(
1238 const ResourceRequest& request)
1240 return ResourceError(internalErrorDomain, PolicyChangeError,
1241 request.url().string(), String());
1244 ResourceError FrameLoaderClientImpl::cannotShowMIMETypeError(const ResourceResponse&)
1247 return ResourceError();
1250 ResourceError FrameLoaderClientImpl::fileDoesNotExistError(const ResourceResponse&)
1253 return ResourceError();
1256 ResourceError FrameLoaderClientImpl::pluginWillHandleLoadError(const ResourceResponse&)
1259 return ResourceError();
1262 bool FrameLoaderClientImpl::shouldFallBack(const ResourceError& error)
1264 // This method is called when we fail to load the URL for an <object> tag
1265 // that has fallback content (child elements) and is being loaded as a frame.
1266 // The error parameter indicates the reason for the load failure.
1267 // We should let the fallback content load only if this wasn't a cancelled
1269 // Note: The mac version also has a case for "WebKitErrorPluginWillHandleLoad"
1270 ResourceError c = cancelledError(ResourceRequest());
1271 return error.errorCode() != c.errorCode() || error.domain() != c.domain();
1274 bool FrameLoaderClientImpl::canHandleRequest(const ResourceRequest& request) const
1276 return m_webFrame->client()->canHandleRequest(
1277 m_webFrame, WrappedResourceRequest(request));
1280 bool FrameLoaderClientImpl::canShowMIMETypeAsHTML(const String& MIMEType) const
1286 bool FrameLoaderClientImpl::canShowMIMEType(const String& mimeType) const
1288 // This method is called to determine if the media type can be shown
1289 // "internally" (i.e. inside the browser) regardless of whether or not the
1290 // browser or a plugin is doing the rendering.
1292 // mimeType strings are supposed to be ASCII, but if they are not for some
1293 // reason, then it just means that the mime type will fail all of these "is
1294 // supported" checks and go down the path of an unhandled mime type.
1295 if (webKitPlatformSupport()->mimeRegistry()->supportsMIMEType(mimeType) == WebMimeRegistry::IsSupported)
1298 // If Chrome is started with the --disable-plugins switch, pluginData is null.
1299 PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
1301 // See if the type is handled by an installed plugin, if so, we can show it.
1302 // FIXME: (http://b/1085524) This is the place to stick a preference to
1303 // disable full page plugins (optionally for certain types!)
1304 return !mimeType.isEmpty() && pluginData && pluginData->supportsMimeType(mimeType);
1307 bool FrameLoaderClientImpl::representationExistsForURLScheme(const String&) const
1313 String FrameLoaderClientImpl::generatedMIMETypeForURLScheme(const String& scheme) const
1315 // This appears to generate MIME types for protocol handlers that are handled
1316 // internally. The only place I can find in the WebKit code that uses this
1317 // function is WebView::registerViewClass, where it is used as part of the
1318 // process by which custom view classes for certain document representations
1320 String mimeType("x-apple-web-kit/");
1321 mimeType.append(scheme.lower());
1325 void FrameLoaderClientImpl::frameLoadCompleted()
1327 // FIXME: the mac port also conditionally calls setDrawsBackground:YES on
1328 // it's ScrollView here.
1330 // This comment from the Mac port:
1331 // Note: Can be called multiple times.
1332 // Even if already complete, we might have set a previous item on a frame that
1333 // didn't do any data loading on the past transaction. Make sure to clear these out.
1335 // FIXME: setPreviousHistoryItem() no longer exists. http://crbug.com/8566
1336 // m_webFrame->frame()->loader()->setPreviousHistoryItem(0);
1339 void FrameLoaderClientImpl::saveViewStateToItem(HistoryItem*)
1344 void FrameLoaderClientImpl::restoreViewState()
1346 // FIXME: probably scrolls to last position when you go back or forward
1349 void FrameLoaderClientImpl::provisionalLoadStarted()
1351 // FIXME: On mac, this does various caching stuff
1354 void FrameLoaderClientImpl::didFinishLoad()
1356 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
1358 observer->didFinishLoading();
1361 void FrameLoaderClientImpl::prepareForDataSourceReplacement()
1366 PassRefPtr<DocumentLoader> FrameLoaderClientImpl::createDocumentLoader(
1367 const ResourceRequest& request,
1368 const SubstituteData& data)
1370 RefPtr<WebDataSourceImpl> ds = WebDataSourceImpl::create(request, data);
1371 if (m_webFrame->client())
1372 m_webFrame->client()->didCreateDataSource(m_webFrame, ds.get());
1373 return ds.release();
1376 void FrameLoaderClientImpl::setTitle(const StringWithDirection& title, const KURL& url)
1378 // FIXME: inform consumer of changes to the title.
1381 String FrameLoaderClientImpl::userAgent(const KURL& url)
1383 return webKitPlatformSupport()->userAgent(url);
1386 void FrameLoaderClientImpl::savePlatformDataToCachedFrame(CachedFrame*)
1388 // The page cache should be disabled.
1389 ASSERT_NOT_REACHED();
1392 void FrameLoaderClientImpl::transitionToCommittedFromCachedFrame(CachedFrame*)
1394 ASSERT_NOT_REACHED();
1397 // Called when the FrameLoader goes into a state in which a new page load
1399 void FrameLoaderClientImpl::transitionToCommittedForNewPage()
1404 void FrameLoaderClientImpl::didSaveToPageCache()
1408 void FrameLoaderClientImpl::didRestoreFromPageCache()
1412 void FrameLoaderClientImpl::dispatchDidBecomeFrameset(bool)
1416 bool FrameLoaderClientImpl::canCachePage() const
1418 // Since we manage the cache, always report this page as non-cacheable to
1423 // Downloading is handled in the browser process, not WebKit. If we get to this
1424 // point, our download detection code in the ResourceDispatcherHost is broken!
1425 void FrameLoaderClientImpl::download(ResourceHandle* handle,
1426 const ResourceRequest& request,
1427 const ResourceRequest& initialRequest,
1428 const ResourceResponse& response)
1430 ASSERT_NOT_REACHED();
1433 PassRefPtr<Frame> FrameLoaderClientImpl::createFrame(
1436 HTMLFrameOwnerElement* ownerElement,
1437 const String& referrer,
1438 bool allowsScrolling,
1442 FrameLoadRequest frameRequest(m_webFrame->frame()->document()->securityOrigin(),
1443 ResourceRequest(url, referrer), name);
1444 return m_webFrame->createChildFrame(frameRequest, ownerElement);
1447 void FrameLoaderClientImpl::didTransferChildFrameToNewDocument(Page*)
1449 ASSERT(m_webFrame->frame()->ownerElement());
1451 WebFrameImpl* newParent = static_cast<WebFrameImpl*>(m_webFrame->parent());
1452 if (!newParent || !newParent->client())
1455 // Replace the client since the old client may be destroyed when the
1456 // previous page is closed.
1457 m_webFrame->setClient(newParent->client());
1460 void FrameLoaderClientImpl::transferLoadingResourceFromPage(ResourceLoader* loader, const ResourceRequest& request, Page* oldPage)
1462 assignIdentifierToInitialRequest(loader->identifier(), loader->documentLoader(), request);
1464 WebFrameImpl* oldWebFrame = WebFrameImpl::fromFrame(oldPage->mainFrame());
1465 if (oldWebFrame && oldWebFrame->client())
1466 oldWebFrame->client()->removeIdentifierForRequest(loader->identifier());
1468 ResourceHandle* handle = loader->handle();
1469 WebURLLoader* webURLLoader = ResourceHandleInternal::FromResourceHandle(handle)->loader();
1470 if (webURLLoader && m_webFrame->client())
1471 m_webFrame->client()->didAdoptURLLoader(webURLLoader);
1474 PassRefPtr<Widget> FrameLoaderClientImpl::createPlugin(
1475 const IntSize& size, // FIXME: how do we use this?
1476 HTMLPlugInElement* element,
1478 const Vector<String>& paramNames,
1479 const Vector<String>& paramValues,
1480 const String& mimeType,
1483 if (!m_webFrame->client())
1486 WebPluginParams params;
1488 params.mimeType = mimeType;
1489 params.attributeNames = paramNames;
1490 params.attributeValues = paramValues;
1491 params.loadManually = loadManually;
1493 WebPlugin* webPlugin = m_webFrame->client()->createPlugin(m_webFrame, params);
1497 // The container takes ownership of the WebPlugin.
1498 RefPtr<WebPluginContainerImpl> container =
1499 WebPluginContainerImpl::create(element, webPlugin);
1501 if (!webPlugin->initialize(container.get()))
1504 // The element might have been removed during plugin initialization!
1505 if (!element->renderer())
1511 // This method gets called when a plugin is put in place of html content
1512 // (e.g., acrobat reader).
1513 void FrameLoaderClientImpl::redirectDataToPlugin(Widget* pluginWidget)
1515 if (pluginWidget->isPluginContainer())
1516 m_pluginWidget = static_cast<WebPluginContainerImpl*>(pluginWidget);
1517 ASSERT(m_pluginWidget);
1520 PassRefPtr<Widget> FrameLoaderClientImpl::createJavaAppletWidget(
1521 const IntSize& size,
1522 HTMLAppletElement* element,
1523 const KURL& /* baseURL */,
1524 const Vector<String>& paramNames,
1525 const Vector<String>& paramValues)
1527 return createPlugin(size, element, KURL(), paramNames, paramValues,
1528 "application/x-java-applet", false);
1531 ObjectContentType FrameLoaderClientImpl::objectContentType(
1533 const String& explicitMimeType,
1534 bool shouldPreferPlugInsForImages)
1536 // This code is based on Apple's implementation from
1537 // WebCoreSupport/WebFrameBridge.mm.
1539 String mimeType = explicitMimeType;
1540 if (mimeType.isEmpty()) {
1541 // Try to guess the MIME type based off the extension.
1542 String filename = url.lastPathComponent();
1543 int extensionPos = filename.reverseFind('.');
1544 if (extensionPos >= 0) {
1545 String extension = filename.substring(extensionPos + 1);
1546 mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1547 if (mimeType.isEmpty()) {
1548 // If there's no mimetype registered for the extension, check to see
1549 // if a plugin can handle the extension.
1550 mimeType = getPluginMimeTypeFromExtension(extension);
1554 if (mimeType.isEmpty())
1555 return ObjectContentFrame;
1558 // If Chrome is started with the --disable-plugins switch, pluginData is 0.
1559 PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
1560 bool plugInSupportsMIMEType = pluginData && pluginData->supportsMimeType(mimeType);
1562 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1563 return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;
1565 if (plugInSupportsMIMEType)
1566 return ObjectContentNetscapePlugin;
1568 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1569 return ObjectContentFrame;
1571 return ObjectContentNone;
1574 String FrameLoaderClientImpl::overrideMediaType() const
1580 bool FrameLoaderClientImpl::actionSpecifiesNavigationPolicy(
1581 const NavigationAction& action,
1582 WebNavigationPolicy* policy)
1584 const MouseEvent* event = 0;
1585 if (action.type() == NavigationTypeLinkClicked
1586 && action.event()->isMouseEvent())
1587 event = static_cast<const MouseEvent*>(action.event());
1588 else if (action.type() == NavigationTypeFormSubmitted
1590 && action.event()->underlyingEvent()
1591 && action.event()->underlyingEvent()->isMouseEvent())
1592 event = static_cast<const MouseEvent*>(action.event()->underlyingEvent());
1597 return WebViewImpl::navigationPolicyFromMouseEvent(
1598 event->button(), event->ctrlKey(), event->shiftKey(), event->altKey(),
1599 event->metaKey(), policy);
1602 PassOwnPtr<WebPluginLoadObserver> FrameLoaderClientImpl::pluginLoadObserver()
1604 WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(
1605 m_webFrame->frame()->loader()->activeDocumentLoader());
1607 // We can arrive here if a popstate event handler detaches this frame.
1608 // FIXME: Remove this code once http://webkit.org/b/36202 is fixed.
1609 ASSERT(!m_webFrame->frame()->page());
1612 return ds->releasePluginLoadObserver();
1615 PassRefPtr<FrameNetworkingContext> FrameLoaderClientImpl::createNetworkingContext()
1617 return FrameNetworkingContextImpl::create(m_webFrame->frame());
1620 } // namespace WebKit