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 "base/command_line.h" | 5 #include "base/command_line.h" |
6 #include "base/strings/stringprintf.h" | 6 #include "base/strings/stringprintf.h" |
7 #include "base/strings/utf_string_conversions.h" | 7 #include "base/strings/utf_string_conversions.h" |
8 #include "content/browser/frame_host/frame_tree.h" | 8 #include "content/browser/frame_host/frame_tree.h" |
| 9 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
9 #include "content/browser/renderer_host/render_view_host_impl.h" | 10 #include "content/browser/renderer_host/render_view_host_impl.h" |
10 #include "content/browser/web_contents/web_contents_impl.h" | 11 #include "content/browser/web_contents/web_contents_impl.h" |
11 #include "content/public/browser/navigation_entry.h" | 12 #include "content/public/browser/navigation_entry.h" |
12 #include "content/public/browser/notification_observer.h" | 13 #include "content/public/browser/notification_observer.h" |
13 #include "content/public/browser/notification_service.h" | 14 #include "content/public/browser/notification_service.h" |
14 #include "content/public/browser/notification_types.h" | 15 #include "content/public/browser/notification_types.h" |
| 16 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
| 17 #include "content/public/browser/resource_throttle.h" |
15 #include "content/public/browser/web_contents_observer.h" | 18 #include "content/public/browser/web_contents_observer.h" |
16 #include "content/public/common/content_switches.h" | 19 #include "content/public/common/content_switches.h" |
17 #include "content/public/common/url_constants.h" | 20 #include "content/public/common/url_constants.h" |
18 #include "content/public/test/browser_test_utils.h" | 21 #include "content/public/test/browser_test_utils.h" |
19 #include "content/public/test/test_navigation_observer.h" | 22 #include "content/public/test/test_navigation_observer.h" |
20 #include "content/public/test/test_utils.h" | 23 #include "content/public/test/test_utils.h" |
21 #include "content/shell/browser/shell.h" | 24 #include "content/shell/browser/shell.h" |
22 #include "content/shell/browser/shell_content_browser_client.h" | 25 #include "content/shell/browser/shell_content_browser_client.h" |
| 26 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" |
23 #include "content/test/content_browser_test.h" | 27 #include "content/test/content_browser_test.h" |
24 #include "content/test/content_browser_test_utils.h" | 28 #include "content/test/content_browser_test_utils.h" |
25 #include "net/base/escape.h" | 29 #include "net/base/escape.h" |
26 #include "net/dns/mock_host_resolver.h" | 30 #include "net/dns/mock_host_resolver.h" |
| 31 #include "net/url_request/url_request.h" |
| 32 #include "net/url_request/url_request_status.h" |
27 | 33 |
28 namespace content { | 34 namespace content { |
29 | 35 |
30 class SitePerProcessWebContentsObserver: public WebContentsObserver { | 36 class SitePerProcessWebContentsObserver: public WebContentsObserver { |
31 public: | 37 public: |
32 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) | 38 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) |
33 : WebContentsObserver(web_contents), | 39 : WebContentsObserver(web_contents), |
34 navigation_succeeded_(false) {} | 40 navigation_succeeded_(false) {} |
35 virtual ~SitePerProcessWebContentsObserver() {} | 41 virtual ~SitePerProcessWebContentsObserver() {} |
36 | 42 |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 details_ = details; | 158 details_ = details; |
153 seen_twice_ = seen_; | 159 seen_twice_ = seen_; |
154 seen_ = true; | 160 seen_ = true; |
155 if (!running_) | 161 if (!running_) |
156 return; | 162 return; |
157 | 163 |
158 message_loop_runner_->Quit(); | 164 message_loop_runner_->Quit(); |
159 running_ = false; | 165 running_ = false; |
160 } | 166 } |
161 | 167 |
| 168 // Tracks a single request for a specified URL, and allows waiting until the |
| 169 // request is destroyed, and then inspecting whether it completed successfully. |
| 170 class TrackingResourceDispatcherHostDelegate |
| 171 : public ShellResourceDispatcherHostDelegate { |
| 172 public: |
| 173 TrackingResourceDispatcherHostDelegate() : throttle_created_(false) { |
| 174 } |
| 175 |
| 176 virtual void RequestBeginning( |
| 177 net::URLRequest* request, |
| 178 ResourceContext* resource_context, |
| 179 appcache::AppCacheService* appcache_service, |
| 180 ResourceType::Type resource_type, |
| 181 int child_id, |
| 182 int route_id, |
| 183 ScopedVector<ResourceThrottle>* throttles) OVERRIDE { |
| 184 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 185 ShellResourceDispatcherHostDelegate::RequestBeginning( |
| 186 request, resource_context, appcache_service, resource_type, child_id, |
| 187 route_id, throttles); |
| 188 // Expect only a single request for the tracked url. |
| 189 ASSERT_FALSE(throttle_created_); |
| 190 // If this is a request for the tracked URL, add a throttle to track it. |
| 191 if (request->url() == tracked_url_) |
| 192 throttles->push_back(new TrackingThrottle(request, this)); |
| 193 } |
| 194 |
| 195 // Starts tracking a URL. The request for previously tracked URL, if any, |
| 196 // must have been made and deleted before calling this function. |
| 197 void SetTrackedURL(const GURL& tracked_url) { |
| 198 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 199 // Should not currently be tracking any URL. |
| 200 ASSERT_FALSE(run_loop_); |
| 201 |
| 202 // Create a RunLoop that will be stopped once the request for the tracked |
| 203 // URL has been destroyed, to allow tracking the URL while also waiting for |
| 204 // other events. |
| 205 run_loop_.reset(new base::RunLoop()); |
| 206 |
| 207 BrowserThread::PostTask( |
| 208 BrowserThread::IO, FROM_HERE, |
| 209 base::Bind( |
| 210 &TrackingResourceDispatcherHostDelegate::SetTrackedURLOnIOThread, |
| 211 base::Unretained(this), |
| 212 tracked_url)); |
| 213 } |
| 214 |
| 215 // Waits until the tracked URL has been requests, and the request for it has |
| 216 // been destroyed. |
| 217 bool WaitForTrackedURLAndGetCompleted() { |
| 218 CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 219 run_loop_->Run(); |
| 220 run_loop_.reset(); |
| 221 return tracked_request_completed_; |
| 222 } |
| 223 |
| 224 private: |
| 225 // ResourceThrottle attached to request for the tracked URL. On destruction, |
| 226 // passes the final URLRequestStatus back to the delegate. |
| 227 class TrackingThrottle : public ResourceThrottle { |
| 228 public: |
| 229 TrackingThrottle(net::URLRequest* request, |
| 230 TrackingResourceDispatcherHostDelegate* tracker) |
| 231 : request_(request), tracker_(tracker) { |
| 232 } |
| 233 |
| 234 virtual ~TrackingThrottle() { |
| 235 // If the request is deleted without being cancelled, its status will |
| 236 // indicate it succeeded, so have to check if the request is still pending |
| 237 // as well. |
| 238 tracker_->OnTrackedRequestDestroyed( |
| 239 !request_->is_pending() && request_->status().is_success()); |
| 240 } |
| 241 |
| 242 // ResourceThrottle implementation: |
| 243 virtual const char* GetNameForLogging() const OVERRIDE { |
| 244 return "TrackingThrottle"; |
| 245 } |
| 246 |
| 247 private: |
| 248 net::URLRequest* request_; |
| 249 TrackingResourceDispatcherHostDelegate* tracker_; |
| 250 |
| 251 DISALLOW_COPY_AND_ASSIGN(TrackingThrottle); |
| 252 }; |
| 253 |
| 254 void SetTrackedURLOnIOThread(const GURL& tracked_url) { |
| 255 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 256 throttle_created_ = false; |
| 257 tracked_url_ = tracked_url; |
| 258 } |
| 259 |
| 260 void OnTrackedRequestDestroyed(bool completed) { |
| 261 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 262 tracked_request_completed_ = completed; |
| 263 tracked_url_ = GURL(); |
| 264 |
| 265 BrowserThread::PostTask( |
| 266 BrowserThread::UI, FROM_HERE, run_loop_->QuitClosure()); |
| 267 } |
| 268 |
| 269 // These live on the IO thread. |
| 270 GURL tracked_url_; |
| 271 bool throttle_created_; |
| 272 |
| 273 // This is created and destroyed on the UI thread, but stopped on the IO |
| 274 // thread. |
| 275 scoped_ptr<base::RunLoop> run_loop_; |
| 276 |
| 277 // Set on the IO thread while |run_loop_| is non-NULL, read on the UI thread |
| 278 // after deleting run_loop_. |
| 279 bool tracked_request_completed_; |
| 280 |
| 281 DISALLOW_COPY_AND_ASSIGN(TrackingResourceDispatcherHostDelegate); |
| 282 }; |
| 283 |
| 284 // WebContentsDelegate that fails to open a URL when there's a request that |
| 285 // needs to be transferred between renderers. |
| 286 class NoTransferRequestDelegate : public WebContentsDelegate { |
| 287 public: |
| 288 NoTransferRequestDelegate() {} |
| 289 |
| 290 virtual WebContents* OpenURLFromTab(WebContents* source, |
| 291 const OpenURLParams& params) OVERRIDE { |
| 292 bool is_transfer = |
| 293 (params.transferred_global_request_id != GlobalRequestID()); |
| 294 if (is_transfer) |
| 295 return NULL; |
| 296 NavigationController::LoadURLParams load_url_params(params.url); |
| 297 load_url_params.referrer = params.referrer; |
| 298 load_url_params.frame_tree_node_id = params.frame_tree_node_id; |
| 299 load_url_params.transition_type = params.transition; |
| 300 load_url_params.extra_headers = params.extra_headers; |
| 301 load_url_params.should_replace_current_entry = |
| 302 params.should_replace_current_entry; |
| 303 load_url_params.is_renderer_initiated = true; |
| 304 source->GetController().LoadURLWithParams(load_url_params); |
| 305 return source; |
| 306 } |
| 307 |
| 308 private: |
| 309 DISALLOW_COPY_AND_ASSIGN(NoTransferRequestDelegate); |
| 310 }; |
| 311 |
162 class SitePerProcessBrowserTest : public ContentBrowserTest { | 312 class SitePerProcessBrowserTest : public ContentBrowserTest { |
| 313 public: |
| 314 SitePerProcessBrowserTest() : old_delegate_(NULL) { |
| 315 } |
| 316 |
| 317 // ContentBrowserTest implementation: |
| 318 virtual void SetUpOnMainThread() OVERRIDE { |
| 319 BrowserThread::PostTask( |
| 320 BrowserThread::IO, FROM_HERE, |
| 321 base::Bind( |
| 322 &SitePerProcessBrowserTest::InjectResourceDisptcherHostDelegate, |
| 323 base::Unretained(this))); |
| 324 } |
| 325 |
| 326 virtual void TearDownOnMainThread() OVERRIDE { |
| 327 BrowserThread::PostTask( |
| 328 BrowserThread::IO, FROM_HERE, |
| 329 base::Bind( |
| 330 &SitePerProcessBrowserTest::RestoreResourceDisptcherHostDelegate, |
| 331 base::Unretained(this))); |
| 332 } |
| 333 |
163 protected: | 334 protected: |
164 // Start at a data URL so each extra navigation creates a navigation entry. | 335 // Start at a data URL so each extra navigation creates a navigation entry. |
165 // (The first navigation will silently be classified as AUTO_SUBFRAME.) | 336 // (The first navigation will silently be classified as AUTO_SUBFRAME.) |
166 // TODO(creis): This won't be necessary when we can wait for LOAD_STOP. | 337 // TODO(creis): This won't be necessary when we can wait for LOAD_STOP. |
167 void StartFrameAtDataURL() { | 338 void StartFrameAtDataURL() { |
168 std::string data_url_script = | 339 std::string data_url_script = |
169 "var iframes = document.getElementById('test');iframes.src=" | 340 "var iframes = document.getElementById('test');iframes.src=" |
170 "'data:text/html,dataurl';"; | 341 "'data:text/html,dataurl';"; |
171 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script)); | 342 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script)); |
172 } | 343 } |
(...skipping 15 matching lines...) Expand all Loading... |
188 NOTIFICATION_NAV_ENTRY_COMMITTED, | 359 NOTIFICATION_NAV_ENTRY_COMMITTED, |
189 Source<NavigationController>( | 360 Source<NavigationController>( |
190 &window->web_contents()->GetController())); | 361 &window->web_contents()->GetController())); |
191 bool result = ExecuteScript(window->web_contents(), script); | 362 bool result = ExecuteScript(window->web_contents(), script); |
192 load_observer.Wait(); | 363 load_observer.Wait(); |
193 return result; | 364 return result; |
194 } | 365 } |
195 | 366 |
196 void NavigateToURLContentInitiated(Shell* window, | 367 void NavigateToURLContentInitiated(Shell* window, |
197 const GURL& url, | 368 const GURL& url, |
198 bool should_replace_current_entry) { | 369 bool should_replace_current_entry, |
| 370 bool should_wait_for_navigation) { |
199 std::string script; | 371 std::string script; |
200 if (should_replace_current_entry) | 372 if (should_replace_current_entry) |
201 script = base::StringPrintf("location.replace('%s')", url.spec().c_str()); | 373 script = base::StringPrintf("location.replace('%s')", url.spec().c_str()); |
202 else | 374 else |
203 script = base::StringPrintf("location.href = '%s'", url.spec().c_str()); | 375 script = base::StringPrintf("location.href = '%s'", url.spec().c_str()); |
204 TestNavigationObserver load_observer(shell()->web_contents(), 1); | 376 TestNavigationObserver load_observer(shell()->web_contents(), 1); |
205 bool result = ExecuteScript(window->web_contents(), script); | 377 bool result = ExecuteScript(window->web_contents(), script); |
206 EXPECT_TRUE(result); | 378 EXPECT_TRUE(result); |
207 load_observer.Wait(); | 379 if (should_wait_for_navigation) |
| 380 load_observer.Wait(); |
208 } | 381 } |
209 | 382 |
210 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 383 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
211 command_line->AppendSwitch(switches::kSitePerProcess); | 384 command_line->AppendSwitch(switches::kSitePerProcess); |
212 | 385 |
213 // TODO(creis): Remove this when GTK is no longer a supported platform. | 386 // TODO(creis): Remove this when GTK is no longer a supported platform. |
214 command_line->AppendSwitch(switches::kForceCompositingMode); | 387 command_line->AppendSwitch(switches::kForceCompositingMode); |
215 } | 388 } |
| 389 |
| 390 void InjectResourceDisptcherHostDelegate() { |
| 391 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 392 old_delegate_ = ResourceDispatcherHostImpl::Get()->delegate(); |
| 393 ResourceDispatcherHostImpl::Get()->SetDelegate(&tracking_delegate_); |
| 394 } |
| 395 |
| 396 void RestoreResourceDisptcherHostDelegate() { |
| 397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 398 ResourceDispatcherHostImpl::Get()->SetDelegate(old_delegate_); |
| 399 old_delegate_ = NULL; |
| 400 } |
| 401 |
| 402 TrackingResourceDispatcherHostDelegate& tracking_delegate() { |
| 403 return tracking_delegate_; |
| 404 } |
| 405 |
| 406 private: |
| 407 TrackingResourceDispatcherHostDelegate tracking_delegate_; |
| 408 ResourceDispatcherHostDelegate* old_delegate_; |
216 }; | 409 }; |
217 | 410 |
218 // Ensure that we can complete a cross-process subframe navigation. | 411 // Ensure that we can complete a cross-process subframe navigation. |
219 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) { | 412 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) { |
220 host_resolver()->AddRule("*", "127.0.0.1"); | 413 host_resolver()->AddRule("*", "127.0.0.1"); |
221 ASSERT_TRUE(test_server()->Start()); | 414 ASSERT_TRUE(test_server()->Start()); |
222 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); | 415 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); |
223 NavigateToURL(shell(), main_url); | 416 NavigateToURL(shell(), main_url); |
224 | 417 |
225 StartFrameAtDataURL(); | 418 StartFrameAtDataURL(); |
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
491 // transfer). This test intentionally exercises that case. | 684 // transfer). This test intentionally exercises that case. |
492 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); | 685 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); |
493 | 686 |
494 // Navigate to a page on A.com with entry replacement. This navigation is | 687 // Navigate to a page on A.com with entry replacement. This navigation is |
495 // cross-site, so the renderer will send it to the browser via OpenURL to give | 688 // cross-site, so the renderer will send it to the browser via OpenURL to give |
496 // to a new process. It will then be transferred into yet another process due | 689 // to a new process. It will then be transferred into yet another process due |
497 // to the call above. | 690 // to the call above. |
498 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); | 691 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); |
499 replace_host.SetHostStr(a_com); | 692 replace_host.SetHostStr(a_com); |
500 url2 = url2.ReplaceComponents(replace_host); | 693 url2 = url2.ReplaceComponents(replace_host); |
501 NavigateToURLContentInitiated(shell(), url2, true); | 694 // Used to make sure the request for url2 succeeds, and there was only one of |
| 695 // them. |
| 696 tracking_delegate().SetTrackedURL(url2); |
| 697 NavigateToURLContentInitiated(shell(), url2, true, true); |
502 | 698 |
503 // There should be one history entry. url2 should have replaced url1. | 699 // There should be one history entry. url2 should have replaced url1. |
504 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 700 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
505 EXPECT_EQ(1, controller.GetEntryCount()); | 701 EXPECT_EQ(1, controller.GetEntryCount()); |
506 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | 702 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); |
507 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | 703 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); |
| 704 // Make sure the request succeeded. |
| 705 EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); |
508 | 706 |
509 // Now navigate as before to a page on B.com, but normally (without | 707 // Now navigate as before to a page on B.com, but normally (without |
510 // replacement). This will still perform a double process-swap as above, via | 708 // replacement). This will still perform a double process-swap as above, via |
511 // OpenURL and then transfer. | 709 // OpenURL and then transfer. |
512 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); | 710 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); |
513 replace_host.SetHostStr(b_com); | 711 replace_host.SetHostStr(b_com); |
514 url3 = url3.ReplaceComponents(replace_host); | 712 url3 = url3.ReplaceComponents(replace_host); |
515 NavigateToURLContentInitiated(shell(), url3, false); | 713 // Used to make sure the request for url3 succeeds, and there was only one of |
| 714 // them. |
| 715 tracking_delegate().SetTrackedURL(url3); |
| 716 NavigateToURLContentInitiated(shell(), url3, false, true); |
516 | 717 |
517 // There should be two history entries. url2 should have replaced url1. url2 | 718 // There should be two history entries. url2 should have replaced url1. url2 |
518 // should not have replaced url3. | 719 // should not have replaced url3. |
519 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 720 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
520 EXPECT_EQ(2, controller.GetEntryCount()); | 721 EXPECT_EQ(2, controller.GetEntryCount()); |
521 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | 722 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); |
522 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | 723 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); |
523 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); | 724 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); |
| 725 |
| 726 // Make sure the request succeeded. |
| 727 EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); |
524 } | 728 } |
525 | 729 |
526 // Tests that the |should_replace_current_entry| flag persists correctly across | 730 // Tests that the |should_replace_current_entry| flag persists correctly across |
527 // request transfers that began with a content-initiated in-process | 731 // request transfers that began with a content-initiated in-process |
528 // navigation. This test is the same as the test above, except transfering from | 732 // navigation. This test is the same as the test above, except transfering from |
529 // in-process. | 733 // in-process. |
530 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | 734 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
531 ReplaceEntryInProcessThenTranfers) { | 735 ReplaceEntryInProcessThenTranfers) { |
532 const NavigationController& controller = | 736 const NavigationController& controller = |
533 shell()->web_contents()->GetController(); | 737 shell()->web_contents()->GetController(); |
534 ASSERT_TRUE(test_server()->Start()); | 738 ASSERT_TRUE(test_server()->Start()); |
535 | 739 |
536 // Navigate to a starting URL, so there is a history entry to replace. | 740 // Navigate to a starting URL, so there is a history entry to replace. |
537 GURL url = test_server()->GetURL("files/site_isolation/blank.html?1"); | 741 GURL url = test_server()->GetURL("files/site_isolation/blank.html?1"); |
538 NavigateToURL(shell(), url); | 742 NavigateToURL(shell(), url); |
539 | 743 |
540 // Force all future navigations to transfer. Note that this includes same-site | 744 // Force all future navigations to transfer. Note that this includes same-site |
541 // navigiations which may cause double process swaps (via OpenURL and then via | 745 // navigiations which may cause double process swaps (via OpenURL and then via |
542 // transfer). All navigations in this test are same-site, so it only swaps | 746 // transfer). All navigations in this test are same-site, so it only swaps |
543 // processes via request transfer. | 747 // processes via request transfer. |
544 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); | 748 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); |
545 | 749 |
546 // Navigate in-process with entry replacement. It will then be transferred | 750 // Navigate in-process with entry replacement. It will then be transferred |
547 // into a new one due to the call above. | 751 // into a new one due to the call above. |
548 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); | 752 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); |
549 NavigateToURLContentInitiated(shell(), url2, true); | 753 NavigateToURLContentInitiated(shell(), url2, true, true); |
550 | 754 |
551 // There should be one history entry. url2 should have replaced url1. | 755 // There should be one history entry. url2 should have replaced url1. |
552 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 756 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
553 EXPECT_EQ(1, controller.GetEntryCount()); | 757 EXPECT_EQ(1, controller.GetEntryCount()); |
554 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | 758 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); |
555 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | 759 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); |
556 | 760 |
557 // Now navigate as before, but without replacement. | 761 // Now navigate as before, but without replacement. |
558 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); | 762 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); |
559 NavigateToURLContentInitiated(shell(), url3, false); | 763 NavigateToURLContentInitiated(shell(), url3, false, true); |
560 | 764 |
561 // There should be two history entries. url2 should have replaced url1. url2 | 765 // There should be two history entries. url2 should have replaced url1. url2 |
562 // should not have replaced url3. | 766 // should not have replaced url3. |
563 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 767 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
564 EXPECT_EQ(2, controller.GetEntryCount()); | 768 EXPECT_EQ(2, controller.GetEntryCount()); |
565 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | 769 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); |
566 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | 770 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); |
567 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); | 771 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); |
568 } | 772 } |
569 | 773 |
(...skipping 20 matching lines...) Expand all Loading... |
590 // and second in response to the server redirect to B.com. The second swap is | 794 // and second in response to the server redirect to B.com. The second swap is |
591 // also renderer-initiated via OpenURL because decidePolicyForNavigation is | 795 // also renderer-initiated via OpenURL because decidePolicyForNavigation is |
592 // currently applied on redirects. | 796 // currently applied on redirects. |
593 GURL url2b = test_server()->GetURL("files/site_isolation/blank.html?2"); | 797 GURL url2b = test_server()->GetURL("files/site_isolation/blank.html?2"); |
594 replace_host.SetHostStr(b_com); | 798 replace_host.SetHostStr(b_com); |
595 url2b = url2b.ReplaceComponents(replace_host); | 799 url2b = url2b.ReplaceComponents(replace_host); |
596 GURL url2a = test_server()->GetURL( | 800 GURL url2a = test_server()->GetURL( |
597 "server-redirect?" + net::EscapeQueryParamValue(url2b.spec(), false)); | 801 "server-redirect?" + net::EscapeQueryParamValue(url2b.spec(), false)); |
598 replace_host.SetHostStr(a_com); | 802 replace_host.SetHostStr(a_com); |
599 url2a = url2a.ReplaceComponents(replace_host); | 803 url2a = url2a.ReplaceComponents(replace_host); |
600 NavigateToURLContentInitiated(shell(), url2a, true); | 804 NavigateToURLContentInitiated(shell(), url2a, true, true); |
601 | 805 |
602 // There should be one history entry. url2b should have replaced url1. | 806 // There should be one history entry. url2b should have replaced url1. |
603 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 807 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
604 EXPECT_EQ(1, controller.GetEntryCount()); | 808 EXPECT_EQ(1, controller.GetEntryCount()); |
605 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | 809 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); |
606 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); | 810 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); |
607 | 811 |
608 // Now repeat without replacement. | 812 // Now repeat without replacement. |
609 GURL url3b = test_server()->GetURL("files/site_isolation/blank.html?3"); | 813 GURL url3b = test_server()->GetURL("files/site_isolation/blank.html?3"); |
610 replace_host.SetHostStr(b_com); | 814 replace_host.SetHostStr(b_com); |
611 url3b = url3b.ReplaceComponents(replace_host); | 815 url3b = url3b.ReplaceComponents(replace_host); |
612 GURL url3a = test_server()->GetURL( | 816 GURL url3a = test_server()->GetURL( |
613 "server-redirect?" + net::EscapeQueryParamValue(url3b.spec(), false)); | 817 "server-redirect?" + net::EscapeQueryParamValue(url3b.spec(), false)); |
614 replace_host.SetHostStr(a_com); | 818 replace_host.SetHostStr(a_com); |
615 url3a = url3a.ReplaceComponents(replace_host); | 819 url3a = url3a.ReplaceComponents(replace_host); |
616 NavigateToURLContentInitiated(shell(), url3a, false); | 820 NavigateToURLContentInitiated(shell(), url3a, false, true); |
617 | 821 |
618 // There should be two history entries. url2b should have replaced url1. url2b | 822 // There should be two history entries. url2b should have replaced url1. url2b |
619 // should not have replaced url3b. | 823 // should not have replaced url3b. |
620 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | 824 EXPECT_TRUE(controller.GetPendingEntry() == NULL); |
621 EXPECT_EQ(2, controller.GetEntryCount()); | 825 EXPECT_EQ(2, controller.GetEntryCount()); |
622 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | 826 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); |
623 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); | 827 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); |
624 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL()); | 828 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL()); |
625 } | 829 } |
626 | 830 |
| 831 // Tests that the request is destroyed when a cross process navigation is |
| 832 // cancelled. |
| 833 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NoLeakOnCrossSiteCancel) { |
| 834 const NavigationController& controller = |
| 835 shell()->web_contents()->GetController(); |
| 836 host_resolver()->AddRule("*", "127.0.0.1"); |
| 837 ASSERT_TRUE(test_server()->Start()); |
| 838 |
| 839 // These must all stay in scope with replace_host. |
| 840 GURL::Replacements replace_host; |
| 841 std::string a_com("A.com"); |
| 842 std::string b_com("B.com"); |
| 843 |
| 844 // Navigate to a starting URL, so there is a history entry to replace. |
| 845 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); |
| 846 NavigateToURL(shell(), url1); |
| 847 |
| 848 // Force all future navigations to transfer. |
| 849 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); |
| 850 |
| 851 NoTransferRequestDelegate no_transfer_request_delegate; |
| 852 WebContentsDelegate* old_delegate = shell()->web_contents()->GetDelegate(); |
| 853 shell()->web_contents()->SetDelegate(&no_transfer_request_delegate); |
| 854 |
| 855 // Navigate to a page on A.com with entry replacement. This navigation is |
| 856 // cross-site, so the renderer will send it to the browser via OpenURL to give |
| 857 // to a new process. It will then be transferred into yet another process due |
| 858 // to the call above. |
| 859 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); |
| 860 replace_host.SetHostStr(a_com); |
| 861 url2 = url2.ReplaceComponents(replace_host); |
| 862 // Used to make sure the second request is cancelled, and there is only one |
| 863 // request for url2. |
| 864 tracking_delegate().SetTrackedURL(url2); |
| 865 |
| 866 // Don't wait for the navigation to complete, since that never happens in |
| 867 // this case. |
| 868 NavigateToURLContentInitiated(shell(), url2, false, false); |
| 869 |
| 870 // There should be one history entry, with url1. |
| 871 EXPECT_EQ(1, controller.GetEntryCount()); |
| 872 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); |
| 873 EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL()); |
| 874 |
| 875 // Make sure the request for url2 did not complete. |
| 876 EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); |
| 877 |
| 878 shell()->web_contents()->SetDelegate(old_delegate); |
| 879 } |
| 880 |
627 } // namespace content | 881 } // namespace content |
OLD | NEW |