| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/loader/cross_site_resource_handler.h" | 5 #include "content/browser/loader/cross_site_resource_handler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 79 params.global_request_id, cross_site_transferring_request.Pass(), | 79 params.global_request_id, cross_site_transferring_request.Pass(), |
| 80 params.transfer_url_chain, params.referrer, | 80 params.transfer_url_chain, params.referrer, |
| 81 params.page_transition, params.should_replace_current_entry); | 81 params.page_transition, params.should_replace_current_entry); |
| 82 } else if (leak_requests_for_testing_ && cross_site_transferring_request) { | 82 } else if (leak_requests_for_testing_ && cross_site_transferring_request) { |
| 83 // Some unit tests expect requests to be leaked in this case, so they can | 83 // Some unit tests expect requests to be leaked in this case, so they can |
| 84 // pass them along manually. | 84 // pass them along manually. |
| 85 cross_site_transferring_request->ReleaseRequest(); | 85 cross_site_transferring_request->ReleaseRequest(); |
| 86 } | 86 } |
| 87 } | 87 } |
| 88 | 88 |
| 89 // Returns whether a transfer is needed by doing a check on the UI thread. | 89 // Determines whether a navigation to |dest_url| may be completed using an |
| 90 bool CheckNavigationPolicyOnUI(GURL real_url, | 90 // existing RenderFrameHost, or whether transferring to a new RenderFrameHost |
| 91 int process_id, | 91 // backed by a different render process is required. This is a security policy |
| 92 int render_frame_id) { | 92 // check determined by the current site isolation mode, and must be done |
| 93 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible()); | 93 // before the resource at |dest_url| is delivered to |rfh|. |
| 94 RenderFrameHostImpl* rfh = | 94 // |
| 95 RenderFrameHostImpl::FromID(process_id, render_frame_id); | 95 // When this function returns true for a subframe, an out-of-process iframe |
| 96 if (!rfh) | 96 // must be created. |
| 97 return false; | 97 // |
| 98 | 98 // TODO(nick): Move this function to RFHM. |
| 99 bool IsRendererTransferNeededForNavigation(RenderFrameHostImpl* rfh, |
| 100 const GURL& dest_url) { |
| 99 // A transfer is not needed if the current SiteInstance doesn't yet have a | 101 // A transfer is not needed if the current SiteInstance doesn't yet have a |
| 100 // site. This is the case for tests that use NavigateToURL. | 102 // site. This is the case for tests that use NavigateToURL. |
| 101 if (!rfh->GetSiteInstance()->HasSite()) | 103 if (!rfh->GetSiteInstance()->HasSite()) |
| 102 return false; | 104 return false; |
| 103 | 105 |
| 104 // For now, GuestViews never transfer on cross-site navigations. | 106 // For now, GuestViews never transfer on cross-site navigations. |
| 105 WebContentsImpl* web_contents = | 107 WebContentsImpl* web_contents = |
| 106 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(rfh)); | 108 static_cast<WebContentsImpl*>(WebContents::FromRenderFrameHost(rfh)); |
| 107 if (web_contents->GetBrowserPluginGuest()) | 109 if (web_contents->GetBrowserPluginGuest()) |
| 108 return false; | 110 return false; |
| 109 | 111 |
| 110 GURL effective_url = SiteInstanceImpl::GetEffectiveURL( | 112 GURL effective_url = SiteInstanceImpl::GetEffectiveURL( |
| 111 rfh->GetSiteInstance()->GetBrowserContext(), real_url); | 113 rfh->GetSiteInstance()->GetBrowserContext(), dest_url); |
| 112 | 114 |
| 113 // TODO(nasko, nick): These following --site-per-process checks are | 115 // TODO(nasko, nick): These following --site-per-process checks are |
| 114 // overly simplistic. Update them to match all the cases | 116 // overly simplistic. Update them to match all the cases |
| 115 // considered by RenderFrameHostManager::DetermineSiteInstanceForURL. | 117 // considered by RenderFrameHostManager::DetermineSiteInstanceForURL. |
| 116 if (SiteInstance::IsSameWebSite(rfh->GetSiteInstance()->GetBrowserContext(), | 118 if (SiteInstance::IsSameWebSite(rfh->GetSiteInstance()->GetBrowserContext(), |
| 117 rfh->GetSiteInstance()->GetSiteURL(), | 119 rfh->GetSiteInstance()->GetSiteURL(), |
| 118 real_url)) { | 120 dest_url)) { |
| 119 return false; // The same site, no transition needed. | 121 return false; // The same site, no transition needed. |
| 120 } | 122 } |
| 121 | 123 |
| 122 // The sites differ. If either one requires a dedicated process, | 124 // The sites differ. If either one requires a dedicated process, |
| 123 // then a transfer is needed. | 125 // then a transfer is needed. |
| 124 return rfh->GetSiteInstance()->RequiresDedicatedProcess() || | 126 return rfh->GetSiteInstance()->RequiresDedicatedProcess() || |
| 125 SiteIsolationPolicy::DoesSiteRequireDedicatedProcess(effective_url); | 127 SiteIsolationPolicy::DoesSiteRequireDedicatedProcess(effective_url); |
| 126 } | 128 } |
| 127 | 129 |
| 130 // Returns whether a transfer is needed by doing a check on the UI thread. |
| 131 CrossSiteResourceHandler::NavigationDecision |
| 132 CheckNavigationPolicyOnUI(GURL real_url, int process_id, int render_frame_id) { |
| 133 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible()); |
| 134 RenderFrameHostImpl* rfh = |
| 135 RenderFrameHostImpl::FromID(process_id, render_frame_id); |
| 136 |
| 137 // Without a valid RFH against which to check, we must cancel the request, |
| 138 // to prevent the resource at |url| from being delivered to a potentially |
| 139 // unsuitable renderer process. |
| 140 if (!rfh) |
| 141 return CrossSiteResourceHandler::NavigationDecision::CANCEL_REQUEST; |
| 142 |
| 143 if (IsRendererTransferNeededForNavigation(rfh, real_url)) |
| 144 return CrossSiteResourceHandler::NavigationDecision::TRANSFER_REQUIRED; |
| 145 else |
| 146 return CrossSiteResourceHandler::NavigationDecision::USE_EXISTING_RENDERER; |
| 147 } |
| 148 |
| 128 } // namespace | 149 } // namespace |
| 129 | 150 |
| 130 CrossSiteResourceHandler::CrossSiteResourceHandler( | 151 CrossSiteResourceHandler::CrossSiteResourceHandler( |
| 131 scoped_ptr<ResourceHandler> next_handler, | 152 scoped_ptr<ResourceHandler> next_handler, |
| 132 net::URLRequest* request) | 153 net::URLRequest* request) |
| 133 : LayeredResourceHandler(request, next_handler.Pass()), | 154 : LayeredResourceHandler(request, next_handler.Pass()), |
| 134 has_started_response_(false), | 155 has_started_response_(false), |
| 135 in_cross_site_transition_(false), | 156 in_cross_site_transition_(false), |
| 136 completed_during_transition_(false), | 157 completed_during_transition_(false), |
| 137 did_defer_(false), | 158 did_defer_(false), |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 if (SiteIsolationPolicy::AreCrossProcessFramesPossible() && | 250 if (SiteIsolationPolicy::AreCrossProcessFramesPossible() && |
| 230 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | 251 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( |
| 231 info->GetChildID())) { | 252 info->GetChildID())) { |
| 232 return DeferForNavigationPolicyCheck(info, response, defer); | 253 return DeferForNavigationPolicyCheck(info, response, defer); |
| 233 } | 254 } |
| 234 | 255 |
| 235 // No deferral needed. Pass the response through. | 256 // No deferral needed. Pass the response through. |
| 236 return next_handler_->OnResponseStarted(response, defer); | 257 return next_handler_->OnResponseStarted(response, defer); |
| 237 } | 258 } |
| 238 | 259 |
| 239 void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) { | 260 void CrossSiteResourceHandler::ResumeOrTransfer(NavigationDecision decision) { |
| 240 if (is_transfer) { | 261 switch (decision) { |
| 241 StartCrossSiteTransition(response_.get()); | 262 case NavigationDecision::CANCEL_REQUEST: |
| 242 } else { | 263 // TODO(nick): What kind of cleanup do we need here? |
| 243 ResumeResponse(); | 264 controller()->Cancel(); |
| 265 break; |
| 266 case NavigationDecision::USE_EXISTING_RENDERER: |
| 267 ResumeResponse(); |
| 268 break; |
| 269 case NavigationDecision::TRANSFER_REQUIRED: |
| 270 StartCrossSiteTransition(response_.get()); |
| 271 break; |
| 244 } | 272 } |
| 245 } | 273 } |
| 246 | 274 |
| 247 bool CrossSiteResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { | 275 bool CrossSiteResourceHandler::OnReadCompleted(int bytes_read, bool* defer) { |
| 248 CHECK(!in_cross_site_transition_); | 276 CHECK(!in_cross_site_transition_); |
| 249 return next_handler_->OnReadCompleted(bytes_read, defer); | 277 return next_handler_->OnReadCompleted(bytes_read, defer); |
| 250 } | 278 } |
| 251 | 279 |
| 252 void CrossSiteResourceHandler::OnResponseCompleted( | 280 void CrossSiteResourceHandler::OnResponseCompleted( |
| 253 const net::URLRequestStatus& status, | 281 const net::URLRequestStatus& status, |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 393 controller()->Resume(); | 421 controller()->Resume(); |
| 394 } | 422 } |
| 395 } | 423 } |
| 396 | 424 |
| 397 void CrossSiteResourceHandler::OnDidDefer() { | 425 void CrossSiteResourceHandler::OnDidDefer() { |
| 398 did_defer_ = true; | 426 did_defer_ = true; |
| 399 request()->LogBlockedBy("CrossSiteResourceHandler"); | 427 request()->LogBlockedBy("CrossSiteResourceHandler"); |
| 400 } | 428 } |
| 401 | 429 |
| 402 } // namespace content | 430 } // namespace content |
| OLD | NEW |