Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(240)

Side by Side Diff: content/browser/loader/cross_site_resource_handler.cc

Issue 1208143002: Move existing kSitePerProcess checks to a policy-oracle object (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@swapped_out_cmdline_checks
Patch Set: Partial fixes to Nasko's comments. Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "content/browser/appcache/appcache_interceptor.h" 12 #include "content/browser/appcache/appcache_interceptor.h"
13 #include "content/browser/child_process_security_policy_impl.h" 13 #include "content/browser/child_process_security_policy_impl.h"
14 #include "content/browser/frame_host/cross_site_transferring_request.h" 14 #include "content/browser/frame_host/cross_site_transferring_request.h"
15 #include "content/browser/frame_host/render_frame_host_impl.h" 15 #include "content/browser/frame_host/render_frame_host_impl.h"
16 #include "content/browser/loader/resource_dispatcher_host_impl.h" 16 #include "content/browser/loader/resource_dispatcher_host_impl.h"
17 #include "content/browser/loader/resource_request_info_impl.h" 17 #include "content/browser/loader/resource_request_info_impl.h"
18 #include "content/browser/site_instance_impl.h" 18 #include "content/browser/site_instance_impl.h"
19 #include "content/public/browser/browser_thread.h" 19 #include "content/public/browser/browser_thread.h"
20 #include "content/public/browser/content_browser_client.h" 20 #include "content/public/browser/content_browser_client.h"
21 #include "content/public/browser/global_request_id.h" 21 #include "content/public/browser/global_request_id.h"
22 #include "content/public/browser/resource_controller.h" 22 #include "content/public/browser/resource_controller.h"
23 #include "content/public/browser/site_instance.h" 23 #include "content/public/browser/site_instance.h"
24 #include "content/public/common/content_switches.h" 24 #include "content/public/common/content_switches.h"
25 #include "content/public/common/resource_response.h" 25 #include "content/public/common/resource_response.h"
26 #include "content/public/common/site_isolation_policy.h"
26 #include "content/public/common/url_constants.h" 27 #include "content/public/common/url_constants.h"
27 #include "net/http/http_response_headers.h" 28 #include "net/http/http_response_headers.h"
28 #include "net/url_request/url_request.h" 29 #include "net/url_request/url_request.h"
29 30
30 namespace content { 31 namespace content {
31 32
32 namespace { 33 namespace {
33 34
34 bool leak_requests_for_testing_ = false; 35 bool leak_requests_for_testing_ = false;
35 36
(...skipping 28 matching lines...) Expand all
64 new CrossSiteTransferringRequest(params.global_request_id)); 65 new CrossSiteTransferringRequest(params.global_request_id));
65 66
66 RenderFrameHostImpl* rfh = 67 RenderFrameHostImpl* rfh =
67 RenderFrameHostImpl::FromID(params.global_request_id.child_id, 68 RenderFrameHostImpl::FromID(params.global_request_id.child_id,
68 params.render_frame_id); 69 params.render_frame_id);
69 if (rfh) { 70 if (rfh) {
70 if (rfh->GetParent()) { 71 if (rfh->GetParent()) {
71 // We should only swap processes for subframes in --site-per-process mode. 72 // We should only swap processes for subframes in --site-per-process mode.
72 // CrossSiteResourceHandler is not installed on subframe requests in 73 // CrossSiteResourceHandler is not installed on subframe requests in
73 // default Chrome. 74 // default Chrome.
74 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 75 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
75 switches::kSitePerProcess));
76 } 76 }
77 rfh->OnCrossSiteResponse( 77 rfh->OnCrossSiteResponse(
78 params.global_request_id, cross_site_transferring_request.Pass(), 78 params.global_request_id, cross_site_transferring_request.Pass(),
79 params.transfer_url_chain, params.referrer, 79 params.transfer_url_chain, params.referrer,
80 params.page_transition, params.should_replace_current_entry); 80 params.page_transition, params.should_replace_current_entry);
81 } else if (leak_requests_for_testing_ && cross_site_transferring_request) { 81 } else if (leak_requests_for_testing_ && cross_site_transferring_request) {
82 // Some unit tests expect requests to be leaked in this case, so they can 82 // Some unit tests expect requests to be leaked in this case, so they can
83 // pass them along manually. 83 // pass them along manually.
84 cross_site_transferring_request->ReleaseRequest(); 84 cross_site_transferring_request->ReleaseRequest();
85 } 85 }
86 } 86 }
87 87
88 // Returns whether a transfer is needed by doing a check on the UI thread. 88 // Returns whether a transfer is needed by doing a check on the UI thread.
89 bool CheckNavigationPolicyOnUI(GURL url, int process_id, int render_frame_id) { 89 bool CheckNavigationPolicyOnUI(GURL url, int process_id, int render_frame_id) {
90 CHECK(base::CommandLine::ForCurrentProcess()->HasSwitch( 90 CHECK(SiteIsolationPolicy::AreCrossProcessFramesPossible());
91 switches::kSitePerProcess));
92 RenderFrameHostImpl* rfh = 91 RenderFrameHostImpl* rfh =
93 RenderFrameHostImpl::FromID(process_id, render_frame_id); 92 RenderFrameHostImpl::FromID(process_id, render_frame_id);
94 if (!rfh) 93 if (!rfh)
95 return false; 94 return false;
96 95
97 // A transfer is not needed if the current SiteInstance doesn't yet have a 96 // A transfer is not needed if the current SiteInstance doesn't yet have a
98 // site. This is the case for tests that use NavigateToURL. 97 // site. This is the case for tests that use NavigateToURL.
99 if (!rfh->GetSiteInstance()->HasSite()) 98 if (!rfh->GetSiteInstance()->HasSite())
100 return false; 99 return false;
101 100
102 // TODO(nasko): This check is very simplistic and is used temporarily only 101 // TODO(nasko, nick): These following --site-per-process checks are
103 // for --site-per-process. It should be updated to match the check performed 102 // overly simplistic. Update them to match all the cases
104 // by RenderFrameHostManager::UpdateStateForNavigate. 103 // considered by RenderFrameHostManager::DetermineSiteInstanceForURL.
105 return !SiteInstance::IsSameWebSite( 104 if (SiteInstance::IsSameWebSite(rfh->GetSiteInstance()->GetBrowserContext(),
106 rfh->GetSiteInstance()->GetBrowserContext(), 105 rfh->GetSiteInstance()->GetSiteURL(), url)) {
107 rfh->GetSiteInstance()->GetSiteURL(), url); 106 return false; // The same site, no transition needed.
107 }
108
109 // The sites differ. If either one requires a dedicated process,
110 // then a transfer is needed.
111 return rfh->GetSiteInstance()->RequiresDedicatedProcess() ||
112 SiteIsolationPolicy::DoesSiteRequireDedicatedProcess(url);
108 } 113 }
109 114
110 } // namespace 115 } // namespace
111 116
112 CrossSiteResourceHandler::CrossSiteResourceHandler( 117 CrossSiteResourceHandler::CrossSiteResourceHandler(
113 scoped_ptr<ResourceHandler> next_handler, 118 scoped_ptr<ResourceHandler> next_handler,
114 net::URLRequest* request) 119 net::URLRequest* request)
115 : LayeredResourceHandler(request, next_handler.Pass()), 120 : LayeredResourceHandler(request, next_handler.Pass()),
116 has_started_response_(false), 121 has_started_response_(false),
117 in_cross_site_transition_(false), 122 in_cross_site_transition_(false),
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 ResourceResponse* response, 157 ResourceResponse* response,
153 bool* defer) { 158 bool* defer) {
154 // At this point, we know that the response is safe to send back to the 159 // At this point, we know that the response is safe to send back to the
155 // renderer: it is not a download, and it has passed the SSL and safe 160 // renderer: it is not a download, and it has passed the SSL and safe
156 // browsing checks. 161 // browsing checks.
157 // We should not have already started the transition before now. 162 // We should not have already started the transition before now.
158 DCHECK(!in_cross_site_transition_); 163 DCHECK(!in_cross_site_transition_);
159 164
160 ResourceRequestInfoImpl* info = GetRequestInfo(); 165 ResourceRequestInfoImpl* info = GetRequestInfo();
161 166
162 // We only need to pause the response if a transfer to a different process is 167 // The content embedder can decide that a transfer to a different process is
163 // required. Other cross-process navigations can proceed immediately, since 168 // required for this URL. If so, pause the response now. Other cross process
164 // we run the unload handler at commit time. 169 // navigations can proceed immediately, since we run the unload handler at
165 // Note that a process swap may no longer be necessary if we transferred back 170 // commit time. Note that a process swap may no longer be necessary if we
166 // into the original process due to a redirect. 171 // transferred back into the original process due to a redirect.
167 bool should_transfer = 172 bool definitely_transfer =
168 GetContentClient()->browser()->ShouldSwapProcessesForRedirect( 173 GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
169 info->GetContext(), request()->original_url(), request()->url()); 174 info->GetContext(), request()->original_url(), request()->url());
170 175
171 // If this is a download, just pass the response through without doing a 176 // If this is a download, just pass the response through without doing a
172 // cross-site check. The renderer will see it is a download and abort the 177 // cross-site check. The renderer will see it is a download and abort the
173 // request. 178 // request.
174 // 179 //
175 // Similarly, HTTP 204 (No Content) responses leave us showing the previous 180 // Similarly, HTTP 204 (No Content) responses leave us showing the previous
176 // page. We should allow the navigation to finish without running the unload 181 // page. We should allow the navigation to finish without running the unload
177 // handler or swapping in the pending RenderFrameHost. 182 // handler or swapping in the pending RenderFrameHost.
178 // 183 //
179 // In both cases, any pending RenderFrameHost (if one was created for this 184 // In both cases, any pending RenderFrameHost (if one was created for this
180 // navigation) will stick around until the next cross-site navigation, since 185 // navigation) will stick around until the next cross-site navigation, since
181 // we are unable to tell when to destroy it. 186 // we are unable to tell when to destroy it.
182 // See RenderFrameHostManager::RendererAbortedProvisionalLoad. 187 // See RenderFrameHostManager::RendererAbortedProvisionalLoad.
183 // 188 //
184 // TODO(davidben): Unify IsDownload() and is_stream(). Several places need to 189 // TODO(davidben): Unify IsDownload() and is_stream(). Several places need to
185 // check for both and remembering about streams is error-prone. 190 // check for both and remembering about streams is error-prone.
186 if (info->IsDownload() || info->is_stream() || 191 if (info->IsDownload() || info->is_stream() ||
187 (response->head.headers.get() && 192 (response->head.headers.get() &&
188 response->head.headers->response_code() == 204)) { 193 response->head.headers->response_code() == 204)) {
189 return next_handler_->OnResponseStarted(response, defer); 194 return next_handler_->OnResponseStarted(response, defer);
190 } 195 }
191 196
192 // When the --site-per-process flag is passed, we transfer processes for 197 if (definitely_transfer) {
193 // cross-site navigations. This is skipped if a transfer is already required 198 // Now that we know a transfer is needed and we have something to commit, we
194 // or for WebUI processes for now, since pages like the NTP host multiple 199 // pause to let the UI thread set up the transfer.
200 StartCrossSiteTransition(response);
201
202 // Defer loading until after the new renderer process has issued a
203 // corresponding request.
204 *defer = true;
205 OnDidDefer();
206 return true;
207 }
208
209 // In the site-per-process model, we may also decide (independently from the
210 // content embedder's ShouldSwapProcessesForRedirect decision above) that a
211 // process transfer is needed. For that we need to consult the navigation
212 // policy on the UI thread, so pause the response. Process transfers are
213 // skipped for WebUI processes for now, since pages like the NTP host multiple
Charlie Reis 2015/07/13 22:13:14 While we're here, let's fix this wording: the NTP
ncarter (slow) 2015/07/20 17:45:46 Done.
195 // cross-site WebUI iframes. 214 // cross-site WebUI iframes.
196 if (!should_transfer && 215 if (SiteIsolationPolicy::AreCrossProcessFramesPossible() &&
197 base::CommandLine::ForCurrentProcess()->HasSwitch(
198 switches::kSitePerProcess) &&
199 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( 216 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
200 info->GetChildID())) { 217 info->GetChildID())) {
201 return DeferForNavigationPolicyCheck(info, response, defer); 218 return DeferForNavigationPolicyCheck(info, response, defer);
202 } 219 }
203 220
204 if (!should_transfer) 221 // No deferral needed. Pass the response through.
205 return next_handler_->OnResponseStarted(response, defer); 222 return next_handler_->OnResponseStarted(response, defer);
206
207 // Now that we know a transfer is needed and we have something to commit, we
208 // pause to let the UI thread set up the transfer.
209 StartCrossSiteTransition(response);
210
211 // Defer loading until after the new renderer process has issued a
212 // corresponding request.
213 *defer = true;
214 OnDidDefer();
215 return true;
216 } 223 }
217 224
218 void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) { 225 void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) {
219 if (is_transfer) { 226 if (is_transfer) {
220 StartCrossSiteTransition(response_.get()); 227 StartCrossSiteTransition(response_.get());
221 } else { 228 } else {
222 ResumeResponse(); 229 ResumeResponse();
223 } 230 }
224 } 231 }
225 232
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
372 controller()->Resume(); 379 controller()->Resume();
373 } 380 }
374 } 381 }
375 382
376 void CrossSiteResourceHandler::OnDidDefer() { 383 void CrossSiteResourceHandler::OnDidDefer() {
377 did_defer_ = true; 384 did_defer_ = true;
378 request()->LogBlockedBy("CrossSiteResourceHandler"); 385 request()->LogBlockedBy("CrossSiteResourceHandler");
379 } 386 }
380 387
381 } // namespace content 388 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698