Chromium Code Reviews| 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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); | |
|
Charlie Reis
2014/04/24 20:37:50
We should check for null here, in case the tab was
nasko
2014/04/24 22:31:12
Do'h, I had a check here.
| |
| 90 | |
| 91 // TODO(nasko): This check is very simplistic and is used temporarily only | |
| 92 // for --site-per-process. It should be updated to match the check performed | |
| 93 // by RenderFrameHostManager::UpdateRendererStateForNavigate. | |
| 94 bool transfer = !SiteInstance::IsSameWebSite( | |
|
Charlie Reis
2014/04/24 20:37:50
Why not just return from here?
nasko
2014/04/24 22:31:12
Done.
| |
| 95 rfh->GetSiteInstance()->GetBrowserContext(), | |
| 96 rfh->GetSiteInstance()->GetSiteURL(), url); | |
| 97 | |
| 98 return transfer; | |
| 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 Loading... | |
| 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 cross-site |
| 154 // WebUI iframes but don't have referrers. | |
|
Charlie Reis
2014/04/24 20:37:50
We can drop the "but don't have referrers" part no
nasko
2014/04/24 22:31:12
Done.
| |
| 155 if (!should_transfer && | |
| 156 CommandLine::ForCurrentProcess()->HasSwitch(switches::kSitePerProcess) && | |
| 157 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings( | |
| 158 info->GetChildID())) { | |
| 139 GURL referrer(request()->referrer()); | 159 GURL referrer(request()->referrer()); |
|
Charlie Reis
2014/04/24 20:37:50
referrer looks unused now.
nasko
2014/04/24 22:31:12
Done.
| |
| 140 // We skip this for WebUI processes for now, since pages like the NTP host | 160 // Store the response_ object internally, since it is needed when the flow |
|
Charlie Reis
2014/04/24 20:37:50
Can we move this whole block out to a helper funct
nasko
2014/04/24 22:31:12
Done.
| |
| 141 // cross-site WebUI iframes but don't have referrers. | 161 // comes back to the IO thread. |
| 142 bool is_webui_process = ChildProcessSecurityPolicyImpl::GetInstance()-> | 162 response_ = response; |
|
Charlie Reis
2014/04/24 20:37:50
Hmm, this is subtle. It means this value is set i
nasko
2014/04/24 22:31:12
Done.
| |
| 143 HasWebUIBindings(info->GetChildID()); | |
| 144 | 163 |
| 145 // TODO(creis): This shouldn't rely on the referrer to determine the parent | 164 // Always send the navigation to the UI thread to make a policy decision. It |
|
Charlie Reis
2014/04/24 20:37:50
nit: send the navigation to the -> defer to the
nasko
2014/04/24 22:31:12
Done.
| |
| 146 // frame's URL. This also doesn't work for hosted apps, due to passing NULL | 165 // will send the result back to the IO thread to either resume or transfer |
| 147 // to IsSameWebSite. It should be possible to always send the navigation to | 166 // it to a new renderer. |
| 148 // the UI thread to make a policy decision, which could let us eliminate the | 167 BrowserThread::PostTaskAndReplyWithResult( |
|
Charlie Reis
2014/04/24 20:37:50
This function and the use of WeakPtr here is still
nasko
2014/04/24 22:31:12
I'll add dcheng@ to review.
| |
| 149 // renderer-side check in RenderViewImpl::decidePolicyForNavigation as well. | 168 BrowserThread::UI, |
| 150 if (info->GetResourceType() == ResourceType::SUB_FRAME && | 169 FROM_HERE, |
| 151 !is_webui_process && | 170 base::Bind(&CheckNavigationPolicyOnUI, |
| 152 !SiteInstance::IsSameWebSite(NULL, request()->url(), referrer)) { | 171 request()->url(), |
| 153 should_transfer = true; | 172 info->GetChildID(), |
| 154 } | 173 info->GetRenderFrameID()), |
| 174 base::Bind(&CrossSiteResourceHandler::ResumeOrTransfer, | |
| 175 weak_ptr_factory_.GetWeakPtr())); | |
|
Charlie Reis
2014/04/24 20:37:50
I'm sad that we need to add a weak pointer factory
nasko
2014/04/24 22:31:12
I could do away without the factory, but then we r
| |
| 176 // Defer loading until it is known whether the navigation will transfer | |
| 177 // to a new process or continue in the existing one. | |
| 178 *defer = true; | |
| 179 OnDidDefer(); | |
| 180 return true; | |
| 155 } | 181 } |
| 156 | 182 |
| 157 bool swap_needed = should_transfer || | 183 bool swap_needed = should_transfer || |
| 158 CrossSiteRequestManager::GetInstance()-> | 184 CrossSiteRequestManager::GetInstance()-> |
| 159 HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID()); | 185 HasPendingCrossSiteRequest(info->GetChildID(), info->GetRouteID()); |
| 160 | 186 |
| 161 // If this is a download, just pass the response through without doing a | 187 // 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 | 188 // cross-site check. The renderer will see it is a download and abort the |
| 163 // request. | 189 // request. |
| 164 // | 190 // |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 183 // pause to let the UI thread run the unload handler of the previous page | 209 // pause to let the UI thread run the unload handler of the previous page |
| 184 // and set up a transfer if needed. | 210 // and set up a transfer if needed. |
| 185 StartCrossSiteTransition(request_id, response, should_transfer); | 211 StartCrossSiteTransition(request_id, response, should_transfer); |
| 186 | 212 |
| 187 // Defer loading until after the onunload event handler has run. | 213 // Defer loading until after the onunload event handler has run. |
| 188 *defer = true; | 214 *defer = true; |
| 189 OnDidDefer(); | 215 OnDidDefer(); |
| 190 return true; | 216 return true; |
| 191 } | 217 } |
| 192 | 218 |
| 219 void CrossSiteResourceHandler::ResumeOrTransfer(bool is_transfer) { | |
| 220 if (is_transfer) { | |
| 221 ResourceRequestInfoImpl* info = GetRequestInfo(); | |
| 222 StartCrossSiteTransition(info->GetRequestID(), response_, is_transfer); | |
| 223 } else { | |
| 224 ResumeResponse(); | |
| 225 } | |
| 226 } | |
| 227 | |
| 193 bool CrossSiteResourceHandler::OnReadCompleted(int request_id, | 228 bool CrossSiteResourceHandler::OnReadCompleted(int request_id, |
| 194 int bytes_read, | 229 int bytes_read, |
| 195 bool* defer) { | 230 bool* defer) { |
| 196 CHECK(!in_cross_site_transition_); | 231 CHECK(!in_cross_site_transition_); |
| 197 return next_handler_->OnReadCompleted(request_id, bytes_read, defer); | 232 return next_handler_->OnReadCompleted(request_id, bytes_read, defer); |
| 198 } | 233 } |
| 199 | 234 |
| 200 void CrossSiteResourceHandler::OnResponseCompleted( | 235 void CrossSiteResourceHandler::OnResponseCompleted( |
| 201 int request_id, | 236 int request_id, |
| 202 const net::URLRequestStatus& status, | 237 const net::URLRequestStatus& status, |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 231 // Defer to tell RDH not to notify the world or clean up the pending request. | 266 // Defer to tell RDH not to notify the world or clean up the pending request. |
| 232 // We will do so in ResumeResponse. | 267 // We will do so in ResumeResponse. |
| 233 *defer = true; | 268 *defer = true; |
| 234 OnDidDefer(); | 269 OnDidDefer(); |
| 235 } | 270 } |
| 236 | 271 |
| 237 // We can now send the response to the new renderer, which will cause | 272 // 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. | 273 // WebContentsImpl to swap in the new renderer and destroy the old one. |
| 239 void CrossSiteResourceHandler::ResumeResponse() { | 274 void CrossSiteResourceHandler::ResumeResponse() { |
| 240 DCHECK(request()); | 275 DCHECK(request()); |
| 241 DCHECK(in_cross_site_transition_); | |
| 242 in_cross_site_transition_ = false; | 276 in_cross_site_transition_ = false; |
| 243 ResourceRequestInfoImpl* info = GetRequestInfo(); | 277 ResourceRequestInfoImpl* info = GetRequestInfo(); |
| 244 | 278 |
| 245 if (has_started_response_) { | 279 if (has_started_response_) { |
| 246 // Send OnResponseStarted to the new renderer. | 280 // Send OnResponseStarted to the new renderer. |
| 247 DCHECK(response_); | 281 DCHECK(response_); |
| 248 bool defer = false; | 282 bool defer = false; |
| 249 if (!next_handler_->OnResponseStarted(info->GetRequestID(), response_.get(), | 283 if (!next_handler_->OnResponseStarted(info->GetRequestID(), response_.get(), |
| 250 &defer)) { | 284 &defer)) { |
| 251 controller()->Cancel(); | 285 controller()->Cancel(); |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 333 controller()->Resume(); | 367 controller()->Resume(); |
| 334 } | 368 } |
| 335 } | 369 } |
| 336 | 370 |
| 337 void CrossSiteResourceHandler::OnDidDefer() { | 371 void CrossSiteResourceHandler::OnDidDefer() { |
| 338 did_defer_ = true; | 372 did_defer_ = true; |
| 339 request()->LogBlockedBy("CrossSiteResourceHandler"); | 373 request()->LogBlockedBy("CrossSiteResourceHandler"); |
| 340 } | 374 } |
| 341 | 375 |
| 342 } // namespace content | 376 } // namespace content |
| OLD | NEW |