| Index: content/browser/loader/cross_site_resource_handler.cc
|
| diff --git a/content/browser/loader/cross_site_resource_handler.cc b/content/browser/loader/cross_site_resource_handler.cc
|
| index 8e563972111dd87236eea15ad0814ff0c6d5ddb5..bf3f0bd8611826ad1084993d7c5306ec8f5a4ec3 100644
|
| --- a/content/browser/loader/cross_site_resource_handler.cc
|
| +++ b/content/browser/loader/cross_site_resource_handler.cc
|
| @@ -84,6 +84,20 @@ void OnCrossSiteResponseHelper(const CrossSiteResponseParams& params) {
|
| }
|
| }
|
|
|
| +bool CheckNavigationPolicyOnUI(GURL url, int process_id, int render_frame_id) {
|
| + RenderFrameHostImpl* rfh =
|
| + RenderFrameHostImpl::FromID(process_id, render_frame_id);
|
| + if (!rfh)
|
| + return false;
|
| +
|
| + // TODO(nasko): This check is very simplistic and is used temporarily only
|
| + // for --site-per-process. It should be updated to match the check performed
|
| + // by RenderFrameHostManager::UpdateRendererStateForNavigate.
|
| + return !SiteInstance::IsSameWebSite(
|
| + rfh->GetSiteInstance()->GetBrowserContext(),
|
| + rfh->GetSiteInstance()->GetSiteURL(), url);
|
| +}
|
| +
|
| } // namespace
|
|
|
| CrossSiteResourceHandler::CrossSiteResourceHandler(
|
| @@ -93,7 +107,8 @@ CrossSiteResourceHandler::CrossSiteResourceHandler(
|
| has_started_response_(false),
|
| in_cross_site_transition_(false),
|
| completed_during_transition_(false),
|
| - did_defer_(false) {
|
| + did_defer_(false),
|
| + weak_ptr_factory_(this) {
|
| }
|
|
|
| CrossSiteResourceHandler::~CrossSiteResourceHandler() {
|
| @@ -134,24 +149,14 @@ bool CrossSiteResourceHandler::OnResponseStarted(
|
| info->GetContext(), request()->original_url(), request()->url());
|
|
|
| // When the --site-per-process flag is passed, we transfer processes for
|
| - // cross-site subframe navigations.
|
| - if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) {
|
| - GURL referrer(request()->referrer());
|
| - // We skip this for WebUI processes for now, since pages like the NTP host
|
| - // cross-site WebUI iframes but don't have referrers.
|
| - bool is_webui_process = ChildProcessSecurityPolicyImpl::GetInstance()->
|
| - HasWebUIBindings(info->GetChildID());
|
| -
|
| - // TODO(creis): This shouldn't rely on the referrer to determine the parent
|
| - // frame's URL. This also doesn't work for hosted apps, due to passing NULL
|
| - // to IsSameWebSite. It should be possible to always send the navigation to
|
| - // the UI thread to make a policy decision, which could let us eliminate the
|
| - // renderer-side check in RenderViewImpl::decidePolicyForNavigation as well.
|
| - if (info->GetResourceType() == ResourceType::SUB_FRAME &&
|
| - !is_webui_process &&
|
| - !SiteInstance::IsSameWebSite(NULL, request()->url(), referrer)) {
|
| - should_transfer = true;
|
| - }
|
| + // cross-site navigations. This is skipped if a transfer is already required
|
| + // or for WebUI processes for now, since pages like the NTP host multiple
|
| + // cross-site WebUI iframes.
|
| + if (!should_transfer &&
|
| + CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
|
| + !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
|
| + info->GetChildID())) {
|
| + return DeferForNavigationPolicyCheck(info, response, defer);
|
| }
|
|
|
| bool swap_needed = should_transfer ||
|
| @@ -190,6 +195,15 @@ bool CrossSiteResourceHandler::OnResponseStarted(
|
| return true;
|
| }
|
|
|
| +void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) {
|
| + if (is_transfer) {
|
| + ResourceRequestInfoImpl* info = GetRequestInfo();
|
| + StartCrossSiteTransition(info->GetRequestID(), response_, is_transfer);
|
| + } else {
|
| + ResumeResponse();
|
| + }
|
| +}
|
| +
|
| bool CrossSiteResourceHandler::OnReadCompleted(int request_id,
|
| int bytes_read,
|
| bool* defer) {
|
| @@ -238,7 +252,6 @@ void CrossSiteResourceHandler::OnResponseCompleted(
|
| // WebContentsImpl to swap in the new renderer and destroy the old one.
|
| void CrossSiteResourceHandler::ResumeResponse() {
|
| DCHECK(request());
|
| - DCHECK(in_cross_site_transition_);
|
| in_cross_site_transition_ = false;
|
| ResourceRequestInfoImpl* info = GetRequestInfo();
|
|
|
| @@ -326,6 +339,38 @@ void CrossSiteResourceHandler::StartCrossSiteTransition(
|
| info->should_replace_current_entry())));
|
| }
|
|
|
| +bool CrossSiteResourceHandler::DeferForNavigationPolicyCheck(
|
| + ResourceRequestInfoImpl* info,
|
| + ResourceResponse* response,
|
| + bool* defer) {
|
| + // Store the response_ object internally, since the navigation is deferred
|
| + // regardless of whether it will be a transfer or not.
|
| + response_ = response;
|
| +
|
| + // Always defer the navigation to the UI thread to make a policy decision.
|
| + // It will send the result back to the IO thread to either resume or
|
| + // transfer it to a new renderer.
|
| + // TODO(nasko): If the UI thread result is that transfer is required, the
|
| + // IO thread will defer to the UI thread again through
|
| + // StartCrossSiteTransition. This is unnecessary and the policy check on the
|
| + // UI thread should be refactored to avoid the extra hop.
|
| + BrowserThread::PostTaskAndReplyWithResult(
|
| + BrowserThread::UI,
|
| + FROM_HERE,
|
| + base::Bind(&CheckNavigationPolicyOnUI,
|
| + request()->url(),
|
| + info->GetChildID(),
|
| + info->GetRenderFrameID()),
|
| + base::Bind(&CrossSiteResourceHandler::ResumeOrTransfer,
|
| + weak_ptr_factory_.GetWeakPtr()));
|
| +
|
| + // Defer loading until it is known whether the navigation will transfer
|
| + // to a new process or continue in the existing one.
|
| + *defer = true;
|
| + OnDidDefer();
|
| + return true;
|
| +}
|
| +
|
| void CrossSiteResourceHandler::ResumeIfDeferred() {
|
| if (did_defer_) {
|
| request()->LogUnblocked();
|
|
|