summaryrefslogtreecommitdiffstats
path: root/content
diff options
context:
space:
mode:
authornasko@chromium.org <nasko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-04 21:14:18 +0000
committernasko@chromium.org <nasko@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-03-04 21:14:18 +0000
commit65920f331b2945f739abdbb8a3ede4ca68f142a6 (patch)
tree08f9cbc66775fbabdcf35e97913d9d8762cf4a59 /content
parent3a1f1144d2385c01e62f9b474b173a8a8af47608 (diff)
downloadchromium_src-65920f331b2945f739abdbb8a3ede4ca68f142a6.zip
chromium_src-65920f331b2945f739abdbb8a3ede4ca68f142a6.tar.gz
chromium_src-65920f331b2945f739abdbb8a3ede4ca68f142a6.tar.bz2
Move OpenURL from RenderView to RenderFrame.
This CL is follow up attempt at landing this change. The original CL is https://codereview.chromium.org/165063003 and is also ps1. BUG=304341 R=creis@chromium.org Review URL: https://codereview.chromium.org/186623004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@254821 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content')
-rw-r--r--content/browser/frame_host/navigator.h26
-rw-r--r--content/browser/frame_host/navigator_delegate.h6
-rw-r--r--content/browser/frame_host/navigator_impl.cc103
-rw-r--r--content/browser/frame_host/navigator_impl.h18
-rw-r--r--content/browser/frame_host/render_frame_host_impl.cc11
-rw-r--r--content/browser/frame_host/render_frame_host_impl.h2
-rw-r--r--content/browser/frame_host/render_frame_host_manager.cc11
-rw-r--r--content/browser/renderer_host/render_view_host_delegate.h23
-rw-r--r--content/browser/renderer_host/render_view_host_impl.cc11
-rw-r--r--content/browser/renderer_host/render_view_host_impl.h2
-rw-r--r--content/browser/security_exploit_browsertest.cc7
-rw-r--r--content/browser/web_contents/web_contents_impl.cc105
-rw-r--r--content/browser/web_contents/web_contents_impl.h18
-rw-r--r--content/common/frame_messages.h12
-rw-r--r--content/common/swapped_out_messages.cc2
-rw-r--r--content/common/view_messages.h12
-rw-r--r--content/renderer/render_frame_impl.cc304
-rw-r--r--content/renderer/render_frame_impl.h14
-rw-r--r--content/renderer/render_view_impl.cc293
-rw-r--r--content/renderer/render_view_impl.h20
-rw-r--r--content/shell/renderer/test_runner/WebFrameTestProxy.h4
-rw-r--r--content/shell/renderer/test_runner/WebTestProxy.h7
22 files changed, 533 insertions, 478 deletions
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h
index 52f6697..9637d677 100644
--- a/content/browser/frame_host/navigator.h
+++ b/content/browser/frame_host/navigator.h
@@ -8,6 +8,7 @@
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
#include "content/public/browser/navigation_controller.h"
+#include "ui/base/window_open_disposition.h"
class GURL;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
@@ -88,6 +89,31 @@ class CONTENT_EXPORT Navigator : public base::RefCounted<Navigator> {
virtual base::TimeTicks GetCurrentLoadStart();
+ // The RenderFrameHostImpl has received a request to open a URL with the
+ // specified |disposition|.
+ virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ int64 source_frame_id,
+ bool should_replace_current_entry,
+ bool user_gesture) {}
+
+ // The RenderFrameHostImpl wants to transfer the request to a new renderer.
+ // |redirect_chain| contains any redirect URLs (excluding |url|) that happened
+ // before the transfer.
+ virtual void RequestTransferURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const std::vector<GURL>& redirect_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ WindowOpenDisposition disposition,
+ int64 source_frame_id,
+ const GlobalRequestID& transferred_global_request_id,
+ bool should_replace_current_entry,
+ bool user_gesture) {}
+
protected:
friend class base::RefCounted<Navigator>;
virtual ~Navigator() {}
diff --git a/content/browser/frame_host/navigator_delegate.h b/content/browser/frame_host/navigator_delegate.h
index 75280de..6b871da 100644
--- a/content/browser/frame_host/navigator_delegate.h
+++ b/content/browser/frame_host/navigator_delegate.h
@@ -9,6 +9,7 @@
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/common/page_transition_types.h"
+#include "ui/base/window_open_disposition.h"
class GURL;
struct FrameHostMsg_DidCommitProvisionalLoad_Params;
@@ -18,6 +19,7 @@ namespace content {
class RenderFrameHostImpl;
struct LoadCommittedDetails;
+struct OpenURLParams;
// A delegate API used by Navigator to notify its embedder of navigation
// related events.
@@ -89,6 +91,10 @@ class CONTENT_EXPORT NavigatorDelegate {
RenderFrameHostImpl* render_frame_host,
const GURL& url,
NavigationController::ReloadType reload_type) {}
+
+ // Opens a URL with the given parameters. See PageNavigator::OpenURL, which
+ // this forwards to.
+ virtual void RequestOpenURL(const OpenURLParams& params) {}
};
} // namspace content
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc
index 60b1f825..59a2af2 100644
--- a/content/browser/frame_host/navigator_impl.cc
+++ b/content/browser/frame_host/navigator_impl.cc
@@ -14,13 +14,16 @@
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
+#include "content/browser/webui/web_ui_impl.h"
#include "content/common/frame_messages.h"
#include "content/common/view_messages.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
+#include "content/public/browser/global_request_id.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
+#include "content/public/browser/page_navigator.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
@@ -111,6 +114,13 @@ void MakeNavigateParams(const NavigationEntryImpl& entry,
params->frame_to_navigate = entry.GetFrameToNavigate();
}
+RenderFrameHostManager* GetRenderManager(RenderFrameHostImpl* rfh) {
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess))
+ return rfh->frame_tree_node()->render_manager();
+
+ return rfh->frame_tree_node()->frame_tree()->root()->render_manager();
+}
+
} // namespace
@@ -528,4 +538,97 @@ bool NavigatorImpl::ShouldAssignSiteForURL(const GURL& url) {
return GetContentClient()->browser()->ShouldAssignSiteForURL(url);
}
+void NavigatorImpl::RequestOpenURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ int64 source_frame_id,
+ bool should_replace_current_entry,
+ bool user_gesture) {
+ SiteInstance* current_site_instance =
+ GetRenderManager(render_frame_host)->current_frame_host()->
+ GetSiteInstance();
+ // If this came from a swapped out RenderViewHost, we only allow the request
+ // if we are still in the same BrowsingInstance.
+ if (render_frame_host->render_view_host()->IsSwappedOut() &&
+ !render_frame_host->GetSiteInstance()->IsRelatedSiteInstance(
+ current_site_instance)) {
+ return;
+ }
+
+ // Delegate to RequestTransferURL because this is just the generic
+ // case where |old_request_id| is empty.
+ // TODO(creis): Pass the redirect_chain into this method to support client
+ // redirects. http://crbug.com/311721.
+ std::vector<GURL> redirect_chain;
+ RequestTransferURL(
+ render_frame_host, url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
+ disposition, source_frame_id, GlobalRequestID(),
+ should_replace_current_entry, user_gesture);
+}
+
+void NavigatorImpl::RequestTransferURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const std::vector<GURL>& redirect_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ WindowOpenDisposition disposition,
+ int64 source_frame_id,
+ const GlobalRequestID& transferred_global_request_id,
+ bool should_replace_current_entry,
+ bool user_gesture) {
+ GURL dest_url(url);
+ SiteInstance* current_site_instance =
+ GetRenderManager(render_frame_host)->current_frame_host()->
+ GetSiteInstance();
+ if (!GetContentClient()->browser()->ShouldAllowOpenURL(
+ current_site_instance, url)) {
+ dest_url = GURL(kAboutBlankURL);
+ }
+
+ // Look up the FrameTreeNode ID corresponding to source_frame_id.
+ int64 frame_tree_node_id = -1;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
+ source_frame_id != -1) {
+ FrameTreeNode* source_node =
+ render_frame_host->frame_tree_node()->frame_tree()->FindByRoutingID(
+ source_frame_id, transferred_global_request_id.child_id);
+ if (source_node)
+ frame_tree_node_id = source_node->frame_tree_node_id();
+ }
+ OpenURLParams params(
+ dest_url, referrer, source_frame_id, frame_tree_node_id, disposition,
+ page_transition, true /* is_renderer_initiated */);
+ if (redirect_chain.size() > 0)
+ params.redirect_chain = redirect_chain;
+ params.transferred_global_request_id = transferred_global_request_id;
+ params.should_replace_current_entry = should_replace_current_entry;
+ params.user_gesture = user_gesture;
+
+ if (GetRenderManager(render_frame_host)->web_ui()) {
+ // Web UI pages sometimes want to override the page transition type for
+ // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
+ // automatically generated suggestions). We don't override other types
+ // like TYPED because they have different implications (e.g., autocomplete).
+ if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
+ params.transition =
+ GetRenderManager(render_frame_host)->web_ui()->
+ GetLinkTransitionType();
+
+ // Note also that we hide the referrer for Web UI pages. We don't really
+ // want web sites to see a referrer of "chrome://blah" (and some
+ // chrome: URLs might have search terms or other stuff we don't want to
+ // send to the site), so we send no referrer.
+ params.referrer = Referrer();
+
+ // Navigations in Web UI pages count as browser-initiated navigations.
+ params.is_renderer_initiated = false;
+ }
+
+ if (delegate_)
+ delegate_->RequestOpenURL(params);
+}
+
} // namespace content
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h
index 2565ffb..14f1ce5 100644
--- a/content/browser/frame_host/navigator_impl.h
+++ b/content/browser/frame_host/navigator_impl.h
@@ -51,6 +51,24 @@ class CONTENT_EXPORT NavigatorImpl : public Navigator {
RenderFrameHostImpl* render_frame_host,
NavigationController::ReloadType reload_type) OVERRIDE;
virtual base::TimeTicks GetCurrentLoadStart() OVERRIDE;
+ virtual void RequestOpenURL(RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const Referrer& referrer,
+ WindowOpenDisposition disposition,
+ int64 source_frame_id,
+ bool should_replace_current_entry,
+ bool user_gesture) OVERRIDE;
+ virtual void RequestTransferURL(
+ RenderFrameHostImpl* render_frame_host,
+ const GURL& url,
+ const std::vector<GURL>& redirect_chain,
+ const Referrer& referrer,
+ PageTransition page_transition,
+ WindowOpenDisposition disposition,
+ int64 source_frame_id,
+ const GlobalRequestID& transferred_global_request_id,
+ bool should_replace_current_entry,
+ bool user_gesture) OVERRIDE;
private:
virtual ~NavigatorImpl() {}
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc
index 00b8397..fbf0aae 100644
--- a/content/browser/frame_host/render_frame_host_impl.cc
+++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -162,6 +162,7 @@ bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message &msg) {
OnNavigate(msg))
IPC_MESSAGE_HANDLER(FrameHostMsg_DidStartLoading, OnDidStartLoading)
IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
+ IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(FrameHostMsg_SwapOut_ACK, OnSwapOutACK)
IPC_MESSAGE_HANDLER(FrameHostMsg_ContextMenu, OnContextMenu)
IPC_END_MESSAGE_MAP_EX()
@@ -192,6 +193,16 @@ void RenderFrameHostImpl::OnDetach() {
frame_tree_->RemoveFrame(frame_tree_node_);
}
+void RenderFrameHostImpl::OnOpenURL(
+ const FrameHostMsg_OpenURL_Params& params) {
+ GURL validated_url(params.url);
+ GetProcess()->FilterURL(false, &validated_url);
+
+ frame_tree_node_->navigator()->RequestOpenURL(
+ this, validated_url, params.referrer, params.disposition, params.frame_id,
+ params.should_replace_current_entry, params.user_gesture);
+}
+
void RenderFrameHostImpl::OnDidStartProvisionalLoadForFrame(
int parent_routing_id,
bool is_main_frame,
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h
index 4b83d44..7db02602 100644
--- a/content/browser/frame_host/render_frame_host_impl.h
+++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -15,6 +15,7 @@
class GURL;
struct FrameHostMsg_DidFailProvisionalLoadWithError_Params;
+struct FrameHostMsg_OpenURL_Params;
struct FrameMsg_Navigate_Params;
namespace base {
@@ -131,6 +132,7 @@ class CONTENT_EXPORT RenderFrameHostImpl : public RenderFrameHost {
// IPC Message handlers.
void OnDetach();
+ void OnOpenURL(const FrameHostMsg_OpenURL_Params& params);
void OnDidStartProvisionalLoadForFrame(int parent_routing_id,
bool main_frame,
const GURL& url);
diff --git a/content/browser/frame_host/render_frame_host_manager.cc b/content/browser/frame_host/render_frame_host_manager.cc
index 1887c68..5db47137 100644
--- a/content/browser/frame_host/render_frame_host_manager.cc
+++ b/content/browser/frame_host/render_frame_host_manager.cc
@@ -16,6 +16,7 @@
#include "content/browser/frame_host/interstitial_page_impl.h"
#include "content/browser/frame_host/navigation_controller_impl.h"
#include "content/browser/frame_host/navigation_entry_impl.h"
+#include "content/browser/frame_host/navigator.h"
#include "content/browser/frame_host/render_frame_host_factory.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/cross_site_transferring_request.h"
@@ -297,10 +298,14 @@ void RenderFrameHostManager::SwappedOut(RenderViewHost* render_view_host) {
GURL transfer_url = pending_nav_params_->transfer_url_chain.back();
pending_nav_params_->transfer_url_chain.pop_back();
+ RenderFrameHostImpl* render_frame_host =
+ static_cast<RenderFrameHostImpl*>(render_view_host->GetMainFrame());
+
// We don't know whether the original request had |user_action| set to true.
// However, since we force the navigation to be in the current tab, it
// doesn't matter.
- render_view_host->GetDelegate()->RequestTransferURL(
+ render_frame_host->frame_tree_node()->navigator()->RequestTransferURL(
+ render_frame_host,
transfer_url,
pending_nav_params_->transfer_url_chain,
pending_nav_params_->referrer,
@@ -352,8 +357,8 @@ void RenderFrameHostManager::SwappedOutFrame(
// We don't know whether the original request had |user_action| set to true.
// However, since we force the navigation to be in the current tab, it
// doesn't matter.
- // TODO(creis): Move RequestTransferURL to RenderFrameHost's navigator.
- render_frame_host->render_view_host()->GetDelegate()->RequestTransferURL(
+ render_frame_host->frame_tree_node()->navigator()->RequestTransferURL(
+ render_frame_host,
transfer_url,
pending_nav_params_->transfer_url_chain,
pending_nav_params_->referrer,
diff --git a/content/browser/renderer_host/render_view_host_delegate.h b/content/browser/renderer_host/render_view_host_delegate.h
index 7b9a64c..e7f9684ff 100644
--- a/content/browser/renderer_host/render_view_host_delegate.h
+++ b/content/browser/renderer_host/render_view_host_delegate.h
@@ -204,29 +204,6 @@ class CONTENT_EXPORT RenderViewHostDelegate {
RenderViewHost* render_view_host,
int32 page_id) {}
- // The page wants to open a URL with the specified disposition.
- virtual void RequestOpenURL(RenderViewHost* rvh,
- const GURL& url,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- int64 source_frame_id,
- bool is_redirect,
- bool user_gesture) {}
-
- // The page wants to transfer the request to a new renderer.
- // |redirect_chain| contains any redirect URLs (excluding |url|) that happened
- // before the transfer.
- virtual void RequestTransferURL(
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const Referrer& referrer,
- PageTransition page_transition,
- WindowOpenDisposition disposition,
- int64 source_frame_id,
- const GlobalRequestID& old_request_id,
- bool is_redirect,
- bool user_gesture) {}
-
// The page wants to close the active view in this tab.
virtual void RouteCloseEvent(RenderViewHost* rvh) {}
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc
index 05d75ab..55918f0 100644
--- a/content/browser/renderer_host/render_view_host_impl.cc
+++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -1162,7 +1162,6 @@ bool RenderViewHostImpl::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_DocumentOnLoadCompletedInMainFrame,
OnDocumentOnLoadCompletedInMainFrame)
IPC_MESSAGE_HANDLER(ViewHostMsg_ToggleFullscreen, OnToggleFullscreen)
- IPC_MESSAGE_HANDLER(ViewHostMsg_OpenURL, OnOpenURL)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidContentsPreferredSizeChange,
OnDidContentsPreferredSizeChange)
IPC_MESSAGE_HANDLER(ViewHostMsg_DidChangeScrollOffset,
@@ -1399,16 +1398,6 @@ void RenderViewHostImpl::OnToggleFullscreen(bool enter_fullscreen) {
WasResized();
}
-void RenderViewHostImpl::OnOpenURL(
- const ViewHostMsg_OpenURL_Params& params) {
- GURL validated_url(params.url);
- GetProcess()->FilterURL(false, &validated_url);
-
- delegate_->RequestOpenURL(
- this, validated_url, params.referrer, params.disposition, params.frame_id,
- params.should_replace_current_entry, params.user_gesture);
-}
-
void RenderViewHostImpl::OnDidContentsPreferredSizeChange(
const gfx::Size& new_size) {
delegate_->UpdatePreferredSize(new_size);
diff --git a/content/browser/renderer_host/render_view_host_impl.h b/content/browser/renderer_host/render_view_host_impl.h
index 9fdbd0a..a6ed120 100644
--- a/content/browser/renderer_host/render_view_host_impl.h
+++ b/content/browser/renderer_host/render_view_host_impl.h
@@ -37,7 +37,6 @@ struct AccessibilityHostMsg_EventParams;
struct AccessibilityHostMsg_LocationChangeParams;
struct MediaPlayerAction;
struct ViewHostMsg_CreateWindow_Params;
-struct ViewHostMsg_OpenURL_Params;
struct ViewHostMsg_SelectionBounds_Params;
struct ViewHostMsg_ShowPopup_Params;
struct FrameMsg_Navigate_Params;
@@ -566,7 +565,6 @@ class CONTENT_EXPORT RenderViewHostImpl
void OnDocumentAvailableInMainFrame();
void OnDocumentOnLoadCompletedInMainFrame(int32 page_id);
void OnToggleFullscreen(bool enter_fullscreen);
- void OnOpenURL(const ViewHostMsg_OpenURL_Params& params);
void OnDidContentsPreferredSizeChange(const gfx::Size& new_size);
void OnDidChangeScrollOffset();
void OnDidChangeScrollbarsForMainFrame(bool has_horizontal_scrollbar,
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
index 883fb8c..4da524a 100644
--- a/content/browser/security_exploit_browsertest.cc
+++ b/content/browser/security_exploit_browsertest.cc
@@ -6,6 +6,7 @@
#include "base/containers/hash_tables.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/dom_storage/session_storage_namespace_impl.h"
+#include "content/browser/frame_host/navigator.h"
#include "content/browser/renderer_host/render_view_host_factory.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
@@ -56,10 +57,10 @@ RenderViewHostImpl* PrepareToDuplicateHosts(Shell* shell,
// Now, simulate a link click coming from the renderer.
GURL extension_url("https://bar.com/files/simple_page.html");
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell->web_contents());
- wc->RequestOpenURL(
- shell->web_contents()->GetRenderViewHost(), extension_url,
+ wc->GetFrameTree()->root()->navigator()->RequestOpenURL(
+ wc->GetFrameTree()->root()->current_frame_host(), extension_url,
Referrer(), CURRENT_TAB,
- wc->GetFrameTree()->GetMainFrame()->GetRoutingID(),
+ wc->GetFrameTree()->root()->current_frame_host()->GetRoutingID(),
false, true);
// Since the navigation above requires a cross-process swap, there will be a
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6472aa0..7a0920b 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2090,6 +2090,21 @@ void WebContentsImpl::DidStartNavigationToPendingEntry(
DidStartNavigationToPendingEntry(url, reload_type));
}
+void WebContentsImpl::RequestOpenURL(const OpenURLParams& params) {
+ WebContents* new_contents = OpenURL(params);
+
+ if (new_contents) {
+ // Notify observers.
+ FOR_EACH_OBSERVER(WebContentsObserver, observers_,
+ DidOpenRequestedURL(new_contents,
+ params.url,
+ params.referrer,
+ params.disposition,
+ params.transition,
+ params.source_frame_id));
+ }
+}
+
void WebContentsImpl::DidRedirectProvisionalLoad(
RenderFrameHostImpl* render_frame_host,
const GURL& validated_target_url) {
@@ -3033,96 +3048,6 @@ void WebContentsImpl::DocumentOnLoadCompletedInMainFrame(
Details<int>(&page_id));
}
-void WebContentsImpl::RequestOpenURL(RenderViewHost* rvh,
- const GURL& url,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- int64 source_frame_id,
- bool should_replace_current_entry,
- bool user_gesture) {
- // If this came from a swapped out RenderViewHost, we only allow the request
- // if we are still in the same BrowsingInstance.
- if (static_cast<RenderViewHostImpl*>(rvh)->IsSwappedOut() &&
- !rvh->GetSiteInstance()->IsRelatedSiteInstance(GetSiteInstance())) {
- return;
- }
-
- // Delegate to RequestTransferURL because this is just the generic
- // case where |old_request_id| is empty.
- // TODO(creis): Pass the redirect_chain into this method to support client
- // redirects. http://crbug.com/311721.
- std::vector<GURL> redirect_chain;
- RequestTransferURL(url, redirect_chain, referrer, PAGE_TRANSITION_LINK,
- disposition, source_frame_id, GlobalRequestID(),
- should_replace_current_entry, user_gesture);
-}
-
-void WebContentsImpl::RequestTransferURL(
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const Referrer& referrer,
- PageTransition page_transition,
- WindowOpenDisposition disposition,
- int64 source_frame_id,
- const GlobalRequestID& old_request_id,
- bool should_replace_current_entry,
- bool user_gesture) {
- WebContents* new_contents = NULL;
- GURL dest_url(url);
- if (!GetContentClient()->browser()->ShouldAllowOpenURL(
- GetSiteInstance(), url))
- dest_url = GURL(kAboutBlankURL);
-
- // Look up the FrameTreeNode ID corresponding to source_frame_id.
- int64 frame_tree_node_id = -1;
- if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
- source_frame_id != -1) {
- FrameTreeNode* source_node = frame_tree_.FindByRoutingID(
- source_frame_id, old_request_id.child_id);
- if (source_node)
- frame_tree_node_id = source_node->frame_tree_node_id();
- }
- OpenURLParams params(dest_url, referrer, source_frame_id,
- frame_tree_node_id, disposition,
- page_transition, true /* is_renderer_initiated */);
- if (redirect_chain.size() > 0)
- params.redirect_chain = redirect_chain;
- params.transferred_global_request_id = old_request_id;
- params.should_replace_current_entry = should_replace_current_entry;
- params.user_gesture = user_gesture;
-
- if (GetRenderManager()->web_ui()) {
- // Web UI pages sometimes want to override the page transition type for
- // link clicks (e.g., so the new tab page can specify AUTO_BOOKMARK for
- // automatically generated suggestions). We don't override other types
- // like TYPED because they have different implications (e.g., autocomplete).
- if (PageTransitionCoreTypeIs(params.transition, PAGE_TRANSITION_LINK))
- params.transition = GetRenderManager()->web_ui()->GetLinkTransitionType();
-
- // Note also that we hide the referrer for Web UI pages. We don't really
- // want web sites to see a referrer of "chrome://blah" (and some
- // chrome: URLs might have search terms or other stuff we don't want to
- // send to the site), so we send no referrer.
- params.referrer = Referrer();
-
- // Navigations in Web UI pages count as browser-initiated navigations.
- params.is_renderer_initiated = false;
- }
-
- new_contents = OpenURL(params);
-
- if (new_contents) {
- // Notify observers.
- FOR_EACH_OBSERVER(WebContentsObserver, observers_,
- DidOpenRequestedURL(new_contents,
- dest_url,
- referrer,
- disposition,
- params.transition,
- source_frame_id));
- }
-}
-
void WebContentsImpl::RouteCloseEvent(RenderViewHost* rvh) {
// Tell the active RenderViewHost to run unload handlers and close, as long
// as the request came from a RenderViewHost in the same BrowsingInstance.
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index c798c55..45e4224 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -352,23 +352,6 @@ class CONTENT_EXPORT WebContentsImpl
virtual void DocumentOnLoadCompletedInMainFrame(
RenderViewHost* render_view_host,
int32 page_id) OVERRIDE;
- virtual void RequestOpenURL(RenderViewHost* rvh,
- const GURL& url,
- const Referrer& referrer,
- WindowOpenDisposition disposition,
- int64 source_frame_id,
- bool should_replace_current_entry,
- bool user_gesture) OVERRIDE;
- virtual void RequestTransferURL(
- const GURL& url,
- const std::vector<GURL>& redirect_chain,
- const Referrer& referrer,
- PageTransition page_transition,
- WindowOpenDisposition disposition,
- int64 source_frame_id,
- const GlobalRequestID& transferred_global_request_id,
- bool should_replace_current_entry,
- bool user_gesture) OVERRIDE;
virtual void RouteCloseEvent(RenderViewHost* rvh) OVERRIDE;
virtual void RouteMessageEvent(
RenderViewHost* rvh,
@@ -489,6 +472,7 @@ class CONTENT_EXPORT WebContentsImpl
RenderFrameHostImpl* render_frame_host,
const GURL& url,
NavigationController::ReloadType reload_type) OVERRIDE;
+ virtual void RequestOpenURL(const OpenURLParams& params) OVERRIDE;
// RenderWidgetHostDelegate --------------------------------------------------
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h
index 4782282..a8a2898 100644
--- a/content/common/frame_messages.h
+++ b/content/common/frame_messages.h
@@ -243,6 +243,15 @@ IPC_STRUCT_BEGIN(FrameMsg_Navigate_Params)
IPC_STRUCT_MEMBER(base::TimeTicks, browser_navigation_start)
IPC_STRUCT_END()
+IPC_STRUCT_BEGIN(FrameHostMsg_OpenURL_Params)
+ IPC_STRUCT_MEMBER(GURL, url)
+ IPC_STRUCT_MEMBER(content::Referrer, referrer)
+ IPC_STRUCT_MEMBER(WindowOpenDisposition, disposition)
+ IPC_STRUCT_MEMBER(int64, frame_id)
+ IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
+ IPC_STRUCT_MEMBER(bool, user_gesture)
+IPC_STRUCT_END()
+
// -----------------------------------------------------------------------------
// Messages sent from the browser to the renderer.
@@ -344,6 +353,9 @@ IPC_MESSAGE_ROUTED0(FrameHostMsg_DidStartLoading)
// notion of the throbber stopping.
IPC_MESSAGE_ROUTED0(FrameHostMsg_DidStopLoading)
+// Requests that the given URL be opened in the specified manner.
+IPC_MESSAGE_ROUTED1(FrameHostMsg_OpenURL, FrameHostMsg_OpenURL_Params)
+
// Following message is used to communicate the values received by the
// callback binding the JS to Cpp.
// An instance of browser that has an automation host listening to it can
diff --git a/content/common/swapped_out_messages.cc b/content/common/swapped_out_messages.cc
index c41a645..855b786 100644
--- a/content/common/swapped_out_messages.cc
+++ b/content/common/swapped_out_messages.cc
@@ -21,7 +21,7 @@ bool SwappedOutMessages::CanSendWhileSwappedOut(const IPC::Message* msg) {
case InputHostMsg_HandleInputEvent_ACK::ID:
case ViewHostMsg_UpdateRect::ID:
// Allow targeted navigations while swapped out.
- case ViewHostMsg_OpenURL::ID:
+ case FrameHostMsg_OpenURL::ID:
case ViewHostMsg_Focus::ID:
// Handled by RenderViewHost.
case ViewHostMsg_RenderProcessGone::ID:
diff --git a/content/common/view_messages.h b/content/common/view_messages.h
index f210824..54a6aa8 100644
--- a/content/common/view_messages.h
+++ b/content/common/view_messages.h
@@ -337,15 +337,6 @@ IPC_STRUCT_BEGIN(ViewHostMsg_DateTimeDialogValue_Params)
IPC_STRUCT_MEMBER(std::vector<content::DateTimeSuggestion>, suggestions)
IPC_STRUCT_END()
-IPC_STRUCT_BEGIN(ViewHostMsg_OpenURL_Params)
- IPC_STRUCT_MEMBER(GURL, url)
- IPC_STRUCT_MEMBER(content::Referrer, referrer)
- IPC_STRUCT_MEMBER(WindowOpenDisposition, disposition)
- IPC_STRUCT_MEMBER(int64, frame_id)
- IPC_STRUCT_MEMBER(bool, should_replace_current_entry)
- IPC_STRUCT_MEMBER(bool, user_gesture)
-IPC_STRUCT_END()
-
IPC_STRUCT_BEGIN(ViewHostMsg_SelectionBounds_Params)
IPC_STRUCT_MEMBER(gfx::Rect, anchor_rect)
IPC_STRUCT_MEMBER(blink::WebTextDirection, anchor_dir)
@@ -1483,9 +1474,6 @@ IPC_SYNC_MESSAGE_ROUTED4_2(ViewHostMsg_RunJavaScriptMessage,
bool /* out - success */,
base::string16 /* out - user_input field */)
-// Requests that the given URL be opened in the specified manner.
-IPC_MESSAGE_ROUTED1(ViewHostMsg_OpenURL, ViewHostMsg_OpenURL_Params)
-
// Notifies that the preferred size of the content changed.
IPC_MESSAGE_ROUTED1(ViewHostMsg_DidContentsPreferredSizeChange,
gfx::Size /* pref_size */)
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc
index 5ede1bc..e5ed785 100644
--- a/content/renderer/render_frame_impl.cc
+++ b/content/renderer/render_frame_impl.cc
@@ -46,6 +46,7 @@
#include "content/renderer/dom_automation_controller.h"
#include "content/renderer/internal_document_state_data.h"
#include "content/renderer/npapi/plugin_channel_host.h"
+#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/render_view_impl.h"
#include "content/renderer/render_widget_fullscreen_pepper.h"
@@ -54,6 +55,7 @@
#include "content/renderer/websharedworker_proxy.h"
#include "net/base/data_url.h"
#include "net/base/net_errors.h"
+#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_util.h"
#include "third_party/WebKit/public/platform/WebStorageQuotaCallbacks.h"
#include "third_party/WebKit/public/platform/WebString.h"
@@ -94,6 +96,7 @@ using blink::WebFrame;
using blink::WebHistoryItem;
using blink::WebHTTPBody;
using blink::WebNavigationPolicy;
+using blink::WebNavigationType;
using blink::WebPluginParams;
using blink::WebReferrerPolicy;
using blink::WebSearchableFormData;
@@ -211,6 +214,44 @@ static void MaybeHandleDebugURL(const GURL& url) {
#endif // ADDRESS_SANITIZER
}
+// Returns false unless this is a top-level navigation.
+static bool IsTopLevelNavigation(WebFrame* frame) {
+ return frame->parent() == NULL;
+}
+
+// Returns false unless this is a top-level navigation that crosses origins.
+static bool IsNonLocalTopLevelNavigation(const GURL& url,
+ WebFrame* frame,
+ WebNavigationType type,
+ bool is_form_post) {
+ if (!IsTopLevelNavigation(frame))
+ return false;
+
+ // Navigations initiated within Webkit are not sent out to the external host
+ // in the following cases.
+ // 1. The url scheme is not http/https
+ // 2. The origin of the url and the opener is the same in which case the
+ // opener relationship is maintained.
+ // 3. Reloads/form submits/back forward navigations
+ if (!url.SchemeIs(kHttpScheme) && !url.SchemeIs(kHttpsScheme))
+ return false;
+
+ if (type != blink::WebNavigationTypeReload &&
+ type != blink::WebNavigationTypeBackForward && !is_form_post) {
+ // The opener relationship between the new window and the parent allows the
+ // new window to script the parent and vice versa. This is not allowed if
+ // the origins of the two domains are different. This can be treated as a
+ // top level navigation and routed back to the host.
+ blink::WebFrame* opener = frame->opener();
+ if (!opener)
+ return true;
+
+ if (url.GetOrigin() != GURL(opener->document().url()).GetOrigin())
+ return true;
+ }
+ return false;
+}
+
} // namespace
static RenderFrameImpl* (*g_create_render_frame_impl)(RenderViewImpl*, int32) =
@@ -1107,7 +1148,7 @@ void RenderFrameImpl::loadURLExternally(
request.url(), referrer,
suggested_name));
} else {
- render_view_->OpenURL(frame, request.url(), referrer, policy);
+ OpenURL(frame, request.url(), referrer, policy);
}
}
@@ -1119,7 +1160,7 @@ blink::WebNavigationPolicy RenderFrameImpl::decidePolicyForNavigation(
blink::WebNavigationPolicy default_policy,
bool is_redirect) {
DCHECK(!frame_ || frame_ == frame);
- return render_view_->DecidePolicyForNavigation(
+ return DecidePolicyForNavigation(
this, frame, extra_data, request, type, default_policy, is_redirect);
}
@@ -2282,4 +2323,263 @@ void RenderFrameImpl::didStopLoading() {
Send(new FrameHostMsg_DidStopLoading(routing_id_));
}
+WebNavigationPolicy RenderFrameImpl::DecidePolicyForNavigation(
+ RenderFrame* render_frame,
+ WebFrame* frame,
+ WebDataSource::ExtraData* extraData,
+ const WebURLRequest& request,
+ WebNavigationType type,
+ WebNavigationPolicy default_policy,
+ bool is_redirect) {
+#ifdef OS_ANDROID
+ // The handlenavigation API is deprecated and will be removed once
+ // crbug.com/325351 is resolved.
+ if (request.url() != GURL(kSwappedOutURL) &&
+ GetContentClient()->renderer()->HandleNavigation(
+ render_frame,
+ static_cast<DocumentState*>(extraData),
+ render_view_->opener_id_,
+ frame,
+ request,
+ type,
+ default_policy,
+ is_redirect)) {
+ return blink::WebNavigationPolicyIgnore;
+ }
+#endif
+
+ Referrer referrer(RenderViewImpl::GetReferrerFromRequest(frame, request));
+
+ if (is_swapped_out_ || render_view_->is_swapped_out()) {
+ if (request.url() != GURL(kSwappedOutURL)) {
+ // Targeted links may try to navigate a swapped out frame. Allow the
+ // browser process to navigate the tab instead. Note that it is also
+ // possible for non-targeted navigations (from this view) to arrive
+ // here just after we are swapped out. It's ok to send them to the
+ // browser, as long as they're for the top level frame.
+ // TODO(creis): Ensure this supports targeted form submissions when
+ // fixing http://crbug.com/101395.
+ if (frame->parent() == NULL) {
+ OpenURL(frame, request.url(), referrer, default_policy);
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
+ }
+
+ // We should otherwise ignore in-process iframe navigations, if they
+ // arrive just after we are swapped out.
+ return blink::WebNavigationPolicyIgnore;
+ }
+
+ // Allow kSwappedOutURL to complete.
+ return default_policy;
+ }
+
+ // Webkit is asking whether to navigate to a new URL.
+ // This is fine normally, except if we're showing UI from one security
+ // context and they're trying to navigate to a different context.
+ const GURL& url = request.url();
+
+ // A content initiated navigation may have originated from a link-click,
+ // script, drag-n-drop operation, etc.
+ bool is_content_initiated = static_cast<DocumentState*>(extraData)->
+ navigation_state()->is_content_initiated();
+
+ // Experimental:
+ // If --enable-strict-site-isolation or --site-per-process is enabled, send
+ // all top-level navigations to the browser to let it swap processes when
+ // crossing site boundaries. This is currently expected to break some script
+ // calls and navigations, such as form submissions.
+ const CommandLine& command_line = *CommandLine::ForCurrentProcess();
+ bool force_swap_due_to_flag =
+ command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
+ command_line.HasSwitch(switches::kSitePerProcess);
+ if (force_swap_due_to_flag &&
+ !frame->parent() && (is_content_initiated || is_redirect)) {
+ WebString origin_str = frame->document().securityOrigin().toString();
+ GURL frame_url(origin_str.utf8().data());
+ // TODO(cevans): revisit whether this site check is still necessary once
+ // crbug.com/101395 is fixed.
+ bool same_domain_or_host =
+ net::registry_controlled_domains::SameDomainOrHost(
+ frame_url,
+ url,
+ net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
+ if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
+ OpenURL(frame, url, referrer, default_policy);
+ return blink::WebNavigationPolicyIgnore;
+ }
+ }
+
+ // If the browser is interested, then give it a chance to look at the request.
+ if (is_content_initiated) {
+ bool is_form_post = ((type == blink::WebNavigationTypeFormSubmitted) ||
+ (type == blink::WebNavigationTypeFormResubmitted)) &&
+ EqualsASCII(request.httpMethod(), "POST");
+ bool browser_handles_request =
+ render_view_->renderer_preferences_
+ .browser_handles_non_local_top_level_requests
+ && IsNonLocalTopLevelNavigation(url, frame, type, is_form_post);
+ if (!browser_handles_request) {
+ browser_handles_request = IsTopLevelNavigation(frame) &&
+ render_view_->renderer_preferences_
+ .browser_handles_all_top_level_requests;
+ }
+
+ if (browser_handles_request) {
+ // Reset these counters as the RenderView could be reused for the next
+ // navigation.
+ render_view_->page_id_ = -1;
+ render_view_->last_page_id_sent_to_browser_ = -1;
+ OpenURL(frame, url, referrer, default_policy);
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
+ }
+ }
+
+ // Use the frame's original request's URL rather than the document's URL for
+ // subsequent checks. For a popup, the document's URL may become the opener
+ // window's URL if the opener has called document.write().
+ // See http://crbug.com/93517.
+ GURL old_url(frame->dataSource()->request().url());
+
+ // Detect when we're crossing a permission-based boundary (e.g. into or out of
+ // an extension or app origin, leaving a WebUI page, etc). We only care about
+ // top-level navigations (not iframes). But we sometimes navigate to
+ // about:blank to clear a tab, and we want to still allow that.
+ //
+ // Note: this is known to break POST submissions when crossing process
+ // boundaries until http://crbug.com/101395 is fixed. This is better for
+ // security than loading a WebUI, extension or app page in the wrong process.
+ // POST requests don't work because this mechanism does not preserve form
+ // POST data. We will need to send the request's httpBody data up to the
+ // browser process, and issue a special POST navigation in WebKit (via
+ // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
+ // for examples of how to send the httpBody data.
+ if (!frame->parent() && is_content_initiated &&
+ !url.SchemeIs(chrome::kAboutScheme)) {
+ bool send_referrer = false;
+
+ // All navigations to or from WebUI URLs or within WebUI-enabled
+ // RenderProcesses must be handled by the browser process so that the
+ // correct bindings and data sources can be registered.
+ // Similarly, navigations to view-source URLs or within ViewSource mode
+ // must be handled by the browser process (except for reloads - those are
+ // safe to leave within the renderer).
+ // Lastly, access to file:// URLs from non-file:// URL pages must be
+ // handled by the browser so that ordinary renderer processes don't get
+ // blessed with file permissions.
+ int cumulative_bindings = RenderProcess::current()->GetEnabledBindings();
+ bool is_initial_navigation = render_view_->page_id_ == -1;
+ bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
+ (cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
+ url.SchemeIs(kViewSourceScheme) ||
+ (frame->isViewSourceModeEnabled() &&
+ type != blink::WebNavigationTypeReload);
+
+ if (!should_fork && url.SchemeIs(kFileScheme)) {
+ // Fork non-file to file opens. Check the opener URL if this is the
+ // initial navigation in a newly opened window.
+ GURL source_url(old_url);
+ if (is_initial_navigation && source_url.is_empty() && frame->opener())
+ source_url = frame->opener()->top()->document().url();
+ DCHECK(!source_url.is_empty());
+ should_fork = !source_url.SchemeIs(kFileScheme);
+ }
+
+ if (!should_fork) {
+ // Give the embedder a chance.
+ should_fork = GetContentClient()->renderer()->ShouldFork(
+ frame, url, request.httpMethod().utf8(), is_initial_navigation,
+ is_redirect, &send_referrer);
+ }
+
+ if (should_fork) {
+ OpenURL(
+ frame, url, send_referrer ? referrer : Referrer(), default_policy);
+ return blink::WebNavigationPolicyIgnore; // Suppress the load here.
+ }
+ }
+
+ // Detect when a page is "forking" a new tab that can be safely rendered in
+ // its own process. This is done by sites like Gmail that try to open links
+ // in new windows without script connections back to the original page. We
+ // treat such cases as browser navigations (in which we will create a new
+ // renderer for a cross-site navigation), rather than WebKit navigations.
+ //
+ // We use the following heuristic to decide whether to fork a new page in its
+ // own process:
+ // The parent page must open a new tab to about:blank, set the new tab's
+ // window.opener to null, and then redirect the tab to a cross-site URL using
+ // JavaScript.
+ //
+ // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
+ // (see below).
+ bool is_fork =
+ // Must start from a tab showing about:blank, which is later redirected.
+ old_url == GURL(kAboutBlankURL) &&
+ // Must be the first real navigation of the tab.
+ render_view_->historyBackListCount() < 1 &&
+ render_view_->historyForwardListCount() < 1 &&
+ // The parent page must have set the child's window.opener to null before
+ // redirecting to the desired URL.
+ frame->opener() == NULL &&
+ // Must be a top-level frame.
+ frame->parent() == NULL &&
+ // Must not have issued the request from this page.
+ is_content_initiated &&
+ // Must be targeted at the current tab.
+ default_policy == blink::WebNavigationPolicyCurrentTab &&
+ // Must be a JavaScript navigation, which appears as "other".
+ type == blink::WebNavigationTypeOther;
+
+ if (is_fork) {
+ // Open the URL via the browser, not via WebKit.
+ OpenURL(frame, url, Referrer(), default_policy);
+ return blink::WebNavigationPolicyIgnore;
+ }
+
+ return default_policy;
+}
+
+void RenderFrameImpl::OpenURL(WebFrame* frame,
+ const GURL& url,
+ const Referrer& referrer,
+ WebNavigationPolicy policy) {
+ DCHECK_EQ(frame_, frame);
+
+ FrameHostMsg_OpenURL_Params params;
+ params.url = url;
+ params.referrer = referrer;
+ params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy);
+ params.frame_id = RenderFrameImpl::FromWebFrame(frame)->GetRoutingID();
+ WebDataSource* ds = frame->provisionalDataSource();
+ if (ds) {
+ DocumentState* document_state = DocumentState::FromDataSource(ds);
+ NavigationState* navigation_state = document_state->navigation_state();
+ if (navigation_state->is_content_initiated()) {
+ params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
+ } else {
+ // This is necessary to preserve the should_replace_current_entry value on
+ // cross-process redirects, in the event it was set by a previous process.
+ //
+ // TODO(davidben): Avoid this awkward duplication of state. See comment on
+ // NavigationState::should_replace_current_entry().
+ params.should_replace_current_entry =
+ navigation_state->should_replace_current_entry();
+ }
+ } else {
+ params.should_replace_current_entry = false;
+ }
+ params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
+ if (GetContentClient()->renderer()->AllowPopup())
+ params.user_gesture = true;
+
+ if (policy == blink::WebNavigationPolicyNewBackgroundTab ||
+ policy == blink::WebNavigationPolicyNewForegroundTab ||
+ policy == blink::WebNavigationPolicyNewWindow ||
+ policy == blink::WebNavigationPolicyNewPopup) {
+ WebUserGestureIndicator::consumeUserGesture();
+ }
+
+ Send(new FrameHostMsg_OpenURL(routing_id_, params));
+}
+
} // namespace content
diff --git a/content/renderer/render_frame_impl.h b/content/renderer/render_frame_impl.h
index e5b750a..609d631 100644
--- a/content/renderer/render_frame_impl.h
+++ b/content/renderer/render_frame_impl.h
@@ -15,6 +15,7 @@
#include "base/observer_list.h"
#include "base/process/process_handle.h"
#include "base/strings/string16.h"
+#include "content/public/common/referrer.h"
#include "content/public/renderer/render_frame.h"
#include "content/renderer/renderer_webcookiejar_impl.h"
#include "ipc/ipc_message.h"
@@ -360,6 +361,19 @@ class CONTENT_EXPORT RenderFrameImpl
void OnContextMenuClosed(const CustomContextMenuContext& custom_context);
void OnCustomContextMenuAction(const CustomContextMenuContext& custom_context,
unsigned action);
+ // Virtual since overridden by WebTestProxy for layout tests.
+ virtual blink::WebNavigationPolicy DecidePolicyForNavigation(
+ RenderFrame* render_frame,
+ blink::WebFrame* frame,
+ blink::WebDataSource::ExtraData* extraData,
+ const blink::WebURLRequest& request,
+ blink::WebNavigationType type,
+ blink::WebNavigationPolicy default_policy,
+ bool is_redirect);
+ void OpenURL(blink::WebFrame* frame,
+ const GURL& url,
+ const Referrer& referrer,
+ blink::WebNavigationPolicy policy);
// Returns whether |params.selection_text| should be synchronized to the
// browser before bringing up the context menu. Static for testing.
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
index bf4357f..f4db0f2 100644
--- a/content/renderer/render_view_impl.cc
+++ b/content/renderer/render_view_impl.cc
@@ -378,44 +378,6 @@ Referrer RenderViewImpl::GetReferrerFromRequest(
request.referrerPolicy());
}
-// Returns false unless this is a top-level navigation.
-static bool IsTopLevelNavigation(WebFrame* frame) {
- return frame->parent() == NULL;
-}
-
-// Returns false unless this is a top-level navigation that crosses origins.
-static bool IsNonLocalTopLevelNavigation(const GURL& url,
- WebFrame* frame,
- WebNavigationType type,
- bool is_form_post) {
- if (!IsTopLevelNavigation(frame))
- return false;
-
- // Navigations initiated within Webkit are not sent out to the external host
- // in the following cases.
- // 1. The url scheme is not http/https
- // 2. The origin of the url and the opener is the same in which case the
- // opener relationship is maintained.
- // 3. Reloads/form submits/back forward navigations
- if (!url.SchemeIs(kHttpScheme) && !url.SchemeIs(kHttpsScheme))
- return false;
-
- if (type != blink::WebNavigationTypeReload &&
- type != blink::WebNavigationTypeBackForward && !is_form_post) {
- // The opener relationship between the new window and the parent allows the
- // new window to script the parent and vice versa. This is not allowed if
- // the origins of the two domains are different. This can be treated as a
- // top level navigation and routed back to the host.
- blink::WebFrame* opener = frame->opener();
- if (!opener)
- return true;
-
- if (url.GetOrigin() != GURL(opener->document().url()).GetOrigin())
- return true;
- }
- return false;
-}
-
// static
void RenderViewImpl::NotifyTimezoneChange(blink::WebFrame* frame) {
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
@@ -426,7 +388,8 @@ void RenderViewImpl::NotifyTimezoneChange(blink::WebFrame* frame) {
NotifyTimezoneChange(child);
}
-static WindowOpenDisposition NavigationPolicyToDisposition(
+// static
+WindowOpenDisposition RenderViewImpl::NavigationPolicyToDisposition(
WebNavigationPolicy policy) {
switch (policy) {
case blink::WebNavigationPolicyIgnore:
@@ -1630,47 +1593,6 @@ void RenderViewImpl::SendUpdateState(const WebHistoryItem& item) {
routing_id_, page_id_, HistoryItemToPageState(item)));
}
-void RenderViewImpl::OpenURL(WebFrame* frame,
- const GURL& url,
- const Referrer& referrer,
- WebNavigationPolicy policy) {
- ViewHostMsg_OpenURL_Params params;
- params.url = url;
- params.referrer = referrer;
- params.disposition = NavigationPolicyToDisposition(policy);
- params.frame_id = RenderFrameImpl::FromWebFrame(frame)->GetRoutingID();
- WebDataSource* ds = frame->provisionalDataSource();
- if (ds) {
- DocumentState* document_state = DocumentState::FromDataSource(ds);
- NavigationState* navigation_state = document_state->navigation_state();
- if (navigation_state->is_content_initiated()) {
- params.should_replace_current_entry = ds->replacesCurrentHistoryItem();
- } else {
- // This is necessary to preserve the should_replace_current_entry value on
- // cross-process redirects, in the event it was set by a previous process.
- //
- // TODO(davidben): Avoid this awkward duplication of state. See comment on
- // NavigationState::should_replace_current_entry().
- params.should_replace_current_entry =
- navigation_state->should_replace_current_entry();
- }
- } else {
- params.should_replace_current_entry = false;
- }
- params.user_gesture = WebUserGestureIndicator::isProcessingUserGesture();
- if (GetContentClient()->renderer()->AllowPopup())
- params.user_gesture = true;
-
- if (policy == blink::WebNavigationPolicyNewBackgroundTab ||
- policy == blink::WebNavigationPolicyNewForegroundTab ||
- policy == blink::WebNavigationPolicyNewWindow ||
- policy == blink::WebNavigationPolicyNewPopup) {
- WebUserGestureIndicator::consumeUserGesture();
- }
-
- Send(new ViewHostMsg_OpenURL(routing_id_, params));
-}
-
// WebViewDelegate ------------------------------------------------------------
void RenderViewImpl::LoadNavigationErrorPage(
@@ -2587,217 +2509,6 @@ const std::string& RenderViewImpl::GetAcceptLanguages() const {
return renderer_preferences_.accept_languages;
}
-WebNavigationPolicy RenderViewImpl::DecidePolicyForNavigation(
- RenderFrame* render_frame, WebFrame* frame,
- WebDataSource::ExtraData* extraData, const WebURLRequest& request,
- WebNavigationType type, WebNavigationPolicy default_policy,
- bool is_redirect) {
-#ifdef OS_ANDROID
- // The handlenavigation API is deprecated and will be removed once
- // crbug.com/325351 is resolved.
- if (request.url() != GURL(kSwappedOutURL) &&
- GetContentClient()->renderer()->HandleNavigation(
- render_frame,
- static_cast<DocumentState*>(extraData),
- opener_id_,
- frame,
- request,
- type,
- default_policy,
- is_redirect)) {
- return blink::WebNavigationPolicyIgnore;
- }
-#endif
-
- Referrer referrer(GetReferrerFromRequest(frame, request));
-
- if (is_swapped_out_) {
- if (request.url() != GURL(kSwappedOutURL)) {
- // Targeted links may try to navigate a swapped out frame. Allow the
- // browser process to navigate the tab instead. Note that it is also
- // possible for non-targeted navigations (from this view) to arrive
- // here just after we are swapped out. It's ok to send them to the
- // browser, as long as they're for the top level frame.
- // TODO(creis): Ensure this supports targeted form submissions when
- // fixing http://crbug.com/101395.
- if (frame->parent() == NULL) {
- OpenURL(frame, request.url(), referrer, default_policy);
- return blink::WebNavigationPolicyIgnore; // Suppress the load here.
- }
-
- // We should otherwise ignore in-process iframe navigations, if they
- // arrive just after we are swapped out.
- return blink::WebNavigationPolicyIgnore;
- }
-
- // Allow kSwappedOutURL to complete.
- return default_policy;
- }
-
- // Webkit is asking whether to navigate to a new URL.
- // This is fine normally, except if we're showing UI from one security
- // context and they're trying to navigate to a different context.
- const GURL& url = request.url();
-
- // A content initiated navigation may have originated from a link-click,
- // script, drag-n-drop operation, etc.
- bool is_content_initiated = static_cast<DocumentState*>(extraData)->
- navigation_state()->is_content_initiated();
-
- // Experimental:
- // If --enable-strict-site-isolation or --site-per-process is enabled, send
- // all top-level navigations to the browser to let it swap processes when
- // crossing site boundaries. This is currently expected to break some script
- // calls and navigations, such as form submissions.
- const CommandLine& command_line = *CommandLine::ForCurrentProcess();
- bool force_swap_due_to_flag =
- command_line.HasSwitch(switches::kEnableStrictSiteIsolation) ||
- command_line.HasSwitch(switches::kSitePerProcess);
- if (force_swap_due_to_flag &&
- !frame->parent() && (is_content_initiated || is_redirect)) {
- WebString origin_str = frame->document().securityOrigin().toString();
- GURL frame_url(origin_str.utf8().data());
- // TODO(cevans): revisit whether this site check is still necessary once
- // crbug.com/101395 is fixed.
- bool same_domain_or_host =
- net::registry_controlled_domains::SameDomainOrHost(
- frame_url,
- url,
- net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
- if (!same_domain_or_host || frame_url.scheme() != url.scheme()) {
- OpenURL(frame, url, referrer, default_policy);
- return blink::WebNavigationPolicyIgnore;
- }
- }
-
- // If the browser is interested, then give it a chance to look at the request.
- if (is_content_initiated) {
- bool is_form_post = ((type == blink::WebNavigationTypeFormSubmitted) ||
- (type == blink::WebNavigationTypeFormResubmitted)) &&
- EqualsASCII(request.httpMethod(), "POST");
- bool browser_handles_request =
- renderer_preferences_.browser_handles_non_local_top_level_requests &&
- IsNonLocalTopLevelNavigation(url, frame, type, is_form_post);
- if (!browser_handles_request) {
- browser_handles_request = IsTopLevelNavigation(frame) &&
- renderer_preferences_.browser_handles_all_top_level_requests;
- }
-
- if (browser_handles_request) {
- // Reset these counters as the RenderView could be reused for the next
- // navigation.
- page_id_ = -1;
- last_page_id_sent_to_browser_ = -1;
- OpenURL(frame, url, referrer, default_policy);
- return blink::WebNavigationPolicyIgnore; // Suppress the load here.
- }
- }
-
- // Use the frame's original request's URL rather than the document's URL for
- // subsequent checks. For a popup, the document's URL may become the opener
- // window's URL if the opener has called document.write().
- // See http://crbug.com/93517.
- GURL old_url(frame->dataSource()->request().url());
-
- // Detect when we're crossing a permission-based boundary (e.g. into or out of
- // an extension or app origin, leaving a WebUI page, etc). We only care about
- // top-level navigations (not iframes). But we sometimes navigate to
- // about:blank to clear a tab, and we want to still allow that.
- //
- // Note: this is known to break POST submissions when crossing process
- // boundaries until http://crbug.com/101395 is fixed. This is better for
- // security than loading a WebUI, extension or app page in the wrong process.
- // POST requests don't work because this mechanism does not preserve form
- // POST data. We will need to send the request's httpBody data up to the
- // browser process, and issue a special POST navigation in WebKit (via
- // FrameLoader::loadFrameRequest). See ResourceDispatcher and WebURLLoaderImpl
- // for examples of how to send the httpBody data.
- if (!frame->parent() && is_content_initiated &&
- !url.SchemeIs(chrome::kAboutScheme)) {
- bool send_referrer = false;
-
- // All navigations to or from WebUI URLs or within WebUI-enabled
- // RenderProcesses must be handled by the browser process so that the
- // correct bindings and data sources can be registered.
- // Similarly, navigations to view-source URLs or within ViewSource mode
- // must be handled by the browser process (except for reloads - those are
- // safe to leave within the renderer).
- // Lastly, access to file:// URLs from non-file:// URL pages must be
- // handled by the browser so that ordinary renderer processes don't get
- // blessed with file permissions.
- int cumulative_bindings = RenderProcess::current()->GetEnabledBindings();
- bool is_initial_navigation = page_id_ == -1;
- bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
- (cumulative_bindings & BINDINGS_POLICY_WEB_UI) ||
- url.SchemeIs(kViewSourceScheme) ||
- (frame->isViewSourceModeEnabled() &&
- type != blink::WebNavigationTypeReload);
-
- if (!should_fork && url.SchemeIs(kFileScheme)) {
- // Fork non-file to file opens. Check the opener URL if this is the
- // initial navigation in a newly opened window.
- GURL source_url(old_url);
- if (is_initial_navigation && source_url.is_empty() && frame->opener())
- source_url = frame->opener()->top()->document().url();
- DCHECK(!source_url.is_empty());
- should_fork = !source_url.SchemeIs(kFileScheme);
- }
-
- if (!should_fork) {
- // Give the embedder a chance.
- should_fork = GetContentClient()->renderer()->ShouldFork(
- frame, url, request.httpMethod().utf8(), is_initial_navigation,
- is_redirect, &send_referrer);
- }
-
- if (should_fork) {
- OpenURL(
- frame, url, send_referrer ? referrer : Referrer(), default_policy);
- return blink::WebNavigationPolicyIgnore; // Suppress the load here.
- }
- }
-
- // Detect when a page is "forking" a new tab that can be safely rendered in
- // its own process. This is done by sites like Gmail that try to open links
- // in new windows without script connections back to the original page. We
- // treat such cases as browser navigations (in which we will create a new
- // renderer for a cross-site navigation), rather than WebKit navigations.
- //
- // We use the following heuristic to decide whether to fork a new page in its
- // own process:
- // The parent page must open a new tab to about:blank, set the new tab's
- // window.opener to null, and then redirect the tab to a cross-site URL using
- // JavaScript.
- //
- // TODO(creis): Deprecate this logic once we can rely on rel=noreferrer
- // (see below).
- bool is_fork =
- // Must start from a tab showing about:blank, which is later redirected.
- old_url == GURL(kAboutBlankURL) &&
- // Must be the first real navigation of the tab.
- historyBackListCount() < 1 &&
- historyForwardListCount() < 1 &&
- // The parent page must have set the child's window.opener to null before
- // redirecting to the desired URL.
- frame->opener() == NULL &&
- // Must be a top-level frame.
- frame->parent() == NULL &&
- // Must not have issued the request from this page.
- is_content_initiated &&
- // Must be targeted at the current tab.
- default_policy == blink::WebNavigationPolicyCurrentTab &&
- // Must be a JavaScript navigation, which appears as "other".
- type == blink::WebNavigationTypeOther;
-
- if (is_fork) {
- // Open the URL via the browser, not via WebKit.
- OpenURL(frame, url, Referrer(), default_policy);
- return blink::WebNavigationPolicyIgnore;
- }
-
- return default_policy;
-}
-
void RenderViewImpl::willSendSubmitEvent(blink::WebFrame* frame,
const blink::WebFormElement& form) {
FOR_EACH_OBSERVER(
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h
index 2df9c78..808dc0d 100644
--- a/content/renderer/render_view_impl.h
+++ b/content/renderer/render_view_impl.h
@@ -57,6 +57,7 @@
#include "third_party/WebKit/public/web/WebPageVisibilityState.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
#include "third_party/WebKit/public/web/WebViewClient.h"
+#include "ui/base/window_open_disposition.h"
#include "ui/surface/transport_dib.h"
#include "webkit/common/webpreferences.h"
@@ -332,17 +333,6 @@ class CONTENT_EXPORT RenderViewImpl
blink::WebFrame* frame,
const blink::WebURL& url,
blink::WebMediaPlayerClient* client);
- // Temporary call until this code moves to RenderFrame.
- // virtual since overriden by WebTestProxy for layout tests.
- virtual blink::WebNavigationPolicy DecidePolicyForNavigation(
- RenderFrame* render_frame,
- blink::WebFrame* frame,
- blink::WebDataSource::ExtraData* extraData,
- const blink::WebURLRequest& request,
- blink::WebNavigationType type,
- blink::WebNavigationPolicy default_policy,
- bool is_redirect);
-
// Returns the length of the session history of this RenderView. Note that
// this only coincides with the actual length of the session history if this
// RenderView is the currently active RenderView of a WebContents.
@@ -810,6 +800,9 @@ class CONTENT_EXPORT RenderViewImpl
static void NotifyTimezoneChange(blink::WebFrame* frame);
+ static WindowOpenDisposition NavigationPolicyToDisposition(
+ blink::WebNavigationPolicy policy);
+
void UpdateTitle(blink::WebFrame* frame, const base::string16& title,
blink::WebTextDirection title_direction);
void UpdateSessionHistory(blink::WebFrame* frame);
@@ -831,11 +824,6 @@ class CONTENT_EXPORT RenderViewImpl
void UpdateEncoding(blink::WebFrame* frame,
const std::string& encoding_name);
- void OpenURL(blink::WebFrame* frame,
- const GURL& url,
- const Referrer& referrer,
- blink::WebNavigationPolicy policy);
-
bool RunJavaScriptMessage(JavaScriptMessageType type,
const base::string16& message,
const base::string16& default_value,
diff --git a/content/shell/renderer/test_runner/WebFrameTestProxy.h b/content/shell/renderer/test_runner/WebFrameTestProxy.h
index 3d81f2c..238712b 100644
--- a/content/shell/renderer/test_runner/WebFrameTestProxy.h
+++ b/content/shell/renderer/test_runner/WebFrameTestProxy.h
@@ -144,6 +144,10 @@ public:
}
virtual blink::WebNavigationPolicy decidePolicyForNavigation(blink::WebFrame* frame, blink::WebDataSource::ExtraData* extraData, const blink::WebURLRequest& request, blink::WebNavigationType type, blink::WebNavigationPolicy defaultPolicy, bool isRedirect)
{
+ blink::WebNavigationPolicy policy = m_baseProxy->decidePolicyForNavigation(frame, extraData, request, type, defaultPolicy, isRedirect);
+ if (policy == blink::WebNavigationPolicyIgnore)
+ return policy;
+
return Base::decidePolicyForNavigation(frame, extraData, request, type, defaultPolicy, isRedirect);
}
virtual bool willCheckAndDispatchMessageEvent(blink::WebFrame* sourceFrame, blink::WebFrame* targetFrame, blink::WebSecurityOrigin target, blink::WebDOMMessageEvent event)
diff --git a/content/shell/renderer/test_runner/WebTestProxy.h b/content/shell/renderer/test_runner/WebTestProxy.h
index 1cf3ba6..0aa4f7f 100644
--- a/content/shell/renderer/test_runner/WebTestProxy.h
+++ b/content/shell/renderer/test_runner/WebTestProxy.h
@@ -477,13 +477,6 @@ public:
{
return WebTestProxyBase::runModalBeforeUnloadDialog(frame, message);
}
- virtual blink::WebNavigationPolicy DecidePolicyForNavigation(content::RenderFrame* render_frame, blink::WebFrame* frame, blink::WebDataSource::ExtraData* extraData, const blink::WebURLRequest& request, blink::WebNavigationType type, blink::WebNavigationPolicy defaultPolicy, bool isRedirect)
- {
- blink::WebNavigationPolicy policy = WebTestProxyBase::decidePolicyForNavigation(frame, extraData, request, type, defaultPolicy, isRedirect);
- if (policy == blink::WebNavigationPolicyIgnore)
- return policy;
- return Base::DecidePolicyForNavigation(render_frame, frame, extraData, request, type, defaultPolicy, isRedirect);
- }
virtual bool willCheckAndDispatchMessageEvent(blink::WebFrame* sourceFrame, blink::WebFrame* targetFrame, blink::WebSecurityOrigin target, blink::WebDOMMessageEvent event)
{
if (WebTestProxyBase::willCheckAndDispatchMessageEvent(sourceFrame, targetFrame, target, event))