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 |