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 |