Index: chrome/renderer/render_view.cc |
=================================================================== |
--- chrome/renderer/render_view.cc (revision 29478) |
+++ chrome/renderer/render_view.cc (working copy) |
@@ -216,6 +216,7 @@ |
last_page_id_sent_to_browser_(-1), |
last_indexed_page_id_(-1), |
opened_by_user_gesture_(true), |
+ opener_suppressed_(false), |
ALLOW_THIS_IN_INITIALIZER_LIST(method_factory_(this)), |
devtools_agent_(NULL), |
devtools_client_(NULL), |
@@ -1293,6 +1294,7 @@ |
int32 routing_id = MSG_ROUTING_NONE; |
bool user_gesture = creator->isProcessingUserGesture(); |
+ bool opener_suppressed = creator->willSuppressOpenerInNewFrame(); |
render_thread_->Send( |
new ViewHostMsg_CreateWindow(routing_id_, user_gesture, &routing_id)); |
@@ -1308,6 +1310,9 @@ |
routing_id); |
view->opened_by_user_gesture_ = user_gesture; |
+ // Record whether the creator frame is trying to suppress the opener field. |
+ view->opener_suppressed_ = opener_suppressed; |
+ |
// Record the security origin of the creator. |
GURL creator_url(creator->securityOrigin().toString().utf8()); |
if (!creator_url.is_valid() || !creator_url.IsStandard()) |
@@ -1887,6 +1892,9 @@ |
// 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. |
GURL(frame->url()) == GURL(chrome::kAboutBlankURL) && |
@@ -1904,7 +1912,34 @@ |
default_policy == WebKit::WebNavigationPolicyCurrentTab && |
// Must be a JavaScript navigation, which appears as "other". |
type == WebKit::WebNavigationTypeOther; |
- if (is_fork) { |
+ |
+ // Recognize if this navigation is from a link with rel=noreferrer and |
+ // target=_blank attributes, in which case the opener will be suppressed. If |
+ // so, it is safe to load cross-site pages in a separate process, so we |
+ // should let the browser handle it. |
+ bool is_noreferrer_and_blank_target = |
+ // Frame should be top level and not yet navigated. |
+ frame->parent() == NULL && |
+ frame->url().isEmpty() && |
+ historyBackListCount() < 1 && |
+ historyForwardListCount() < 1 && |
+ // Links with rel=noreferrer will have no Referer field, and their |
+ // resulting frame will have its window.opener suppressed. |
+ // TODO(creis): should add a request.httpReferrer() method to help avoid |
+ // typos on the unusual spelling of Referer. |
+ request.httpHeaderField(WebString::fromUTF8("Referer")).isNull() && |
+ opener_suppressed_ && |
+ frame->opener() == NULL && |
+ // Links with target=_blank will have no name. |
+ frame->name().isNull() && |
+ // Another frame (with a non-empty creator) should have initiated the |
+ // request, targeted at this frame. |
+ !creator_url_.is_empty() && |
+ is_content_initiated && |
+ default_policy == WebKit::WebNavigationPolicyCurrentTab && |
+ type == WebKit::WebNavigationTypeOther; |
+ |
+ if (is_fork || is_noreferrer_and_blank_target) { |
// Open the URL via the browser, not via WebKit. |
OpenURL(url, GURL(), default_policy); |
return WebKit::WebNavigationPolicyIgnore; |