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>
88 #include "V8IsolatedContext.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);
143 void FrameLoaderClientImpl::didCreateScriptContextForFrame()
145 if (m_webFrame->client())
146 m_webFrame->client()->didCreateScriptContext(m_webFrame);
149 void FrameLoaderClientImpl::didDestroyScriptContextForFrame()
151 if (m_webFrame->client())
152 m_webFrame->client()->didDestroyScriptContext(m_webFrame);
156 void FrameLoaderClientImpl::didCreateIsolatedScriptContext(V8IsolatedContext* isolatedContext)
158 if (m_webFrame->client())
159 m_webFrame->client()->didCreateIsolatedScriptContext(m_webFrame, isolatedContext->world()->id(), isolatedContext->context());
163 bool FrameLoaderClientImpl::allowScriptExtension(const String& extensionName,
166 WebViewImpl* webview = m_webFrame->viewImpl();
167 if (webview && webview->permissionClient())
168 return webview->permissionClient()->allowScriptExtension(m_webFrame, extensionName, extensionGroup);
173 void FrameLoaderClientImpl::didPerformFirstNavigation() const
177 void FrameLoaderClientImpl::registerForIconNotification(bool)
181 void FrameLoaderClientImpl::didChangeScrollOffset()
183 if (m_webFrame->client())
184 m_webFrame->client()->didChangeScrollOffset(m_webFrame);
187 bool FrameLoaderClientImpl::allowJavaScript(bool enabledPerSettings)
189 WebViewImpl* webview = m_webFrame->viewImpl();
190 if (webview && webview->permissionClient())
191 return webview->permissionClient()->allowScript(m_webFrame, enabledPerSettings);
193 return enabledPerSettings;
196 bool FrameLoaderClientImpl::allowPlugins(bool enabledPerSettings)
198 WebViewImpl* webview = m_webFrame->viewImpl();
199 if (webview && webview->permissionClient())
200 return webview->permissionClient()->allowPlugins(m_webFrame, enabledPerSettings);
202 return enabledPerSettings;
205 bool FrameLoaderClientImpl::allowImages(bool enabledPerSettings)
207 WebViewImpl* webview = m_webFrame->viewImpl();
208 if (webview && webview->permissionClient())
209 return webview->permissionClient()->allowImages(m_webFrame, enabledPerSettings);
211 return enabledPerSettings;
214 bool FrameLoaderClientImpl::allowDisplayingInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
216 WebViewImpl* webview = m_webFrame->viewImpl();
217 if (webview && webview->permissionClient())
218 return webview->permissionClient()->allowDisplayingInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));
220 return enabledPerSettings;
223 bool FrameLoaderClientImpl::allowRunningInsecureContent(bool enabledPerSettings, SecurityOrigin* context, const KURL& url)
225 WebViewImpl* webview = m_webFrame->viewImpl();
226 if (webview && webview->permissionClient())
227 return webview->permissionClient()->allowRunningInsecureContent(m_webFrame, enabledPerSettings, WebSecurityOrigin(context), WebURL(url));
229 return enabledPerSettings;
232 void FrameLoaderClientImpl::didNotAllowScript()
234 WebViewImpl* webview = m_webFrame->viewImpl();
235 if (webview && webview->permissionClient())
236 webview->permissionClient()->didNotAllowScript(m_webFrame);
239 void FrameLoaderClientImpl::didNotAllowPlugins()
241 WebViewImpl* webview = m_webFrame->viewImpl();
242 if (webview && webview->permissionClient())
243 webview->permissionClient()->didNotAllowPlugins(m_webFrame);
247 bool FrameLoaderClientImpl::hasWebView() const
249 return m_webFrame->viewImpl();
252 bool FrameLoaderClientImpl::hasFrameView() const
254 // The Mac port has this notion of a WebFrameView, which seems to be
255 // some wrapper around an NSView. Since our equivalent is HWND, I guess
256 // we have a "frameview" whenever we have the toplevel HWND.
257 return m_webFrame->viewImpl();
260 void FrameLoaderClientImpl::makeDocumentView()
262 m_webFrame->createFrameView();
265 void FrameLoaderClientImpl::makeRepresentation(DocumentLoader*)
267 m_hasRepresentation = true;
270 void FrameLoaderClientImpl::forceLayout()
275 void FrameLoaderClientImpl::forceLayoutForNonHTML()
280 void FrameLoaderClientImpl::setCopiesOnScroll()
285 void FrameLoaderClientImpl::detachedFromParent2()
287 // Nothing to do here.
290 void FrameLoaderClientImpl::detachedFromParent3()
292 // If we were reading data into a plugin, drop our reference to it. If we
293 // don't do this then it may end up out-living the rest of the page, which
294 // leads to problems if the plugin's destructor tries to script things.
297 // Close down the proxy. The purpose of this change is to make the
298 // call to ScriptController::clearWindowShell a no-op when called from
299 // Frame::pageDestroyed. Without this change, this call to clearWindowShell
300 // will cause a crash. If you remove/modify this, just ensure that you can
301 // go to a page and then navigate to a new page without getting any asserts
303 m_webFrame->frame()->script()->proxy()->clearForClose();
305 // Alert the client that the frame is being detached. This is the last
306 // chance we have to communicate with the client.
307 if (m_webFrame->client())
308 m_webFrame->client()->frameDetached(m_webFrame);
310 // Stop communicating with the WebFrameClient at this point since we are no
311 // longer associated with the Page.
312 m_webFrame->setClient(0);
315 // This function is responsible for associating the |identifier| with a given
316 // subresource load. The following functions that accept an |identifier| are
317 // called for each subresource, so they should not be dispatched to the
319 void FrameLoaderClientImpl::assignIdentifierToInitialRequest(
320 unsigned long identifier, DocumentLoader* loader,
321 const ResourceRequest& request)
323 if (m_webFrame->client()) {
324 WrappedResourceRequest webreq(request);
325 m_webFrame->client()->assignIdentifierToRequest(
326 m_webFrame, identifier, webreq);
330 // If the request being loaded by |loader| is a frame, update the ResourceType.
331 // A subresource in this context is anything other than a frame --
332 // this includes images and xmlhttp requests. It is important to note that a
333 // subresource is NOT limited to stuff loaded through the frame's subresource
334 // loader. Synchronous xmlhttp requests for example, do not go through the
335 // subresource loader, but we still label them as TargetIsSubresource.
337 // The important edge cases to consider when modifying this function are
338 // how synchronous resource loads are treated during load/unload threshold.
339 static void setTargetTypeFromLoader(ResourceRequest& request, DocumentLoader* loader)
341 if (loader == loader->frameLoader()->provisionalDocumentLoader()) {
342 ResourceRequest::TargetType type;
343 if (loader->frameLoader()->isLoadingMainFrame())
344 type = ResourceRequest::TargetIsMainFrame;
346 type = ResourceRequest::TargetIsSubframe;
347 request.setTargetType(type);
351 void FrameLoaderClientImpl::dispatchWillSendRequest(
352 DocumentLoader* loader, unsigned long identifier, ResourceRequest& request,
353 const ResourceResponse& redirectResponse)
356 // We want to distinguish between a request for a document to be loaded into
357 // the main frame, a sub-frame, or the sub-objects in that document.
358 setTargetTypeFromLoader(request, loader);
360 // Avoid repeating a form submission when navigating back or forward.
361 if (loader == loader->frameLoader()->provisionalDocumentLoader()
362 && request.httpMethod() == "POST"
363 && isBackForwardLoadType(loader->frameLoader()->loadType()))
364 request.setCachePolicy(ReturnCacheDataDontLoad);
367 // FrameLoader::loadEmptyDocumentSynchronously() creates an empty document
368 // with no URL. We don't like that, so we'll rename it to about:blank.
369 if (request.url().isEmpty())
370 request.setURL(KURL(ParsedURLString, "about:blank"));
371 if (request.firstPartyForCookies().isEmpty())
372 request.setFirstPartyForCookies(KURL(ParsedURLString, "about:blank"));
374 // Give the WebFrameClient a crack at the request.
375 if (m_webFrame->client()) {
376 WrappedResourceRequest webreq(request);
377 WrappedResourceResponse webresp(redirectResponse);
378 m_webFrame->client()->willSendRequest(
379 m_webFrame, identifier, webreq, webresp);
383 bool FrameLoaderClientImpl::shouldUseCredentialStorage(
384 DocumentLoader*, unsigned long identifier)
387 // Intended to pass through to a method on the resource load delegate.
388 // If implemented, that method controls whether the browser should ask the
389 // networking layer for a stored default credential for the page (say from
390 // the Mac OS keychain). If the method returns false, the user should be
391 // presented with an authentication challenge whether or not the networking
392 // layer has a credential stored.
393 // This returns true for backward compatibility: the ability to override the
394 // system credential store is new. (Actually, not yet fully implemented in
395 // WebKit, as of this writing.)
399 void FrameLoaderClientImpl::dispatchDidReceiveAuthenticationChallenge(
400 DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
405 void FrameLoaderClientImpl::dispatchDidCancelAuthenticationChallenge(
406 DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
411 void FrameLoaderClientImpl::dispatchDidReceiveResponse(DocumentLoader* loader,
412 unsigned long identifier,
413 const ResourceResponse& response)
415 if (m_webFrame->client()) {
416 WrappedResourceResponse webresp(response);
417 m_webFrame->client()->didReceiveResponse(m_webFrame, identifier, webresp);
421 void FrameLoaderClientImpl::dispatchDidReceiveContentLength(
422 DocumentLoader* loader,
423 unsigned long identifier,
428 // Called when a particular resource load completes
429 void FrameLoaderClientImpl::dispatchDidFinishLoading(DocumentLoader* loader,
430 unsigned long identifier)
432 if (m_webFrame->client())
433 m_webFrame->client()->didFinishResourceLoad(m_webFrame, identifier);
436 void FrameLoaderClientImpl::dispatchDidFailLoading(DocumentLoader* loader,
437 unsigned long identifier,
438 const ResourceError& error)
440 if (m_webFrame->client())
441 m_webFrame->client()->didFailResourceLoad(m_webFrame, identifier, error);
444 void FrameLoaderClientImpl::dispatchDidFinishDocumentLoad()
446 if (m_webFrame->client())
447 m_webFrame->client()->didFinishDocumentLoad(m_webFrame);
450 bool FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
451 DocumentLoader* loader,
452 const ResourceRequest& request,
453 const ResourceResponse& response,
456 if (m_webFrame->client()) {
457 WrappedResourceRequest webreq(request);
458 WrappedResourceResponse webresp(response);
459 m_webFrame->client()->didLoadResourceFromMemoryCache(
460 m_webFrame, webreq, webresp);
462 return false; // Do not suppress remaining notifications
465 void FrameLoaderClientImpl::dispatchDidHandleOnloadEvents()
467 if (m_webFrame->client())
468 m_webFrame->client()->didHandleOnloadEvents(m_webFrame);
473 // We want to keep track of the chain of redirects that occur during page
474 // loading. There are two types of redirects, server redirects which are HTTP
475 // response codes, and client redirects which are document.location= and meta
478 // This outlines the callbacks that we get in different redirect situations,
479 // and how each call modifies the redirect chain.
483 // dispatchDidStartProvisionalLoad() -> adds URL to the redirect list
484 // dispatchDidCommitLoad() -> DISPATCHES & clears list
486 // Server redirect (success)
487 // -------------------------
488 // dispatchDidStartProvisionalLoad() -> adds source URL
489 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL
490 // dispatchDidCommitLoad() -> DISPATCHES
492 // Client redirect (success)
493 // -------------------------
495 // dispatchWillPerformClientRedirect() -> saves expected redirect
496 // dispatchDidStartProvisionalLoad() -> appends redirect source (since
497 // it matches the expected redirect)
498 // and the current page as the dest)
499 // dispatchDidCancelClientRedirect() -> clears expected redirect
500 // dispatchDidCommitLoad() -> DISPATCHES
502 // Client redirect (cancelled)
503 // (e.g meta-refresh trumped by manual doc.location change, or just cancelled
504 // because a link was clicked that requires the meta refresh to be rescheduled
505 // (the SOURCE URL may have changed).
506 // ---------------------------
507 // dispatchDidCancelClientRedirect() -> clears expected redirect
508 // dispatchDidStartProvisionalLoad() -> adds only URL to redirect list
509 // dispatchDidCommitLoad() -> DISPATCHES & clears list
510 // rescheduled ? dispatchWillPerformClientRedirect() -> saves expected redirect
513 // Client redirect (failure)
514 // -------------------------
516 // dispatchWillPerformClientRedirect() -> saves expected redirect
517 // dispatchDidStartProvisionalLoad() -> appends redirect source (since
518 // it matches the expected redirect)
519 // and the current page as the dest)
520 // dispatchDidCancelClientRedirect()
521 // dispatchDidFailProvisionalLoad()
523 // Load 1 -> Server redirect to 2 -> client redirect to 3 -> server redirect to 4
524 // ------------------------------------------------------------------------------
525 // dispatchDidStartProvisionalLoad() -> adds source URL 1
526 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL 2
527 // dispatchDidCommitLoad() -> DISPATCHES 1+2
528 // -- begin client redirect and NEW DATA SOURCE
529 // dispatchWillPerformClientRedirect() -> saves expected redirect
530 // dispatchDidStartProvisionalLoad() -> appends URL 2 and URL 3
531 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> appends destination URL 4
532 // dispatchDidCancelClientRedirect() -> clears expected redirect
533 // dispatchDidCommitLoad() -> DISPATCHES
535 // Interesting case with multiple location changes involving anchors.
536 // Load page 1 containing future client-redirect (back to 1, e.g meta refresh) > Click
537 // on a link back to the same page (i.e an anchor href) >
538 // client-redirect finally fires (with new source, set to 1#anchor)
539 // -----------------------------------------------------------------------------
540 // dispatchWillPerformClientRedirect(non-zero 'interval' param) -> saves expected redirect
541 // -- click on anchor href
542 // dispatchDidCancelClientRedirect() -> clears expected redirect
543 // dispatchDidStartProvisionalLoad() -> adds 1#anchor source
544 // dispatchDidCommitLoad() -> DISPATCHES 1#anchor
545 // dispatchWillPerformClientRedirect() -> saves exp. source (1#anchor)
546 // -- redirect timer fires
547 // dispatchDidStartProvisionalLoad() -> appends 1#anchor (src) and 1 (dest)
548 // dispatchDidCancelClientRedirect() -> clears expected redirect
549 // dispatchDidCommitLoad() -> DISPATCHES 1#anchor + 1
551 void FrameLoaderClientImpl::dispatchDidReceiveServerRedirectForProvisionalLoad()
553 WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
555 // Got a server redirect when there is no provisional DS!
556 ASSERT_NOT_REACHED();
560 // The server redirect may have been blocked.
561 if (ds->request().isNull())
564 // A provisional load should have started already, which should have put an
565 // entry in our redirect chain.
566 ASSERT(ds->hasRedirectChain());
568 // The URL of the destination is on the provisional data source. We also need
569 // to update the redirect chain to account for this addition (we do this
570 // before the callback so the callback can look at the redirect chain to see
572 ds->appendRedirect(ds->request().url());
574 if (m_webFrame->client())
575 m_webFrame->client()->didReceiveServerRedirectForProvisionalLoad(m_webFrame);
578 // Called on both success and failure of a client redirect.
579 void FrameLoaderClientImpl::dispatchDidCancelClientRedirect()
581 // No longer expecting a client redirect.
582 if (m_webFrame->client()) {
583 m_expectedClientRedirectSrc = KURL();
584 m_expectedClientRedirectDest = KURL();
585 m_webFrame->client()->didCancelClientRedirect(m_webFrame);
588 // No need to clear the redirect chain, since that data source has already
589 // been deleted by the time this function is called.
592 void FrameLoaderClientImpl::dispatchWillPerformClientRedirect(
597 // Tells dispatchDidStartProvisionalLoad that if it sees this item it is a
598 // redirect and the source item should be added as the start of the chain.
599 m_expectedClientRedirectSrc = m_webFrame->document().url();
600 m_expectedClientRedirectDest = url;
602 // FIXME: bug 1135512. Webkit does not properly notify us of cancelling
603 // http > file client redirects. Since the FrameLoader's policy is to never
604 // carry out such a navigation anyway, the best thing we can do for now to
605 // not get confused is ignore this notification.
606 if (m_expectedClientRedirectDest.isLocalFile()
607 && m_expectedClientRedirectSrc.protocolInHTTPFamily()) {
608 m_expectedClientRedirectSrc = KURL();
609 m_expectedClientRedirectDest = KURL();
613 if (m_webFrame->client()) {
614 m_webFrame->client()->willPerformClientRedirect(
616 m_expectedClientRedirectSrc,
617 m_expectedClientRedirectDest,
618 static_cast<unsigned int>(interval),
619 static_cast<unsigned int>(fireDate));
623 void FrameLoaderClientImpl::dispatchDidNavigateWithinPage()
625 // Anchor fragment navigations are not normal loads, so we need to synthesize
626 // some events for our delegate.
627 WebViewImpl* webView = m_webFrame->viewImpl();
629 // Flag of whether frame loader is completed. Generate didStartLoading and
630 // didStopLoading only when loader is completed so that we don't fire
631 // them for fragment redirection that happens in window.onload handler.
632 // See https://bugs.webkit.org/show_bug.cgi?id=31838
633 bool loaderCompleted =
634 !webView->page()->mainFrame()->loader()->activeDocumentLoader()->isLoadingInAPISense();
636 // Generate didStartLoading if loader is completed.
637 if (webView->client() && loaderCompleted)
638 webView->client()->didStartLoading();
640 // We need to classify some hash changes as client redirects.
641 // FIXME: It seems wrong that the currentItem can sometimes be null.
642 HistoryItem* currentItem = m_webFrame->frame()->loader()->history()->currentItem();
643 bool isHashChange = !currentItem || !currentItem->stateObject();
645 WebDataSourceImpl* ds = m_webFrame->dataSourceImpl();
646 ASSERT(ds); // Should not be null when navigating to a reference fragment!
648 KURL url = ds->request().url();
650 if (ds->hasRedirectChain()) {
651 chainEnd = ds->endOfRedirectChain();
652 ds->clearRedirectChain();
656 // Figure out if this location change is because of a JS-initiated
657 // client redirect (e.g onload/setTimeout document.location.href=).
658 // FIXME: (b/1085325, b/1046841) We don't get proper redirect
659 // performed/cancelled notifications across anchor navigations, so the
660 // other redirect-tracking code in this class (see
661 // dispatch*ClientRedirect() and dispatchDidStartProvisionalLoad) is
662 // insufficient to catch and properly flag these transitions. Once a
663 // proper fix for this bug is identified and applied the following
664 // block may no longer be required.
666 // FIXME: Why do we call isProcessingUserGesture here but none of
667 // the other ports do?
668 bool wasClientRedirect =
669 (url == m_expectedClientRedirectDest && chainEnd == m_expectedClientRedirectSrc)
670 || !m_webFrame->isProcessingUserGesture();
672 if (wasClientRedirect) {
673 if (m_webFrame->client())
674 m_webFrame->client()->didCompleteClientRedirect(m_webFrame, chainEnd);
675 ds->appendRedirect(chainEnd);
676 // Make sure we clear the expected redirect since we just effectively
678 m_expectedClientRedirectSrc = KURL();
679 m_expectedClientRedirectDest = KURL();
683 // Regardless of how we got here, we are navigating to a URL so we need to
684 // add it to the redirect chain.
685 ds->appendRedirect(url);
688 bool isNewNavigation;
689 webView->didCommitLoad(&isNewNavigation);
690 if (m_webFrame->client())
691 m_webFrame->client()->didNavigateWithinPage(m_webFrame, isNewNavigation);
693 // Generate didStopLoading if loader is completed.
694 if (webView->client() && loaderCompleted)
695 webView->client()->didStopLoading();
698 void FrameLoaderClientImpl::dispatchDidChangeLocationWithinPage()
701 m_webFrame->client()->didChangeLocationWithinPage(m_webFrame);
704 void FrameLoaderClientImpl::dispatchDidPushStateWithinPage()
706 dispatchDidNavigateWithinPage();
709 void FrameLoaderClientImpl::dispatchDidReplaceStateWithinPage()
711 dispatchDidNavigateWithinPage();
714 void FrameLoaderClientImpl::dispatchDidPopStateWithinPage()
716 // Ignored since dispatchDidNavigateWithinPage was already called.
719 void FrameLoaderClientImpl::dispatchWillClose()
721 if (m_webFrame->client())
722 m_webFrame->client()->willClose(m_webFrame);
725 void FrameLoaderClientImpl::dispatchDidReceiveIcon()
727 // The icon database is disabled, so this should never be called.
728 ASSERT_NOT_REACHED();
731 void FrameLoaderClientImpl::dispatchDidStartProvisionalLoad()
733 // In case a redirect occurs, we need this to be set so that the redirect
734 // handling code can tell where the redirect came from. Server redirects
735 // will occur on the provisional load, so we need to keep track of the most
736 // recent provisional load URL.
737 // See dispatchDidReceiveServerRedirectForProvisionalLoad.
738 WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
740 ASSERT_NOT_REACHED();
743 KURL url = ds->request().url();
745 // Since the provisional load just started, we should have not gotten
746 // any redirects yet.
747 ASSERT(!ds->hasRedirectChain());
749 // If this load is what we expected from a client redirect, treat it as a
750 // redirect from that original page. The expected redirect urls will be
751 // cleared by DidCancelClientRedirect.
752 bool completingClientRedirect = false;
753 if (m_expectedClientRedirectSrc.isValid()) {
754 // m_expectedClientRedirectDest could be something like
755 // "javascript:history.go(-1)" thus we need to exclude url starts with
756 // "javascript:". See bug: 1080873
757 if (m_expectedClientRedirectDest.protocolIs("javascript")
758 || m_expectedClientRedirectDest == url) {
759 ds->appendRedirect(m_expectedClientRedirectSrc);
760 completingClientRedirect = true;
762 // Any pending redirect is no longer in progress. This can happen
763 // if the navigation was canceled with PolicyIgnore, or if the
764 // redirect was scheduled on the wrong frame (e.g., due to a form
765 // submission targeted to _blank, as in http://webkit.org/b/44079).
766 m_expectedClientRedirectSrc = KURL();
767 m_expectedClientRedirectDest = KURL();
770 ds->appendRedirect(url);
772 if (m_webFrame->client()) {
773 // Whatever information didCompleteClientRedirect contains should only
774 // be considered relevant until the next provisional load has started.
775 // So we first tell the client that the load started, and then tell it
776 // about the client redirect the load is responsible for completing.
777 m_webFrame->client()->didStartProvisionalLoad(m_webFrame);
778 if (completingClientRedirect) {
779 m_webFrame->client()->didCompleteClientRedirect(
780 m_webFrame, m_expectedClientRedirectSrc);
785 void FrameLoaderClientImpl::dispatchDidReceiveTitle(const StringWithDirection& title)
787 if (m_webFrame->client())
788 m_webFrame->client()->didReceiveTitle(m_webFrame, title.string(), title.direction() == LTR ? WebTextDirectionLeftToRight : WebTextDirectionRightToLeft);
791 void FrameLoaderClientImpl::dispatchDidChangeIcons(WebCore::IconType type)
793 if (m_webFrame->client())
794 m_webFrame->client()->didChangeIcon(m_webFrame, static_cast<WebIconURL::Type>(type));
797 void FrameLoaderClientImpl::dispatchDidCommitLoad()
799 WebViewImpl* webview = m_webFrame->viewImpl();
800 bool isNewNavigation;
801 webview->didCommitLoad(&isNewNavigation);
803 if (m_webFrame->client())
804 m_webFrame->client()->didCommitProvisionalLoad(m_webFrame, isNewNavigation);
807 void FrameLoaderClientImpl::dispatchDidFailProvisionalLoad(
808 const ResourceError& error)
811 // If a policy change occured, then we do not want to inform the plugin
812 // delegate. See http://b/907789 for details. FIXME: This means the
813 // plugin won't receive NPP_URLNotify, which seems like it could result in
814 // a memory leak in the plugin!!
815 if (error.domain() == internalErrorDomain
816 && error.errorCode() == PolicyChangeError) {
817 m_webFrame->didFail(cancelledError(error.failingURL()), true);
821 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
822 m_webFrame->didFail(error, true);
824 observer->didFailLoading(error);
827 void FrameLoaderClientImpl::dispatchDidFailLoad(const ResourceError& error)
829 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
830 m_webFrame->didFail(error, false);
832 observer->didFailLoading(error);
834 // Don't clear the redirect chain, this will happen in the middle of client
835 // redirects, and we need the context. The chain will be cleared when the
836 // provisional load succeeds or fails, not the "real" one.
839 void FrameLoaderClientImpl::dispatchDidFinishLoad()
841 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
843 if (m_webFrame->client())
844 m_webFrame->client()->didFinishLoad(m_webFrame);
847 observer->didFinishLoading();
849 // Don't clear the redirect chain, this will happen in the middle of client
850 // redirects, and we need the context. The chain will be cleared when the
851 // provisional load succeeds or fails, not the "real" one.
854 void FrameLoaderClientImpl::dispatchDidFirstLayout()
856 if (m_webFrame->client())
857 m_webFrame->client()->didFirstLayout(m_webFrame);
860 void FrameLoaderClientImpl::dispatchDidFirstVisuallyNonEmptyLayout()
862 if (m_webFrame->client())
863 m_webFrame->client()->didFirstVisuallyNonEmptyLayout(m_webFrame);
866 Frame* FrameLoaderClientImpl::dispatchCreatePage(const NavigationAction& action)
868 struct WindowFeatures features;
869 Page* newPage = m_webFrame->frame()->page()->chrome()->createWindow(
870 m_webFrame->frame(), FrameLoadRequest(m_webFrame->frame()->document()->securityOrigin()),
873 // Make sure that we have a valid disposition. This should have been set in
874 // the preceeding call to dispatchDecidePolicyForNewWindowAction.
875 ASSERT(m_nextNavigationPolicy != WebNavigationPolicyIgnore);
876 WebNavigationPolicy policy = m_nextNavigationPolicy;
877 m_nextNavigationPolicy = WebNavigationPolicyIgnore;
879 // createWindow can return null (e.g., popup blocker denies the window).
883 WebViewImpl::fromPage(newPage)->setInitialNavigationPolicy(policy);
884 return newPage->mainFrame();
887 void FrameLoaderClientImpl::dispatchShow()
889 WebViewImpl* webView = m_webFrame->viewImpl();
890 if (webView && webView->client())
891 webView->client()->show(webView->initialNavigationPolicy());
894 void FrameLoaderClientImpl::dispatchDecidePolicyForResponse(
895 FramePolicyFunction function,
896 const ResourceResponse& response,
897 const ResourceRequest&)
901 int statusCode = response.httpStatusCode();
902 if (statusCode == 204 || statusCode == 205) {
903 // The server does not want us to replace the page contents.
904 action = PolicyIgnore;
905 } else if (WebCore::contentDispositionType(response.httpHeaderField("Content-Disposition")) == WebCore::ContentDispositionAttachment) {
906 // The server wants us to download instead of replacing the page contents.
907 // Downloading is handled by the embedder, but we still get the initial
908 // response so that we can ignore it and clean up properly.
909 action = PolicyIgnore;
910 } else if (!canShowMIMEType(response.mimeType())) {
911 // Make sure that we can actually handle this type internally.
912 action = PolicyIgnore;
914 // OK, we will render this page.
918 // NOTE: PolicyChangeError will be generated when action is not PolicyUse.
919 (m_webFrame->frame()->loader()->policyChecker()->*function)(action);
922 void FrameLoaderClientImpl::dispatchDecidePolicyForNewWindowAction(
923 FramePolicyFunction function,
924 const NavigationAction& action,
925 const ResourceRequest& request,
926 PassRefPtr<FormState> formState,
927 const String& frameName)
929 WebNavigationPolicy navigationPolicy;
930 if (!actionSpecifiesNavigationPolicy(action, &navigationPolicy))
931 navigationPolicy = WebNavigationPolicyNewForegroundTab;
933 PolicyAction policyAction;
934 if (navigationPolicy == WebNavigationPolicyDownload)
935 policyAction = PolicyDownload;
937 policyAction = PolicyUse;
939 // Remember the disposition for when dispatchCreatePage is called. It is
940 // unfortunate that WebCore does not provide us with any context when
941 // creating or showing the new window that would allow us to avoid having
942 // to keep this state.
943 m_nextNavigationPolicy = navigationPolicy;
945 (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
948 void FrameLoaderClientImpl::dispatchDecidePolicyForNavigationAction(
949 FramePolicyFunction function,
950 const NavigationAction& action,
951 const ResourceRequest& request,
952 PassRefPtr<FormState> formState) {
953 PolicyAction policyAction = PolicyIgnore;
955 // It is valid for this function to be invoked in code paths where the
956 // webview is closed.
957 // The null check here is to fix a crash that seems strange
958 // (see - https://bugs.webkit.org/show_bug.cgi?id=23554).
959 if (m_webFrame->client() && !request.url().isNull()) {
960 WebNavigationPolicy navigationPolicy = WebNavigationPolicyCurrentTab;
961 actionSpecifiesNavigationPolicy(action, &navigationPolicy);
963 // Give the delegate a chance to change the navigation policy.
964 const WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
966 KURL url = ds->request().url();
967 ASSERT(!url.protocolIs(backForwardNavigationScheme));
969 bool isRedirect = ds->isRedirect();
971 WebNavigationType webnavType =
972 WebDataSourceImpl::toWebNavigationType(action.type());
975 for (const Event* event = action.event(); event; event = event->underlyingEvent()) {
976 if (event->isMouseEvent()) {
977 const MouseEvent* mouseEvent =
978 static_cast<const MouseEvent*>(event);
979 node = m_webFrame->frame()->eventHandler()->hitTestResultAtPoint(
980 mouseEvent->absoluteLocation(), false).innerNonSharedNode();
984 WebNode originatingNode(node);
986 navigationPolicy = m_webFrame->client()->decidePolicyForNavigation(
987 m_webFrame, ds->request(), webnavType, originatingNode,
988 navigationPolicy, isRedirect);
991 if (navigationPolicy == WebNavigationPolicyCurrentTab)
992 policyAction = PolicyUse;
993 else if (navigationPolicy == WebNavigationPolicyDownload)
994 policyAction = PolicyDownload;
996 if (navigationPolicy != WebNavigationPolicyIgnore) {
997 WrappedResourceRequest webreq(request);
998 m_webFrame->client()->loadURLExternally(m_webFrame, webreq, navigationPolicy);
1000 policyAction = PolicyIgnore;
1004 (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
1007 void FrameLoaderClientImpl::cancelPolicyCheck()
1012 void FrameLoaderClientImpl::dispatchUnableToImplementPolicy(const ResourceError& error)
1014 m_webFrame->client()->unableToImplementPolicyWithError(m_webFrame, error);
1017 void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(HTMLFormElement* form)
1019 if (m_webFrame->client())
1020 m_webFrame->client()->willSendSubmitEvent(m_webFrame, WebFormElement(form));
1023 void FrameLoaderClientImpl::dispatchWillSubmitForm(FramePolicyFunction function,
1024 PassRefPtr<FormState> formState)
1026 if (m_webFrame->client())
1027 m_webFrame->client()->willSubmitForm(m_webFrame, WebFormElement(formState->form()));
1028 (m_webFrame->frame()->loader()->policyChecker()->*function)(PolicyUse);
1031 void FrameLoaderClientImpl::dispatchDidLoadMainResource(DocumentLoader*)
1036 void FrameLoaderClientImpl::revertToProvisionalState(DocumentLoader*)
1038 m_hasRepresentation = true;
1041 void FrameLoaderClientImpl::setMainDocumentError(DocumentLoader*,
1042 const ResourceError& error)
1044 if (m_pluginWidget.get()) {
1045 if (m_sentInitialResponseToPlugin) {
1046 m_pluginWidget->didFailLoading(error);
1047 m_sentInitialResponseToPlugin = false;
1053 void FrameLoaderClientImpl::postProgressStartedNotification()
1055 WebViewImpl* webview = m_webFrame->viewImpl();
1056 if (webview && webview->client())
1057 webview->client()->didStartLoading();
1060 void FrameLoaderClientImpl::postProgressEstimateChangedNotification()
1062 WebViewImpl* webview = m_webFrame->viewImpl();
1063 if (webview && webview->client()) {
1064 webview->client()->didChangeLoadProgress(
1065 m_webFrame, m_webFrame->frame()->page()->progress()->estimatedProgress());
1070 void FrameLoaderClientImpl::postProgressFinishedNotification()
1072 // FIXME: why might the webview be null? http://b/1234461
1073 WebViewImpl* webview = m_webFrame->viewImpl();
1074 if (webview && webview->client())
1075 webview->client()->didStopLoading();
1078 void FrameLoaderClientImpl::setMainFrameDocumentReady(bool ready)
1083 // Creates a new connection and begins downloading from that (contrast this
1084 // with |download|).
1085 void FrameLoaderClientImpl::startDownload(const ResourceRequest& request, const String& suggestedName)
1087 if (m_webFrame->client()) {
1088 WrappedResourceRequest webreq(request);
1089 m_webFrame->client()->loadURLExternally(
1090 m_webFrame, webreq, WebNavigationPolicyDownload, suggestedName);
1094 void FrameLoaderClientImpl::willChangeTitle(DocumentLoader*)
1099 void FrameLoaderClientImpl::didChangeTitle(DocumentLoader*)
1104 // Called whenever data is received.
1105 void FrameLoaderClientImpl::committedLoad(DocumentLoader* loader, const char* data, int length)
1107 if (!m_pluginWidget.get()) {
1108 if (m_webFrame->client()) {
1109 bool preventDefault = false;
1110 m_webFrame->client()->didReceiveDocumentData(m_webFrame, data, length, preventDefault);
1111 if (!preventDefault)
1112 m_webFrame->commitDocumentData(data, length);
1116 // If we are sending data to MediaDocument, we should stop here
1117 // and cancel the request.
1118 if (m_webFrame->frame()->document()->isMediaDocument())
1119 loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1121 // The plugin widget could have been created in the m_webFrame->DidReceiveData
1123 if (m_pluginWidget.get()) {
1124 if (!m_sentInitialResponseToPlugin) {
1125 m_sentInitialResponseToPlugin = true;
1126 m_pluginWidget->didReceiveResponse(
1127 m_webFrame->frame()->loader()->activeDocumentLoader()->response());
1130 // It's possible that the above call removed the pointer to the plugin, so
1131 // check before calling it.
1132 if (m_pluginWidget.get())
1133 m_pluginWidget->didReceiveData(data, length);
1137 void FrameLoaderClientImpl::finishedLoading(DocumentLoader* dl)
1139 if (m_pluginWidget.get()) {
1140 m_pluginWidget->didFinishLoading();
1142 m_sentInitialResponseToPlugin = false;
1144 // This is necessary to create an empty document. See bug 634004.
1145 // However, we only want to do this if makeRepresentation has been called, to
1146 // match the behavior on the Mac.
1147 if (m_hasRepresentation)
1148 dl->writer()->setEncoding("", false);
1152 void FrameLoaderClientImpl::updateGlobalHistory()
1156 void FrameLoaderClientImpl::updateGlobalHistoryRedirectLinks()
1160 bool FrameLoaderClientImpl::shouldGoToHistoryItem(HistoryItem* item) const
1162 const KURL& url = item->url();
1163 if (!url.protocolIs(backForwardNavigationScheme))
1166 // Else, we'll punt this history navigation to the embedder. It is
1167 // necessary that we intercept this here, well before the FrameLoader
1168 // has made any state changes for this history traversal.
1171 int offset = url.lastPathComponent().toIntStrict(&ok);
1173 ASSERT_NOT_REACHED();
1177 WebViewImpl* webview = m_webFrame->viewImpl();
1178 if (webview->client())
1179 webview->client()->navigateBackForwardSoon(offset);
1184 bool FrameLoaderClientImpl::shouldStopLoadingForHistoryItem(HistoryItem* targetItem) const
1186 // Don't stop loading for pseudo-back-forward URLs, since they will get
1187 // translated and then pass through again.
1188 const KURL& url = targetItem->url();
1189 return !url.protocolIs(backForwardNavigationScheme);
1192 void FrameLoaderClientImpl::dispatchDidAddBackForwardItem(HistoryItem*) const
1196 void FrameLoaderClientImpl::dispatchDidRemoveBackForwardItem(HistoryItem*) const
1200 void FrameLoaderClientImpl::dispatchDidChangeBackForwardIndex() const
1204 void FrameLoaderClientImpl::didDisplayInsecureContent()
1206 if (m_webFrame->client())
1207 m_webFrame->client()->didDisplayInsecureContent(m_webFrame);
1210 void FrameLoaderClientImpl::didRunInsecureContent(SecurityOrigin* origin, const KURL& insecureURL)
1212 if (m_webFrame->client())
1213 m_webFrame->client()->didRunInsecureContent(m_webFrame, WebSecurityOrigin(origin), insecureURL);
1216 ResourceError FrameLoaderClientImpl::blockedError(const ResourceRequest&)
1219 return ResourceError();
1222 ResourceError FrameLoaderClientImpl::cancelledError(const ResourceRequest& request)
1224 if (!m_webFrame->client())
1225 return ResourceError();
1227 return m_webFrame->client()->cancelledError(
1228 m_webFrame, WrappedResourceRequest(request));
1231 ResourceError FrameLoaderClientImpl::cannotShowURLError(const ResourceRequest& request)
1233 if (!m_webFrame->client())
1234 return ResourceError();
1236 return m_webFrame->client()->cannotHandleRequestError(
1237 m_webFrame, WrappedResourceRequest(request));
1240 ResourceError FrameLoaderClientImpl::interruptedForPolicyChangeError(
1241 const ResourceRequest& request)
1243 return ResourceError(internalErrorDomain, PolicyChangeError,
1244 request.url().string(), String());
1247 ResourceError FrameLoaderClientImpl::cannotShowMIMETypeError(const ResourceResponse&)
1250 return ResourceError();
1253 ResourceError FrameLoaderClientImpl::fileDoesNotExistError(const ResourceResponse&)
1256 return ResourceError();
1259 ResourceError FrameLoaderClientImpl::pluginWillHandleLoadError(const ResourceResponse&)
1262 return ResourceError();
1265 bool FrameLoaderClientImpl::shouldFallBack(const ResourceError& error)
1267 // This method is called when we fail to load the URL for an <object> tag
1268 // that has fallback content (child elements) and is being loaded as a frame.
1269 // The error parameter indicates the reason for the load failure.
1270 // We should let the fallback content load only if this wasn't a cancelled
1272 // Note: The mac version also has a case for "WebKitErrorPluginWillHandleLoad"
1273 ResourceError c = cancelledError(ResourceRequest());
1274 return error.errorCode() != c.errorCode() || error.domain() != c.domain();
1277 bool FrameLoaderClientImpl::canHandleRequest(const ResourceRequest& request) const
1279 return m_webFrame->client()->canHandleRequest(
1280 m_webFrame, WrappedResourceRequest(request));
1283 bool FrameLoaderClientImpl::canShowMIMETypeAsHTML(const String& MIMEType) const
1289 bool FrameLoaderClientImpl::canShowMIMEType(const String& mimeType) const
1291 // This method is called to determine if the media type can be shown
1292 // "internally" (i.e. inside the browser) regardless of whether or not the
1293 // browser or a plugin is doing the rendering.
1295 // mimeType strings are supposed to be ASCII, but if they are not for some
1296 // reason, then it just means that the mime type will fail all of these "is
1297 // supported" checks and go down the path of an unhandled mime type.
1298 if (webKitPlatformSupport()->mimeRegistry()->supportsMIMEType(mimeType) == WebMimeRegistry::IsSupported)
1301 // If Chrome is started with the --disable-plugins switch, pluginData is null.
1302 PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
1304 // See if the type is handled by an installed plugin, if so, we can show it.
1305 // FIXME: (http://b/1085524) This is the place to stick a preference to
1306 // disable full page plugins (optionally for certain types!)
1307 return !mimeType.isEmpty() && pluginData && pluginData->supportsMimeType(mimeType);
1310 bool FrameLoaderClientImpl::representationExistsForURLScheme(const String&) const
1316 String FrameLoaderClientImpl::generatedMIMETypeForURLScheme(const String& scheme) const
1318 // This appears to generate MIME types for protocol handlers that are handled
1319 // internally. The only place I can find in the WebKit code that uses this
1320 // function is WebView::registerViewClass, where it is used as part of the
1321 // process by which custom view classes for certain document representations
1323 String mimeType("x-apple-web-kit/");
1324 mimeType.append(scheme.lower());
1328 void FrameLoaderClientImpl::frameLoadCompleted()
1330 // FIXME: the mac port also conditionally calls setDrawsBackground:YES on
1331 // it's ScrollView here.
1333 // This comment from the Mac port:
1334 // Note: Can be called multiple times.
1335 // Even if already complete, we might have set a previous item on a frame that
1336 // didn't do any data loading on the past transaction. Make sure to clear these out.
1338 // FIXME: setPreviousHistoryItem() no longer exists. http://crbug.com/8566
1339 // m_webFrame->frame()->loader()->setPreviousHistoryItem(0);
1342 void FrameLoaderClientImpl::saveViewStateToItem(HistoryItem*)
1347 void FrameLoaderClientImpl::restoreViewState()
1349 // FIXME: probably scrolls to last position when you go back or forward
1352 void FrameLoaderClientImpl::provisionalLoadStarted()
1354 // FIXME: On mac, this does various caching stuff
1357 void FrameLoaderClientImpl::didFinishLoad()
1359 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
1361 observer->didFinishLoading();
1364 void FrameLoaderClientImpl::prepareForDataSourceReplacement()
1369 PassRefPtr<DocumentLoader> FrameLoaderClientImpl::createDocumentLoader(
1370 const ResourceRequest& request,
1371 const SubstituteData& data)
1373 RefPtr<WebDataSourceImpl> ds = WebDataSourceImpl::create(request, data);
1374 if (m_webFrame->client())
1375 m_webFrame->client()->didCreateDataSource(m_webFrame, ds.get());
1376 return ds.release();
1379 void FrameLoaderClientImpl::setTitle(const StringWithDirection& title, const KURL& url)
1381 // FIXME: inform consumer of changes to the title.
1384 String FrameLoaderClientImpl::userAgent(const KURL& url)
1386 return webKitPlatformSupport()->userAgent(url);
1389 void FrameLoaderClientImpl::savePlatformDataToCachedFrame(CachedFrame*)
1391 // The page cache should be disabled.
1392 ASSERT_NOT_REACHED();
1395 void FrameLoaderClientImpl::transitionToCommittedFromCachedFrame(CachedFrame*)
1397 ASSERT_NOT_REACHED();
1400 // Called when the FrameLoader goes into a state in which a new page load
1402 void FrameLoaderClientImpl::transitionToCommittedForNewPage()
1407 void FrameLoaderClientImpl::didSaveToPageCache()
1411 void FrameLoaderClientImpl::didRestoreFromPageCache()
1415 void FrameLoaderClientImpl::dispatchDidBecomeFrameset(bool)
1419 bool FrameLoaderClientImpl::canCachePage() const
1421 // Since we manage the cache, always report this page as non-cacheable to
1426 // Downloading is handled in the browser process, not WebKit. If we get to this
1427 // point, our download detection code in the ResourceDispatcherHost is broken!
1428 void FrameLoaderClientImpl::download(ResourceHandle* handle,
1429 const ResourceRequest& request,
1430 const ResourceRequest& initialRequest,
1431 const ResourceResponse& response)
1433 ASSERT_NOT_REACHED();
1436 PassRefPtr<Frame> FrameLoaderClientImpl::createFrame(
1439 HTMLFrameOwnerElement* ownerElement,
1440 const String& referrer,
1441 bool allowsScrolling,
1445 FrameLoadRequest frameRequest(m_webFrame->frame()->document()->securityOrigin(),
1446 ResourceRequest(url, referrer), name);
1447 return m_webFrame->createChildFrame(frameRequest, ownerElement);
1450 void FrameLoaderClientImpl::didTransferChildFrameToNewDocument(Page*)
1452 ASSERT(m_webFrame->frame()->ownerElement());
1454 WebFrameImpl* newParent = static_cast<WebFrameImpl*>(m_webFrame->parent());
1455 if (!newParent || !newParent->client())
1458 // Replace the client since the old client may be destroyed when the
1459 // previous page is closed.
1460 m_webFrame->setClient(newParent->client());
1463 void FrameLoaderClientImpl::transferLoadingResourceFromPage(ResourceLoader* loader, const ResourceRequest& request, Page* oldPage)
1465 assignIdentifierToInitialRequest(loader->identifier(), loader->documentLoader(), request);
1467 WebFrameImpl* oldWebFrame = WebFrameImpl::fromFrame(oldPage->mainFrame());
1468 if (oldWebFrame && oldWebFrame->client())
1469 oldWebFrame->client()->removeIdentifierForRequest(loader->identifier());
1471 ResourceHandle* handle = loader->handle();
1472 WebURLLoader* webURLLoader = ResourceHandleInternal::FromResourceHandle(handle)->loader();
1473 if (webURLLoader && m_webFrame->client())
1474 m_webFrame->client()->didAdoptURLLoader(webURLLoader);
1477 PassRefPtr<Widget> FrameLoaderClientImpl::createPlugin(
1478 const IntSize& size, // FIXME: how do we use this?
1479 HTMLPlugInElement* element,
1481 const Vector<String>& paramNames,
1482 const Vector<String>& paramValues,
1483 const String& mimeType,
1486 if (!m_webFrame->client())
1489 RefPtr<HTMLPlugInElement> protect(element);
1491 WebPluginParams params;
1493 params.mimeType = mimeType;
1494 params.attributeNames = paramNames;
1495 params.attributeValues = paramValues;
1496 params.loadManually = loadManually;
1498 WebPlugin* webPlugin = m_webFrame->client()->createPlugin(m_webFrame, params);
1502 // The container takes ownership of the WebPlugin.
1503 RefPtr<WebPluginContainerImpl> container =
1504 WebPluginContainerImpl::create(element, webPlugin);
1506 if (!webPlugin->initialize(container.get()))
1509 // The element might have been removed during plugin initialization!
1510 if (!element->renderer())
1516 // This method gets called when a plugin is put in place of html content
1517 // (e.g., acrobat reader).
1518 void FrameLoaderClientImpl::redirectDataToPlugin(Widget* pluginWidget)
1520 if (pluginWidget->isPluginContainer())
1521 m_pluginWidget = static_cast<WebPluginContainerImpl*>(pluginWidget);
1522 ASSERT(m_pluginWidget.get());
1525 PassRefPtr<Widget> FrameLoaderClientImpl::createJavaAppletWidget(
1526 const IntSize& size,
1527 HTMLAppletElement* element,
1528 const KURL& /* baseURL */,
1529 const Vector<String>& paramNames,
1530 const Vector<String>& paramValues)
1532 return createPlugin(size, element, KURL(), paramNames, paramValues,
1533 "application/x-java-applet", false);
1536 ObjectContentType FrameLoaderClientImpl::objectContentType(
1538 const String& explicitMimeType,
1539 bool shouldPreferPlugInsForImages)
1541 // This code is based on Apple's implementation from
1542 // WebCoreSupport/WebFrameBridge.mm.
1544 String mimeType = explicitMimeType;
1545 if (mimeType.isEmpty()) {
1546 // Try to guess the MIME type based off the extension.
1547 String filename = url.lastPathComponent();
1548 int extensionPos = filename.reverseFind('.');
1549 if (extensionPos >= 0) {
1550 String extension = filename.substring(extensionPos + 1);
1551 mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1552 if (mimeType.isEmpty()) {
1553 // If there's no mimetype registered for the extension, check to see
1554 // if a plugin can handle the extension.
1555 mimeType = getPluginMimeTypeFromExtension(extension);
1559 if (mimeType.isEmpty())
1560 return ObjectContentFrame;
1563 // If Chrome is started with the --disable-plugins switch, pluginData is 0.
1564 PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
1565 bool plugInSupportsMIMEType = pluginData && pluginData->supportsMimeType(mimeType);
1567 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1568 return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;
1570 if (plugInSupportsMIMEType)
1571 return ObjectContentNetscapePlugin;
1573 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1574 return ObjectContentFrame;
1576 return ObjectContentNone;
1579 String FrameLoaderClientImpl::overrideMediaType() const
1585 bool FrameLoaderClientImpl::actionSpecifiesNavigationPolicy(
1586 const NavigationAction& action,
1587 WebNavigationPolicy* policy)
1589 const MouseEvent* event = 0;
1590 if (action.type() == NavigationTypeLinkClicked
1591 && action.event()->isMouseEvent())
1592 event = static_cast<const MouseEvent*>(action.event());
1593 else if (action.type() == NavigationTypeFormSubmitted
1595 && action.event()->underlyingEvent()
1596 && action.event()->underlyingEvent()->isMouseEvent())
1597 event = static_cast<const MouseEvent*>(action.event()->underlyingEvent());
1602 return WebViewImpl::navigationPolicyFromMouseEvent(
1603 event->button(), event->ctrlKey(), event->shiftKey(), event->altKey(),
1604 event->metaKey(), policy);
1607 PassOwnPtr<WebPluginLoadObserver> FrameLoaderClientImpl::pluginLoadObserver()
1609 WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(
1610 m_webFrame->frame()->loader()->activeDocumentLoader());
1612 // We can arrive here if a popstate event handler detaches this frame.
1613 // FIXME: Remove this code once http://webkit.org/b/36202 is fixed.
1614 ASSERT(!m_webFrame->frame()->page());
1617 return ds->releasePluginLoadObserver();
1620 PassRefPtr<FrameNetworkingContext> FrameLoaderClientImpl::createNetworkingContext()
1622 return FrameNetworkingContextImpl::create(m_webFrame->frame());
1625 } // namespace WebKit