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

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

Issue 248963007: Perform navigation policy check on UI thread for --site-per-process. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebase on ToT. Created 6 years, 8 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 | Annotate | Revision Log
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"
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
77 params.global_request_id, cross_site_transferring_request.Pass(), 77 params.global_request_id, cross_site_transferring_request.Pass(),
78 params.transfer_url_chain, params.referrer, 78 params.transfer_url_chain, params.referrer,
79 params.page_transition, params.should_replace_current_entry); 79 params.page_transition, params.should_replace_current_entry);
80 } else if (leak_requests_for_testing_ && cross_site_transferring_request) { 80 } else if (leak_requests_for_testing_ && cross_site_transferring_request) {
81 // Some unit tests expect requests to be leaked in this case, so they can 81 // Some unit tests expect requests to be leaked in this case, so they can
82 // pass them along manually. 82 // pass them along manually.
83 cross_site_transferring_request->ReleaseRequest(); 83 cross_site_transferring_request->ReleaseRequest();
84 } 84 }
85 } 85 }
86 86
87 bool CheckNavigationPolicyOnUI(GURL url, int process_id, int render_frame_id) {
88 RenderFrameHostImpl* rfh =
89 RenderFrameHostImpl::FromID(process_id, render_frame_id);
90 if (!rfh)
91 return false;
92
93 // TODO(nasko): This check is very simplistic and is used temporarily only
94 // for --site-per-process. It should be updated to match the check performed
95 // by RenderFrameHostManager::UpdateRendererStateForNavigate.
96 return !SiteInstance::IsSameWebSite(
97 rfh->GetSiteInstance()->GetBrowserContext(),
98 rfh->GetSiteInstance()->GetSiteURL(), url);
99 }
100
87 } // namespace 101 } // namespace
88 102
89 CrossSiteResourceHandler::CrossSiteResourceHandler( 103 CrossSiteResourceHandler::CrossSiteResourceHandler(
90 scoped_ptr<ResourceHandler> next_handler, 104 scoped_ptr<ResourceHandler> next_handler,
91 net::URLRequest* request) 105 net::URLRequest* request)
92 : LayeredResourceHandler(request, next_handler.Pass()), 106 : LayeredResourceHandler(request, next_handler.Pass()),
93 has_started_response_(false), 107 has_started_response_(false),
94 in_cross_site_transition_(false), 108 in_cross_site_transition_(false),
95 completed_during_transition_(false), 109 completed_during_transition_(false),
96 did_defer_(false) { 110 did_defer_(false),
111 weak_ptr_factory_(this) {
97 } 112 }
98 113
99 CrossSiteResourceHandler::~CrossSiteResourceHandler() { 114 CrossSiteResourceHandler::~CrossSiteResourceHandler() {
100 // Cleanup back-pointer stored on the request info. 115 // Cleanup back-pointer stored on the request info.
101 GetRequestInfo()->set_cross_site_handler(NULL); 116 GetRequestInfo()->set_cross_site_handler(NULL);
102 } 117 }
103 118
104 bool CrossSiteResourceHandler::OnRequestRedirected( 119 bool CrossSiteResourceHandler::OnRequestRedirected(
105 int request_id, 120 int request_id,
106 const GURL& new_url, 121 const GURL& new_url,
(...skipping 20 matching lines...) Expand all
127 142
128 // We will need to swap processes if either (1) a redirect that requires a 143 // We will need to swap processes if either (1) a redirect that requires a
129 // transfer occurred before we got here, or (2) a pending cross-site request 144 // transfer occurred before we got here, or (2) a pending cross-site request
130 // was already in progress. Note that a swap may no longer be needed if we 145 // was already in progress. Note that a swap may no longer be needed if we
131 // transferred back into the original process due to a redirect. 146 // transferred back into the original process due to a redirect.
132 bool should_transfer = 147 bool should_transfer =
133 GetContentClient()->browser()->ShouldSwapProcessesForRedirect( 148 GetContentClient()->browser()->ShouldSwapProcessesForRedirect(
134 info->GetContext(), request()->original_url(), request()->url()); 149 info->GetContext(), request()->original_url(), request()->url());
135 150
136 // When the --site-per-process flag is passed, we transfer processes for 151 // When the --site-per-process flag is passed, we transfer processes for
137 // cross-site subframe navigations. 152 // cross-site navigations. This is skipped if a transfer is already required
138 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess)) { 153 // or for WebUI processes for now, since pages like the NTP host multiple
139 GURL referrer(request()->referrer()); 154 // cross-site WebUI iframes.
140 // We skip this for WebUI processes for now, since pages like the NTP host 155 if (!should_transfer &&
141 // cross-site WebUI iframes but don't have referrers. 156 CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) &&
142 bool is_webui_process = ChildProcessSecurityPolicyImpl::GetInstance()-> 157 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
143 HasWebUIBindings(info->GetChildID()); 158 info->GetChildID())) {
144 159 return DeferForNavigationPolicyCheck(info, response, defer);
145 // TODO(creis): This shouldn't rely on the referrer to determine the parent
146 // frame's URL. This also doesn't work for hosted apps, due to passing NULL
147 // to IsSameWebSite. It should be possible to always send the navigation to
148 // the UI thread to make a policy decision, which could let us eliminate the
149 // renderer-side check in RenderViewImpl::decidePolicyForNavigation as well.
150 if (info->GetResourceType() == ResourceType::SUB_FRAME &&
151 !is_webui_process &&
152 !SiteInstance::IsSameWebSite(NULL, request()->url(), referrer)) {
153 should_transfer = true;
154 }
155 } 160 }
156 161
157 bool swap_needed = should_transfer || 162 bool swap_needed = should_transfer ||
158 CrossSiteRequestManager::GetInstance()-> 163 CrossSiteRequestManager::GetInstance()->
159 HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID()); 164 HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID());
160 165
161 // If this is a download, just pass the response through without doing a 166 // If this is a download, just pass the response through without doing a
162 // cross-site check. The renderer will see it is a download and abort the 167 // cross-site check. The renderer will see it is a download and abort the
163 // request. 168 // request.
164 // 169 //
(...skipping 18 matching lines...) Expand all
183 // pause to let the UI thread run the unload handler of the previous page 188 // pause to let the UI thread run the unload handler of the previous page
184 // and set up a transfer if needed. 189 // and set up a transfer if needed.
185 StartCrossSiteTransition(request_id, response, should_transfer); 190 StartCrossSiteTransition(request_id, response, should_transfer);
186 191
187 // Defer loading until after the onunload event handler has run. 192 // Defer loading until after the onunload event handler has run.
188 *defer = true; 193 *defer = true;
189 OnDidDefer(); 194 OnDidDefer();
190 return true; 195 return true;
191 } 196 }
192 197
198 void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) {
199 if (is_transfer) {
200 ResourceRequestInfoImpl* info = GetRequestInfo();
201 StartCrossSiteTransition(info->GetRequestID(), response_, is_transfer);
202 } else {
203 ResumeResponse();
204 }
205 }
206
193 bool CrossSiteResourceHandler::OnReadCompleted(int request_id, 207 bool CrossSiteResourceHandler::OnReadCompleted(int request_id,
194 int bytes_read, 208 int bytes_read,
195 bool* defer) { 209 bool* defer) {
196 CHECK(!in_cross_site_transition_); 210 CHECK(!in_cross_site_transition_);
197 return next_handler_->OnReadCompleted(request_id, bytes_read, defer); 211 return next_handler_->OnReadCompleted(request_id, bytes_read, defer);
198 } 212 }
199 213
200 void CrossSiteResourceHandler::OnResponseCompleted( 214 void CrossSiteResourceHandler::OnResponseCompleted(
201 int request_id, 215 int request_id,
202 const net::URLRequestStatus& status, 216 const net::URLRequestStatus& status,
(...skipping 28 matching lines...) Expand all
231 // Defer to tell RDH not to notify the world or clean up the pending request. 245 // Defer to tell RDH not to notify the world or clean up the pending request.
232 // We will do so in ResumeResponse. 246 // We will do so in ResumeResponse.
233 *defer = true; 247 *defer = true;
234 OnDidDefer(); 248 OnDidDefer();
235 } 249 }
236 250
237 // We can now send the response to the new renderer, which will cause 251 // We can now send the response to the new renderer, which will cause
238 // WebContentsImpl to swap in the new renderer and destroy the old one. 252 // WebContentsImpl to swap in the new renderer and destroy the old one.
239 void CrossSiteResourceHandler::ResumeResponse() { 253 void CrossSiteResourceHandler::ResumeResponse() {
240 DCHECK(request()); 254 DCHECK(request());
241 DCHECK(in_cross_site_transition_);
242 in_cross_site_transition_ = false; 255 in_cross_site_transition_ = false;
243 ResourceRequestInfoImpl* info = GetRequestInfo(); 256 ResourceRequestInfoImpl* info = GetRequestInfo();
244 257
245 if (has_started_response_) { 258 if (has_started_response_) {
246 // Send OnResponseStarted to the new renderer. 259 // Send OnResponseStarted to the new renderer.
247 DCHECK(response_); 260 DCHECK(response_);
248 bool defer = false; 261 bool defer = false;
249 if (!next_handler_->OnResponseStarted(info->GetRequestID(), response_.get(), 262 if (!next_handler_->OnResponseStarted(info->GetRequestID(), response_.get(),
250 &defer)) { 263 &defer)) {
251 controller()->Cancel(); 264 controller()->Cancel();
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
319 &OnCrossSiteResponseHelper, 332 &OnCrossSiteResponseHelper,
320 CrossSiteResponseParams(render_frame_id, 333 CrossSiteResponseParams(render_frame_id,
321 global_id, 334 global_id,
322 should_transfer, 335 should_transfer,
323 transfer_url_chain, 336 transfer_url_chain,
324 referrer, 337 referrer,
325 info->GetPageTransition(), 338 info->GetPageTransition(),
326 info->should_replace_current_entry()))); 339 info->should_replace_current_entry())));
327 } 340 }
328 341
342 bool CrossSiteResourceHandler::DeferForNavigationPolicyCheck(
343 ResourceRequestInfoImpl* info,
344 ResourceResponse* response,
345 bool* defer) {
346 // Store the response_ object internally, since the navigation is deferred
347 // regardless of whether it will be a transfer or not.
348 response_ = response;
349
350 // Always defer the navigation to the UI thread to make a policy decision.
351 // It will send the result back to the IO thread to either resume or
352 // transfer it to a new renderer.
353 // TODO(nasko): If the UI thread result is that transfer is required, the
354 // IO thread will defer to the UI thread again through
355 // StartCrossSiteTransition. This is unnecessary and the policy check on the
356 // UI thread should be refactored to avoid the extra hop.
357 BrowserThread::PostTaskAndReplyWithResult(
358 BrowserThread::UI,
359 FROM_HERE,
360 base::Bind(&CheckNavigationPolicyOnUI,
361 request()->url(),
362 info->GetChildID(),
363 info->GetRenderFrameID()),
364 base::Bind(&CrossSiteResourceHandler::ResumeOrTransfer,
365 weak_ptr_factory_.GetWeakPtr()));
366
367 // Defer loading until it is known whether the navigation will transfer
368 // to a new process or continue in the existing one.
369 *defer = true;
370 OnDidDefer();
371 return true;
372 }
373
329 void CrossSiteResourceHandler::ResumeIfDeferred() { 374 void CrossSiteResourceHandler::ResumeIfDeferred() {
330 if (did_defer_) { 375 if (did_defer_) {
331 request()->LogUnblocked(); 376 request()->LogUnblocked();
332 did_defer_ = false; 377 did_defer_ = false;
333 controller()->Resume(); 378 controller()->Resume();
334 } 379 }
335 } 380 }
336 381
337 void CrossSiteResourceHandler::OnDidDefer() { 382 void CrossSiteResourceHandler::OnDidDefer() {
338 did_defer_ = true; 383 did_defer_ = true;
339 request()->LogBlockedBy("CrossSiteResourceHandler"); 384 request()->LogBlockedBy("CrossSiteResourceHandler");
340 } 385 }
341 386
342 } // namespace content 387 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/loader/cross_site_resource_handler.h ('k') | content/browser/site_per_process_browsertest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698