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 "WebKitClient.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 // Close down the proxy. The purpose of this change is to make the
293 // call to ScriptController::clearWindowShell a no-op when called from
294 // Frame::pageDestroyed. Without this change, this call to clearWindowShell
295 // will cause a crash. If you remove/modify this, just ensure that you can
296 // go to a page and then navigate to a new page without getting any asserts
298 m_webFrame->frame()->script()->proxy()->clearForClose();
300 // Alert the client that the frame is being detached. This is the last
301 // chance we have to communicate with the client.
302 if (m_webFrame->client())
303 m_webFrame->client()->frameDetached(m_webFrame);
305 // Stop communicating with the WebFrameClient at this point since we are no
306 // longer associated with the Page.
307 m_webFrame->setClient(0);
310 // This function is responsible for associating the |identifier| with a given
311 // subresource load. The following functions that accept an |identifier| are
312 // called for each subresource, so they should not be dispatched to the
314 void FrameLoaderClientImpl::assignIdentifierToInitialRequest(
315 unsigned long identifier, DocumentLoader* loader,
316 const ResourceRequest& request)
318 if (m_webFrame->client()) {
319 WrappedResourceRequest webreq(request);
320 m_webFrame->client()->assignIdentifierToRequest(
321 m_webFrame, identifier, webreq);
325 // If the request being loaded by |loader| is a frame, update the ResourceType.
326 // A subresource in this context is anything other than a frame --
327 // this includes images and xmlhttp requests. It is important to note that a
328 // subresource is NOT limited to stuff loaded through the frame's subresource
329 // loader. Synchronous xmlhttp requests for example, do not go through the
330 // subresource loader, but we still label them as TargetIsSubresource.
332 // The important edge cases to consider when modifying this function are
333 // how synchronous resource loads are treated during load/unload threshold.
334 static void setTargetTypeFromLoader(ResourceRequest& request, DocumentLoader* loader)
336 if (loader == loader->frameLoader()->provisionalDocumentLoader()) {
337 ResourceRequest::TargetType type;
338 if (loader->frameLoader()->isLoadingMainFrame())
339 type = ResourceRequest::TargetIsMainFrame;
341 type = ResourceRequest::TargetIsSubframe;
342 request.setTargetType(type);
346 void FrameLoaderClientImpl::dispatchWillSendRequest(
347 DocumentLoader* loader, unsigned long identifier, ResourceRequest& request,
348 const ResourceResponse& redirectResponse)
351 // We want to distinguish between a request for a document to be loaded into
352 // the main frame, a sub-frame, or the sub-objects in that document.
353 setTargetTypeFromLoader(request, loader);
355 // Avoid repeating a form submission when navigating back or forward.
356 if (loader == loader->frameLoader()->provisionalDocumentLoader()
357 && request.httpMethod() == "POST"
358 && isBackForwardLoadType(loader->frameLoader()->loadType()))
359 request.setCachePolicy(ReturnCacheDataDontLoad);
362 // FrameLoader::loadEmptyDocumentSynchronously() creates an empty document
363 // with no URL. We don't like that, so we'll rename it to about:blank.
364 if (request.url().isEmpty())
365 request.setURL(KURL(ParsedURLString, "about:blank"));
366 if (request.firstPartyForCookies().isEmpty())
367 request.setFirstPartyForCookies(KURL(ParsedURLString, "about:blank"));
369 // Give the WebFrameClient a crack at the request.
370 if (m_webFrame->client()) {
371 WrappedResourceRequest webreq(request);
372 WrappedResourceResponse webresp(redirectResponse);
373 m_webFrame->client()->willSendRequest(
374 m_webFrame, identifier, webreq, webresp);
378 bool FrameLoaderClientImpl::shouldUseCredentialStorage(
379 DocumentLoader*, unsigned long identifier)
382 // Intended to pass through to a method on the resource load delegate.
383 // If implemented, that method controls whether the browser should ask the
384 // networking layer for a stored default credential for the page (say from
385 // the Mac OS keychain). If the method returns false, the user should be
386 // presented with an authentication challenge whether or not the networking
387 // layer has a credential stored.
388 // This returns true for backward compatibility: the ability to override the
389 // system credential store is new. (Actually, not yet fully implemented in
390 // WebKit, as of this writing.)
394 void FrameLoaderClientImpl::dispatchDidReceiveAuthenticationChallenge(
395 DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
400 void FrameLoaderClientImpl::dispatchDidCancelAuthenticationChallenge(
401 DocumentLoader*, unsigned long identifier, const AuthenticationChallenge&)
406 void FrameLoaderClientImpl::dispatchDidReceiveResponse(DocumentLoader* loader,
407 unsigned long identifier,
408 const ResourceResponse& response)
410 if (m_webFrame->client()) {
411 WrappedResourceResponse webresp(response);
412 m_webFrame->client()->didReceiveResponse(m_webFrame, identifier, webresp);
416 void FrameLoaderClientImpl::dispatchDidReceiveContentLength(
417 DocumentLoader* loader,
418 unsigned long identifier,
423 // Called when a particular resource load completes
424 void FrameLoaderClientImpl::dispatchDidFinishLoading(DocumentLoader* loader,
425 unsigned long identifier)
427 if (m_webFrame->client())
428 m_webFrame->client()->didFinishResourceLoad(m_webFrame, identifier);
431 void FrameLoaderClientImpl::dispatchDidFailLoading(DocumentLoader* loader,
432 unsigned long identifier,
433 const ResourceError& error)
435 if (m_webFrame->client())
436 m_webFrame->client()->didFailResourceLoad(m_webFrame, identifier, error);
439 void FrameLoaderClientImpl::dispatchDidFinishDocumentLoad()
441 if (m_webFrame->client())
442 m_webFrame->client()->didFinishDocumentLoad(m_webFrame);
445 bool FrameLoaderClientImpl::dispatchDidLoadResourceFromMemoryCache(
446 DocumentLoader* loader,
447 const ResourceRequest& request,
448 const ResourceResponse& response,
451 if (m_webFrame->client()) {
452 WrappedResourceRequest webreq(request);
453 WrappedResourceResponse webresp(response);
454 m_webFrame->client()->didLoadResourceFromMemoryCache(
455 m_webFrame, webreq, webresp);
457 return false; // Do not suppress remaining notifications
460 void FrameLoaderClientImpl::dispatchDidHandleOnloadEvents()
462 if (m_webFrame->client())
463 m_webFrame->client()->didHandleOnloadEvents(m_webFrame);
468 // We want to keep track of the chain of redirects that occur during page
469 // loading. There are two types of redirects, server redirects which are HTTP
470 // response codes, and client redirects which are document.location= and meta
473 // This outlines the callbacks that we get in different redirect situations,
474 // and how each call modifies the redirect chain.
478 // dispatchDidStartProvisionalLoad() -> adds URL to the redirect list
479 // dispatchDidCommitLoad() -> DISPATCHES & clears list
481 // Server redirect (success)
482 // -------------------------
483 // dispatchDidStartProvisionalLoad() -> adds source URL
484 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL
485 // dispatchDidCommitLoad() -> DISPATCHES
487 // Client redirect (success)
488 // -------------------------
490 // dispatchWillPerformClientRedirect() -> saves expected redirect
491 // dispatchDidStartProvisionalLoad() -> appends redirect source (since
492 // it matches the expected redirect)
493 // and the current page as the dest)
494 // dispatchDidCancelClientRedirect() -> clears expected redirect
495 // dispatchDidCommitLoad() -> DISPATCHES
497 // Client redirect (cancelled)
498 // (e.g meta-refresh trumped by manual doc.location change, or just cancelled
499 // because a link was clicked that requires the meta refresh to be rescheduled
500 // (the SOURCE URL may have changed).
501 // ---------------------------
502 // dispatchDidCancelClientRedirect() -> clears expected redirect
503 // dispatchDidStartProvisionalLoad() -> adds only URL to redirect list
504 // dispatchDidCommitLoad() -> DISPATCHES & clears list
505 // rescheduled ? dispatchWillPerformClientRedirect() -> saves expected redirect
508 // Client redirect (failure)
509 // -------------------------
511 // dispatchWillPerformClientRedirect() -> saves expected redirect
512 // dispatchDidStartProvisionalLoad() -> appends redirect source (since
513 // it matches the expected redirect)
514 // and the current page as the dest)
515 // dispatchDidCancelClientRedirect()
516 // dispatchDidFailProvisionalLoad()
518 // Load 1 -> Server redirect to 2 -> client redirect to 3 -> server redirect to 4
519 // ------------------------------------------------------------------------------
520 // dispatchDidStartProvisionalLoad() -> adds source URL 1
521 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> adds dest URL 2
522 // dispatchDidCommitLoad() -> DISPATCHES 1+2
523 // -- begin client redirect and NEW DATA SOURCE
524 // dispatchWillPerformClientRedirect() -> saves expected redirect
525 // dispatchDidStartProvisionalLoad() -> appends URL 2 and URL 3
526 // dispatchDidReceiveServerRedirectForProvisionalLoad() -> appends destination URL 4
527 // dispatchDidCancelClientRedirect() -> clears expected redirect
528 // dispatchDidCommitLoad() -> DISPATCHES
530 // Interesting case with multiple location changes involving anchors.
531 // Load page 1 containing future client-redirect (back to 1, e.g meta refresh) > Click
532 // on a link back to the same page (i.e an anchor href) >
533 // client-redirect finally fires (with new source, set to 1#anchor)
534 // -----------------------------------------------------------------------------
535 // dispatchWillPerformClientRedirect(non-zero 'interval' param) -> saves expected redirect
536 // -- click on anchor href
537 // dispatchDidCancelClientRedirect() -> clears expected redirect
538 // dispatchDidStartProvisionalLoad() -> adds 1#anchor source
539 // dispatchDidCommitLoad() -> DISPATCHES 1#anchor
540 // dispatchWillPerformClientRedirect() -> saves exp. source (1#anchor)
541 // -- redirect timer fires
542 // dispatchDidStartProvisionalLoad() -> appends 1#anchor (src) and 1 (dest)
543 // dispatchDidCancelClientRedirect() -> clears expected redirect
544 // dispatchDidCommitLoad() -> DISPATCHES 1#anchor + 1
546 void FrameLoaderClientImpl::dispatchDidReceiveServerRedirectForProvisionalLoad()
548 WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
550 // Got a server redirect when there is no provisional DS!
551 ASSERT_NOT_REACHED();
555 // The server redirect may have been blocked.
556 if (ds->request().isNull())
559 // A provisional load should have started already, which should have put an
560 // entry in our redirect chain.
561 ASSERT(ds->hasRedirectChain());
563 // The URL of the destination is on the provisional data source. We also need
564 // to update the redirect chain to account for this addition (we do this
565 // before the callback so the callback can look at the redirect chain to see
567 ds->appendRedirect(ds->request().url());
569 if (m_webFrame->client())
570 m_webFrame->client()->didReceiveServerRedirectForProvisionalLoad(m_webFrame);
573 // Called on both success and failure of a client redirect.
574 void FrameLoaderClientImpl::dispatchDidCancelClientRedirect()
576 // No longer expecting a client redirect.
577 if (m_webFrame->client()) {
578 m_expectedClientRedirectSrc = KURL();
579 m_expectedClientRedirectDest = KURL();
580 m_webFrame->client()->didCancelClientRedirect(m_webFrame);
583 // No need to clear the redirect chain, since that data source has already
584 // been deleted by the time this function is called.
587 void FrameLoaderClientImpl::dispatchWillPerformClientRedirect(
592 // Tells dispatchDidStartProvisionalLoad that if it sees this item it is a
593 // redirect and the source item should be added as the start of the chain.
594 m_expectedClientRedirectSrc = m_webFrame->document().url();
595 m_expectedClientRedirectDest = url;
597 // FIXME: bug 1135512. Webkit does not properly notify us of cancelling
598 // http > file client redirects. Since the FrameLoader's policy is to never
599 // carry out such a navigation anyway, the best thing we can do for now to
600 // not get confused is ignore this notification.
601 if (m_expectedClientRedirectDest.isLocalFile()
602 && m_expectedClientRedirectSrc.protocolInHTTPFamily()) {
603 m_expectedClientRedirectSrc = KURL();
604 m_expectedClientRedirectDest = KURL();
608 if (m_webFrame->client()) {
609 m_webFrame->client()->willPerformClientRedirect(
611 m_expectedClientRedirectSrc,
612 m_expectedClientRedirectDest,
613 static_cast<unsigned int>(interval),
614 static_cast<unsigned int>(fireDate));
618 void FrameLoaderClientImpl::dispatchDidNavigateWithinPage()
620 // Anchor fragment navigations are not normal loads, so we need to synthesize
621 // some events for our delegate.
622 WebViewImpl* webView = m_webFrame->viewImpl();
624 // Flag of whether frame loader is completed. Generate didStartLoading and
625 // didStopLoading only when loader is completed so that we don't fire
626 // them for fragment redirection that happens in window.onload handler.
627 // See https://bugs.webkit.org/show_bug.cgi?id=31838
628 bool loaderCompleted =
629 !webView->page()->mainFrame()->loader()->activeDocumentLoader()->isLoadingInAPISense();
631 // Generate didStartLoading if loader is completed.
632 if (webView->client() && loaderCompleted)
633 webView->client()->didStartLoading();
635 // We need to classify some hash changes as client redirects.
636 // FIXME: It seems wrong that the currentItem can sometimes be null.
637 HistoryItem* currentItem = m_webFrame->frame()->loader()->history()->currentItem();
638 bool isHashChange = !currentItem || !currentItem->stateObject();
640 WebDataSourceImpl* ds = m_webFrame->dataSourceImpl();
641 ASSERT(ds); // Should not be null when navigating to a reference fragment!
643 KURL url = ds->request().url();
645 if (ds->hasRedirectChain()) {
646 chainEnd = ds->endOfRedirectChain();
647 ds->clearRedirectChain();
651 // Figure out if this location change is because of a JS-initiated
652 // client redirect (e.g onload/setTimeout document.location.href=).
653 // FIXME: (b/1085325, b/1046841) We don't get proper redirect
654 // performed/cancelled notifications across anchor navigations, so the
655 // other redirect-tracking code in this class (see
656 // dispatch*ClientRedirect() and dispatchDidStartProvisionalLoad) is
657 // insufficient to catch and properly flag these transitions. Once a
658 // proper fix for this bug is identified and applied the following
659 // block may no longer be required.
661 // FIXME: Why do we call isProcessingUserGesture here but none of
662 // the other ports do?
663 bool wasClientRedirect =
664 (url == m_expectedClientRedirectDest && chainEnd == m_expectedClientRedirectSrc)
665 || !m_webFrame->isProcessingUserGesture();
667 if (wasClientRedirect) {
668 if (m_webFrame->client())
669 m_webFrame->client()->didCompleteClientRedirect(m_webFrame, chainEnd);
670 ds->appendRedirect(chainEnd);
671 // Make sure we clear the expected redirect since we just effectively
673 m_expectedClientRedirectSrc = KURL();
674 m_expectedClientRedirectDest = KURL();
678 // Regardless of how we got here, we are navigating to a URL so we need to
679 // add it to the redirect chain.
680 ds->appendRedirect(url);
683 bool isNewNavigation;
684 webView->didCommitLoad(&isNewNavigation);
685 if (m_webFrame->client())
686 m_webFrame->client()->didNavigateWithinPage(m_webFrame, isNewNavigation);
688 // Generate didStopLoading if loader is completed.
689 if (webView->client() && loaderCompleted)
690 webView->client()->didStopLoading();
693 void FrameLoaderClientImpl::dispatchDidChangeLocationWithinPage()
696 m_webFrame->client()->didChangeLocationWithinPage(m_webFrame);
699 void FrameLoaderClientImpl::dispatchDidPushStateWithinPage()
701 dispatchDidNavigateWithinPage();
704 void FrameLoaderClientImpl::dispatchDidReplaceStateWithinPage()
706 dispatchDidNavigateWithinPage();
709 void FrameLoaderClientImpl::dispatchDidPopStateWithinPage()
711 // Ignored since dispatchDidNavigateWithinPage was already called.
714 void FrameLoaderClientImpl::dispatchWillClose()
716 if (m_webFrame->client())
717 m_webFrame->client()->willClose(m_webFrame);
720 void FrameLoaderClientImpl::dispatchDidReceiveIcon()
722 // The icon database is disabled, so this should never be called.
723 ASSERT_NOT_REACHED();
726 void FrameLoaderClientImpl::dispatchDidStartProvisionalLoad()
728 // In case a redirect occurs, we need this to be set so that the redirect
729 // handling code can tell where the redirect came from. Server redirects
730 // will occur on the provisional load, so we need to keep track of the most
731 // recent provisional load URL.
732 // See dispatchDidReceiveServerRedirectForProvisionalLoad.
733 WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
735 ASSERT_NOT_REACHED();
738 KURL url = ds->request().url();
740 // Since the provisional load just started, we should have not gotten
741 // any redirects yet.
742 ASSERT(!ds->hasRedirectChain());
744 // If this load is what we expected from a client redirect, treat it as a
745 // redirect from that original page. The expected redirect urls will be
746 // cleared by DidCancelClientRedirect.
747 bool completingClientRedirect = false;
748 if (m_expectedClientRedirectSrc.isValid()) {
749 // m_expectedClientRedirectDest could be something like
750 // "javascript:history.go(-1)" thus we need to exclude url starts with
751 // "javascript:". See bug: 1080873
752 if (m_expectedClientRedirectDest.protocolIs("javascript")
753 || m_expectedClientRedirectDest == url) {
754 ds->appendRedirect(m_expectedClientRedirectSrc);
755 completingClientRedirect = true;
757 // Any pending redirect is no longer in progress. This can happen
758 // if the navigation was canceled with PolicyIgnore, or if the
759 // redirect was scheduled on the wrong frame (e.g., due to a form
760 // submission targeted to _blank, as in http://webkit.org/b/44079).
761 m_expectedClientRedirectSrc = KURL();
762 m_expectedClientRedirectDest = KURL();
765 ds->appendRedirect(url);
767 if (m_webFrame->client()) {
768 // Whatever information didCompleteClientRedirect contains should only
769 // be considered relevant until the next provisional load has started.
770 // So we first tell the client that the load started, and then tell it
771 // about the client redirect the load is responsible for completing.
772 m_webFrame->client()->didStartProvisionalLoad(m_webFrame);
773 if (completingClientRedirect) {
774 m_webFrame->client()->didCompleteClientRedirect(
775 m_webFrame, m_expectedClientRedirectSrc);
780 void FrameLoaderClientImpl::dispatchDidReceiveTitle(const StringWithDirection& title)
782 if (m_webFrame->client())
783 m_webFrame->client()->didReceiveTitle(m_webFrame, title.string(), title.direction() == LTR ? WebTextDirectionLeftToRight : WebTextDirectionRightToLeft);
786 void FrameLoaderClientImpl::dispatchDidChangeIcons(WebCore::IconType type)
788 if (m_webFrame->client())
789 m_webFrame->client()->didChangeIcon(m_webFrame, static_cast<WebIconURL::Type>(type));
792 void FrameLoaderClientImpl::dispatchDidCommitLoad()
794 WebViewImpl* webview = m_webFrame->viewImpl();
795 bool isNewNavigation;
796 webview->didCommitLoad(&isNewNavigation);
798 if (m_webFrame->client())
799 m_webFrame->client()->didCommitProvisionalLoad(m_webFrame, isNewNavigation);
802 void FrameLoaderClientImpl::dispatchDidFailProvisionalLoad(
803 const ResourceError& error)
806 // If a policy change occured, then we do not want to inform the plugin
807 // delegate. See http://b/907789 for details. FIXME: This means the
808 // plugin won't receive NPP_URLNotify, which seems like it could result in
809 // a memory leak in the plugin!!
810 if (error.domain() == internalErrorDomain
811 && error.errorCode() == PolicyChangeError) {
812 m_webFrame->didFail(cancelledError(error.failingURL()), true);
816 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
817 m_webFrame->didFail(error, true);
819 observer->didFailLoading(error);
822 void FrameLoaderClientImpl::dispatchDidFailLoad(const ResourceError& error)
824 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
825 m_webFrame->didFail(error, false);
827 observer->didFailLoading(error);
829 // Don't clear the redirect chain, this will happen in the middle of client
830 // redirects, and we need the context. The chain will be cleared when the
831 // provisional load succeeds or fails, not the "real" one.
834 void FrameLoaderClientImpl::dispatchDidFinishLoad()
836 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
838 if (m_webFrame->client())
839 m_webFrame->client()->didFinishLoad(m_webFrame);
842 observer->didFinishLoading();
844 // Don't clear the redirect chain, this will happen in the middle of client
845 // redirects, and we need the context. The chain will be cleared when the
846 // provisional load succeeds or fails, not the "real" one.
849 void FrameLoaderClientImpl::dispatchDidFirstLayout()
851 if (m_webFrame->client())
852 m_webFrame->client()->didFirstLayout(m_webFrame);
855 void FrameLoaderClientImpl::dispatchDidFirstVisuallyNonEmptyLayout()
857 if (m_webFrame->client())
858 m_webFrame->client()->didFirstVisuallyNonEmptyLayout(m_webFrame);
861 Frame* FrameLoaderClientImpl::dispatchCreatePage(const NavigationAction& action)
863 struct WindowFeatures features;
864 Page* newPage = m_webFrame->frame()->page()->chrome()->createWindow(
865 m_webFrame->frame(), FrameLoadRequest(m_webFrame->frame()->document()->securityOrigin()),
868 // Make sure that we have a valid disposition. This should have been set in
869 // the preceeding call to dispatchDecidePolicyForNewWindowAction.
870 ASSERT(m_nextNavigationPolicy != WebNavigationPolicyIgnore);
871 WebNavigationPolicy policy = m_nextNavigationPolicy;
872 m_nextNavigationPolicy = WebNavigationPolicyIgnore;
874 // createWindow can return null (e.g., popup blocker denies the window).
878 WebViewImpl::fromPage(newPage)->setInitialNavigationPolicy(policy);
879 return newPage->mainFrame();
882 void FrameLoaderClientImpl::dispatchShow()
884 WebViewImpl* webView = m_webFrame->viewImpl();
885 if (webView && webView->client())
886 webView->client()->show(webView->initialNavigationPolicy());
889 void FrameLoaderClientImpl::dispatchDecidePolicyForResponse(
890 FramePolicyFunction function,
891 const ResourceResponse& response,
892 const ResourceRequest&)
896 int statusCode = response.httpStatusCode();
897 if (statusCode == 204 || statusCode == 205) {
898 // The server does not want us to replace the page contents.
899 action = PolicyIgnore;
900 } else if (WebCore::contentDispositionType(response.httpHeaderField("Content-Disposition")) == WebCore::ContentDispositionAttachment) {
901 // The server wants us to download instead of replacing the page contents.
902 // Downloading is handled by the embedder, but we still get the initial
903 // response so that we can ignore it and clean up properly.
904 action = PolicyIgnore;
905 } else if (!canShowMIMEType(response.mimeType())) {
906 // Make sure that we can actually handle this type internally.
907 action = PolicyIgnore;
909 // OK, we will render this page.
913 // NOTE: PolicyChangeError will be generated when action is not PolicyUse.
914 (m_webFrame->frame()->loader()->policyChecker()->*function)(action);
917 void FrameLoaderClientImpl::dispatchDecidePolicyForNewWindowAction(
918 FramePolicyFunction function,
919 const NavigationAction& action,
920 const ResourceRequest& request,
921 PassRefPtr<FormState> formState,
922 const String& frameName)
924 WebNavigationPolicy navigationPolicy;
925 if (!actionSpecifiesNavigationPolicy(action, &navigationPolicy))
926 navigationPolicy = WebNavigationPolicyNewForegroundTab;
928 PolicyAction policyAction;
929 if (navigationPolicy == WebNavigationPolicyDownload)
930 policyAction = PolicyDownload;
932 policyAction = PolicyUse;
934 // Remember the disposition for when dispatchCreatePage is called. It is
935 // unfortunate that WebCore does not provide us with any context when
936 // creating or showing the new window that would allow us to avoid having
937 // to keep this state.
938 m_nextNavigationPolicy = navigationPolicy;
940 (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
943 void FrameLoaderClientImpl::dispatchDecidePolicyForNavigationAction(
944 FramePolicyFunction function,
945 const NavigationAction& action,
946 const ResourceRequest& request,
947 PassRefPtr<FormState> formState) {
948 PolicyAction policyAction = PolicyIgnore;
950 // It is valid for this function to be invoked in code paths where the
951 // webview is closed.
952 // The null check here is to fix a crash that seems strange
953 // (see - https://bugs.webkit.org/show_bug.cgi?id=23554).
954 if (m_webFrame->client() && !request.url().isNull()) {
955 WebNavigationPolicy navigationPolicy = WebNavigationPolicyCurrentTab;
956 actionSpecifiesNavigationPolicy(action, &navigationPolicy);
958 // Give the delegate a chance to change the navigation policy.
959 const WebDataSourceImpl* ds = m_webFrame->provisionalDataSourceImpl();
961 KURL url = ds->request().url();
962 ASSERT(!url.protocolIs(backForwardNavigationScheme));
964 bool isRedirect = ds->hasRedirectChain();
966 WebNavigationType webnavType =
967 WebDataSourceImpl::toWebNavigationType(action.type());
970 for (const Event* event = action.event(); event; event = event->underlyingEvent()) {
971 if (event->isMouseEvent()) {
972 const MouseEvent* mouseEvent =
973 static_cast<const MouseEvent*>(event);
974 node = m_webFrame->frame()->eventHandler()->hitTestResultAtPoint(
975 mouseEvent->absoluteLocation(), false).innerNonSharedNode();
979 WebNode originatingNode(node);
981 navigationPolicy = m_webFrame->client()->decidePolicyForNavigation(
982 m_webFrame, ds->request(), webnavType, originatingNode,
983 navigationPolicy, isRedirect);
986 if (navigationPolicy == WebNavigationPolicyCurrentTab)
987 policyAction = PolicyUse;
988 else if (navigationPolicy == WebNavigationPolicyDownload)
989 policyAction = PolicyDownload;
991 if (navigationPolicy != WebNavigationPolicyIgnore) {
992 WrappedResourceRequest webreq(request);
993 m_webFrame->client()->loadURLExternally(m_webFrame, webreq, navigationPolicy);
995 policyAction = PolicyIgnore;
999 (m_webFrame->frame()->loader()->policyChecker()->*function)(policyAction);
1002 void FrameLoaderClientImpl::cancelPolicyCheck()
1007 void FrameLoaderClientImpl::dispatchUnableToImplementPolicy(const ResourceError& error)
1009 m_webFrame->client()->unableToImplementPolicyWithError(m_webFrame, error);
1012 void FrameLoaderClientImpl::dispatchWillSendSubmitEvent(HTMLFormElement* form)
1014 if (m_webFrame->client())
1015 m_webFrame->client()->willSendSubmitEvent(m_webFrame, WebFormElement(form));
1018 void FrameLoaderClientImpl::dispatchWillSubmitForm(FramePolicyFunction function,
1019 PassRefPtr<FormState> formState)
1021 if (m_webFrame->client())
1022 m_webFrame->client()->willSubmitForm(m_webFrame, WebFormElement(formState->form()));
1023 (m_webFrame->frame()->loader()->policyChecker()->*function)(PolicyUse);
1026 void FrameLoaderClientImpl::dispatchDidLoadMainResource(DocumentLoader*)
1031 void FrameLoaderClientImpl::revertToProvisionalState(DocumentLoader*)
1033 m_hasRepresentation = true;
1036 void FrameLoaderClientImpl::setMainDocumentError(DocumentLoader*,
1037 const ResourceError& error)
1039 if (m_pluginWidget.get()) {
1040 if (m_sentInitialResponseToPlugin) {
1041 m_pluginWidget->didFailLoading(error);
1042 m_sentInitialResponseToPlugin = false;
1048 void FrameLoaderClientImpl::postProgressStartedNotification()
1050 WebViewImpl* webview = m_webFrame->viewImpl();
1051 if (webview && webview->client())
1052 webview->client()->didStartLoading();
1055 void FrameLoaderClientImpl::postProgressEstimateChangedNotification()
1057 WebViewImpl* webview = m_webFrame->viewImpl();
1058 if (webview && webview->client()) {
1059 webview->client()->didChangeLoadProgress(
1060 m_webFrame, m_webFrame->frame()->page()->progress()->estimatedProgress());
1065 void FrameLoaderClientImpl::postProgressFinishedNotification()
1067 // FIXME: why might the webview be null? http://b/1234461
1068 WebViewImpl* webview = m_webFrame->viewImpl();
1069 if (webview && webview->client())
1070 webview->client()->didStopLoading();
1073 void FrameLoaderClientImpl::setMainFrameDocumentReady(bool ready)
1078 // Creates a new connection and begins downloading from that (contrast this
1079 // with |download|).
1080 void FrameLoaderClientImpl::startDownload(const ResourceRequest& request, const String& suggestedName)
1082 if (m_webFrame->client()) {
1083 WrappedResourceRequest webreq(request);
1084 m_webFrame->client()->loadURLExternally(
1085 m_webFrame, webreq, WebNavigationPolicyDownload, suggestedName);
1089 void FrameLoaderClientImpl::willChangeTitle(DocumentLoader*)
1094 void FrameLoaderClientImpl::didChangeTitle(DocumentLoader*)
1099 // Called whenever data is received.
1100 void FrameLoaderClientImpl::committedLoad(DocumentLoader* loader, const char* data, int length)
1102 if (!m_pluginWidget.get()) {
1103 if (m_webFrame->client()) {
1104 bool preventDefault = false;
1105 m_webFrame->client()->didReceiveDocumentData(m_webFrame, data, length, preventDefault);
1106 if (!preventDefault)
1107 m_webFrame->commitDocumentData(data, length);
1111 // If we are sending data to MediaDocument, we should stop here
1112 // and cancel the request.
1113 if (m_webFrame->frame()->document()->isMediaDocument())
1114 loader->cancelMainResourceLoad(pluginWillHandleLoadError(loader->response()));
1116 // The plugin widget could have been created in the m_webFrame->DidReceiveData
1118 if (m_pluginWidget.get()) {
1119 if (!m_sentInitialResponseToPlugin) {
1120 m_sentInitialResponseToPlugin = true;
1121 m_pluginWidget->didReceiveResponse(
1122 m_webFrame->frame()->loader()->activeDocumentLoader()->response());
1125 // It's possible that the above call removed the pointer to the plugin, so
1126 // check before calling it.
1127 if (m_pluginWidget.get())
1128 m_pluginWidget->didReceiveData(data, length);
1132 void FrameLoaderClientImpl::finishedLoading(DocumentLoader* dl)
1134 if (m_pluginWidget.get()) {
1135 m_pluginWidget->didFinishLoading();
1137 m_sentInitialResponseToPlugin = false;
1139 // This is necessary to create an empty document. See bug 634004.
1140 // However, we only want to do this if makeRepresentation has been called, to
1141 // match the behavior on the Mac.
1142 if (m_hasRepresentation)
1143 dl->writer()->setEncoding("", false);
1147 void FrameLoaderClientImpl::updateGlobalHistory()
1151 void FrameLoaderClientImpl::updateGlobalHistoryRedirectLinks()
1155 bool FrameLoaderClientImpl::shouldGoToHistoryItem(HistoryItem* item) const
1157 const KURL& url = item->url();
1158 if (!url.protocolIs(backForwardNavigationScheme))
1161 // Else, we'll punt this history navigation to the embedder. It is
1162 // necessary that we intercept this here, well before the FrameLoader
1163 // has made any state changes for this history traversal.
1166 int offset = url.lastPathComponent().toIntStrict(&ok);
1168 ASSERT_NOT_REACHED();
1172 WebViewImpl* webview = m_webFrame->viewImpl();
1173 if (webview->client())
1174 webview->client()->navigateBackForwardSoon(offset);
1179 bool FrameLoaderClientImpl::shouldStopLoadingForHistoryItem(HistoryItem* targetItem) const
1181 // Don't stop loading for pseudo-back-forward URLs, since they will get
1182 // translated and then pass through again.
1183 const KURL& url = targetItem->url();
1184 return !url.protocolIs(backForwardNavigationScheme);
1187 void FrameLoaderClientImpl::dispatchDidAddBackForwardItem(HistoryItem*) const
1191 void FrameLoaderClientImpl::dispatchDidRemoveBackForwardItem(HistoryItem*) const
1195 void FrameLoaderClientImpl::dispatchDidChangeBackForwardIndex() const
1199 void FrameLoaderClientImpl::didDisplayInsecureContent()
1201 if (m_webFrame->client())
1202 m_webFrame->client()->didDisplayInsecureContent(m_webFrame);
1205 void FrameLoaderClientImpl::didRunInsecureContent(SecurityOrigin* origin, const KURL& insecureURL)
1207 if (m_webFrame->client())
1208 m_webFrame->client()->didRunInsecureContent(m_webFrame, WebSecurityOrigin(origin), insecureURL);
1211 ResourceError FrameLoaderClientImpl::blockedError(const ResourceRequest&)
1214 return ResourceError();
1217 ResourceError FrameLoaderClientImpl::cancelledError(const ResourceRequest& request)
1219 if (!m_webFrame->client())
1220 return ResourceError();
1222 return m_webFrame->client()->cancelledError(
1223 m_webFrame, WrappedResourceRequest(request));
1226 ResourceError FrameLoaderClientImpl::cannotShowURLError(const ResourceRequest& request)
1228 if (!m_webFrame->client())
1229 return ResourceError();
1231 return m_webFrame->client()->cannotHandleRequestError(
1232 m_webFrame, WrappedResourceRequest(request));
1235 ResourceError FrameLoaderClientImpl::interruptedForPolicyChangeError(
1236 const ResourceRequest& request)
1238 return ResourceError(internalErrorDomain, PolicyChangeError,
1239 request.url().string(), String());
1242 ResourceError FrameLoaderClientImpl::cannotShowMIMETypeError(const ResourceResponse&)
1245 return ResourceError();
1248 ResourceError FrameLoaderClientImpl::fileDoesNotExistError(const ResourceResponse&)
1251 return ResourceError();
1254 ResourceError FrameLoaderClientImpl::pluginWillHandleLoadError(const ResourceResponse&)
1257 return ResourceError();
1260 bool FrameLoaderClientImpl::shouldFallBack(const ResourceError& error)
1262 // This method is called when we fail to load the URL for an <object> tag
1263 // that has fallback content (child elements) and is being loaded as a frame.
1264 // The error parameter indicates the reason for the load failure.
1265 // We should let the fallback content load only if this wasn't a cancelled
1267 // Note: The mac version also has a case for "WebKitErrorPluginWillHandleLoad"
1268 ResourceError c = cancelledError(ResourceRequest());
1269 return error.errorCode() != c.errorCode() || error.domain() != c.domain();
1272 bool FrameLoaderClientImpl::canHandleRequest(const ResourceRequest& request) const
1274 return m_webFrame->client()->canHandleRequest(
1275 m_webFrame, WrappedResourceRequest(request));
1278 bool FrameLoaderClientImpl::canShowMIMETypeAsHTML(const String& MIMEType) const
1284 bool FrameLoaderClientImpl::canShowMIMEType(const String& mimeType) const
1286 // This method is called to determine if the media type can be shown
1287 // "internally" (i.e. inside the browser) regardless of whether or not the
1288 // browser or a plugin is doing the rendering.
1290 // mimeType strings are supposed to be ASCII, but if they are not for some
1291 // reason, then it just means that the mime type will fail all of these "is
1292 // supported" checks and go down the path of an unhandled mime type.
1293 if (webKitClient()->mimeRegistry()->supportsMIMEType(mimeType) == WebMimeRegistry::IsSupported)
1296 // If Chrome is started with the --disable-plugins switch, pluginData is null.
1297 PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
1299 // See if the type is handled by an installed plugin, if so, we can show it.
1300 // FIXME: (http://b/1085524) This is the place to stick a preference to
1301 // disable full page plugins (optionally for certain types!)
1302 return !mimeType.isEmpty() && pluginData && pluginData->supportsMimeType(mimeType);
1305 bool FrameLoaderClientImpl::representationExistsForURLScheme(const String&) const
1311 String FrameLoaderClientImpl::generatedMIMETypeForURLScheme(const String& scheme) const
1313 // This appears to generate MIME types for protocol handlers that are handled
1314 // internally. The only place I can find in the WebKit code that uses this
1315 // function is WebView::registerViewClass, where it is used as part of the
1316 // process by which custom view classes for certain document representations
1318 String mimeType("x-apple-web-kit/");
1319 mimeType.append(scheme.lower());
1323 void FrameLoaderClientImpl::frameLoadCompleted()
1325 // FIXME: the mac port also conditionally calls setDrawsBackground:YES on
1326 // it's ScrollView here.
1328 // This comment from the Mac port:
1329 // Note: Can be called multiple times.
1330 // Even if already complete, we might have set a previous item on a frame that
1331 // didn't do any data loading on the past transaction. Make sure to clear these out.
1333 // FIXME: setPreviousHistoryItem() no longer exists. http://crbug.com/8566
1334 // m_webFrame->frame()->loader()->setPreviousHistoryItem(0);
1337 void FrameLoaderClientImpl::saveViewStateToItem(HistoryItem*)
1342 void FrameLoaderClientImpl::restoreViewState()
1344 // FIXME: probably scrolls to last position when you go back or forward
1347 void FrameLoaderClientImpl::provisionalLoadStarted()
1349 // FIXME: On mac, this does various caching stuff
1352 void FrameLoaderClientImpl::didFinishLoad()
1354 OwnPtr<WebPluginLoadObserver> observer = pluginLoadObserver();
1356 observer->didFinishLoading();
1359 void FrameLoaderClientImpl::prepareForDataSourceReplacement()
1364 PassRefPtr<DocumentLoader> FrameLoaderClientImpl::createDocumentLoader(
1365 const ResourceRequest& request,
1366 const SubstituteData& data)
1368 RefPtr<WebDataSourceImpl> ds = WebDataSourceImpl::create(request, data);
1369 if (m_webFrame->client())
1370 m_webFrame->client()->didCreateDataSource(m_webFrame, ds.get());
1371 return ds.release();
1374 void FrameLoaderClientImpl::setTitle(const StringWithDirection& title, const KURL& url)
1376 // FIXME: inform consumer of changes to the title.
1379 String FrameLoaderClientImpl::userAgent(const KURL& url)
1381 return webKitClient()->userAgent(url);
1384 void FrameLoaderClientImpl::savePlatformDataToCachedFrame(CachedFrame*)
1386 // The page cache should be disabled.
1387 ASSERT_NOT_REACHED();
1390 void FrameLoaderClientImpl::transitionToCommittedFromCachedFrame(CachedFrame*)
1392 ASSERT_NOT_REACHED();
1395 // Called when the FrameLoader goes into a state in which a new page load
1397 void FrameLoaderClientImpl::transitionToCommittedForNewPage()
1402 void FrameLoaderClientImpl::didSaveToPageCache()
1406 void FrameLoaderClientImpl::didRestoreFromPageCache()
1410 void FrameLoaderClientImpl::dispatchDidBecomeFrameset(bool)
1414 bool FrameLoaderClientImpl::canCachePage() const
1416 // Since we manage the cache, always report this page as non-cacheable to
1421 // Downloading is handled in the browser process, not WebKit. If we get to this
1422 // point, our download detection code in the ResourceDispatcherHost is broken!
1423 void FrameLoaderClientImpl::download(ResourceHandle* handle,
1424 const ResourceRequest& request,
1425 const ResourceRequest& initialRequest,
1426 const ResourceResponse& response)
1428 ASSERT_NOT_REACHED();
1431 PassRefPtr<Frame> FrameLoaderClientImpl::createFrame(
1434 HTMLFrameOwnerElement* ownerElement,
1435 const String& referrer,
1436 bool allowsScrolling,
1440 FrameLoadRequest frameRequest(m_webFrame->frame()->document()->securityOrigin(),
1441 ResourceRequest(url, referrer), name);
1442 return m_webFrame->createChildFrame(frameRequest, ownerElement);
1445 void FrameLoaderClientImpl::didTransferChildFrameToNewDocument(Page*)
1447 ASSERT(m_webFrame->frame()->ownerElement());
1449 WebFrameImpl* newParent = static_cast<WebFrameImpl*>(m_webFrame->parent());
1450 if (!newParent || !newParent->client())
1453 // Replace the client since the old client may be destroyed when the
1454 // previous page is closed.
1455 m_webFrame->setClient(newParent->client());
1458 void FrameLoaderClientImpl::transferLoadingResourceFromPage(ResourceLoader* loader, const ResourceRequest& request, Page* oldPage)
1460 assignIdentifierToInitialRequest(loader->identifier(), loader->documentLoader(), request);
1462 WebFrameImpl* oldWebFrame = WebFrameImpl::fromFrame(oldPage->mainFrame());
1463 if (oldWebFrame && oldWebFrame->client())
1464 oldWebFrame->client()->removeIdentifierForRequest(loader->identifier());
1466 ResourceHandle* handle = loader->handle();
1467 WebURLLoader* webURLLoader = ResourceHandleInternal::FromResourceHandle(handle)->loader();
1468 if (webURLLoader && m_webFrame->client())
1469 m_webFrame->client()->didAdoptURLLoader(webURLLoader);
1472 PassRefPtr<Widget> FrameLoaderClientImpl::createPlugin(
1473 const IntSize& size, // FIXME: how do we use this?
1474 HTMLPlugInElement* element,
1476 const Vector<String>& paramNames,
1477 const Vector<String>& paramValues,
1478 const String& mimeType,
1481 if (!m_webFrame->client())
1484 WebPluginParams params;
1486 params.mimeType = mimeType;
1487 params.attributeNames = paramNames;
1488 params.attributeValues = paramValues;
1489 params.loadManually = loadManually;
1491 WebPlugin* webPlugin = m_webFrame->client()->createPlugin(m_webFrame, params);
1495 // The container takes ownership of the WebPlugin.
1496 RefPtr<WebPluginContainerImpl> container =
1497 WebPluginContainerImpl::create(element, webPlugin);
1499 if (!webPlugin->initialize(container.get()))
1502 // The element might have been removed during plugin initialization!
1503 if (!element->renderer())
1509 // This method gets called when a plugin is put in place of html content
1510 // (e.g., acrobat reader).
1511 void FrameLoaderClientImpl::redirectDataToPlugin(Widget* pluginWidget)
1513 if (pluginWidget->isPluginContainer())
1514 m_pluginWidget = static_cast<WebPluginContainerImpl*>(pluginWidget);
1515 ASSERT(m_pluginWidget.get());
1518 PassRefPtr<Widget> FrameLoaderClientImpl::createJavaAppletWidget(
1519 const IntSize& size,
1520 HTMLAppletElement* element,
1521 const KURL& /* baseURL */,
1522 const Vector<String>& paramNames,
1523 const Vector<String>& paramValues)
1525 return createPlugin(size, element, KURL(), paramNames, paramValues,
1526 "application/x-java-applet", false);
1529 ObjectContentType FrameLoaderClientImpl::objectContentType(
1531 const String& explicitMimeType,
1532 bool shouldPreferPlugInsForImages)
1534 // This code is based on Apple's implementation from
1535 // WebCoreSupport/WebFrameBridge.mm.
1537 String mimeType = explicitMimeType;
1538 if (mimeType.isEmpty()) {
1539 // Try to guess the MIME type based off the extension.
1540 String filename = url.lastPathComponent();
1541 int extensionPos = filename.reverseFind('.');
1542 if (extensionPos >= 0) {
1543 String extension = filename.substring(extensionPos + 1);
1544 mimeType = MIMETypeRegistry::getMIMETypeForExtension(extension);
1545 if (mimeType.isEmpty()) {
1546 // If there's no mimetype registered for the extension, check to see
1547 // if a plugin can handle the extension.
1548 mimeType = getPluginMimeTypeFromExtension(extension);
1552 if (mimeType.isEmpty())
1553 return ObjectContentFrame;
1556 // If Chrome is started with the --disable-plugins switch, pluginData is 0.
1557 PluginData* pluginData = m_webFrame->frame()->page()->pluginData();
1558 bool plugInSupportsMIMEType = pluginData && pluginData->supportsMimeType(mimeType);
1560 if (MIMETypeRegistry::isSupportedImageMIMEType(mimeType))
1561 return shouldPreferPlugInsForImages && plugInSupportsMIMEType ? ObjectContentNetscapePlugin : ObjectContentImage;
1563 if (plugInSupportsMIMEType)
1564 return ObjectContentNetscapePlugin;
1566 if (MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType))
1567 return ObjectContentFrame;
1569 return ObjectContentNone;
1572 String FrameLoaderClientImpl::overrideMediaType() const
1578 bool FrameLoaderClientImpl::actionSpecifiesNavigationPolicy(
1579 const NavigationAction& action,
1580 WebNavigationPolicy* policy)
1582 const MouseEvent* event = 0;
1583 if (action.type() == NavigationTypeLinkClicked
1584 && action.event()->isMouseEvent())
1585 event = static_cast<const MouseEvent*>(action.event());
1586 else if (action.type() == NavigationTypeFormSubmitted
1588 && action.event()->underlyingEvent()
1589 && action.event()->underlyingEvent()->isMouseEvent())
1590 event = static_cast<const MouseEvent*>(action.event()->underlyingEvent());
1595 return WebViewImpl::navigationPolicyFromMouseEvent(
1596 event->button(), event->ctrlKey(), event->shiftKey(), event->altKey(),
1597 event->metaKey(), policy);
1600 PassOwnPtr<WebPluginLoadObserver> FrameLoaderClientImpl::pluginLoadObserver()
1602 WebDataSourceImpl* ds = WebDataSourceImpl::fromDocumentLoader(
1603 m_webFrame->frame()->loader()->activeDocumentLoader());
1605 // We can arrive here if a popstate event handler detaches this frame.
1606 // FIXME: Remove this code once http://webkit.org/b/36202 is fixed.
1607 ASSERT(!m_webFrame->frame()->page());
1610 return ds->releasePluginLoadObserver();
1613 PassRefPtr<FrameNetworkingContext> FrameLoaderClientImpl::createNetworkingContext()
1615 return FrameNetworkingContextImpl::create(m_webFrame->frame());
1618 } // namespace WebKit