| 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" | |
| 10 #include "content/browser/renderer_host/render_view_host_impl.h" | 9 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 11 #include "content/browser/web_contents/web_contents_impl.h" | 10 #include "content/browser/web_contents/web_contents_impl.h" |
| 12 #include "content/public/browser/navigation_entry.h" | |
| 13 #include "content/public/browser/notification_observer.h" | 11 #include "content/public/browser/notification_observer.h" |
| 14 #include "content/public/browser/notification_service.h" | 12 #include "content/public/browser/notification_service.h" |
| 15 #include "content/public/browser/notification_types.h" | 13 #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" | |
| 18 #include "content/public/browser/web_contents_observer.h" | 14 #include "content/public/browser/web_contents_observer.h" |
| 19 #include "content/public/common/content_switches.h" | 15 #include "content/public/common/content_switches.h" |
| 20 #include "content/public/common/url_constants.h" | 16 #include "content/public/common/url_constants.h" |
| 21 #include "content/public/test/browser_test_utils.h" | 17 #include "content/public/test/browser_test_utils.h" |
| 22 #include "content/public/test/test_navigation_observer.h" | |
| 23 #include "content/public/test/test_utils.h" | 18 #include "content/public/test/test_utils.h" |
| 24 #include "content/shell/browser/shell.h" | 19 #include "content/shell/browser/shell.h" |
| 25 #include "content/shell/browser/shell_content_browser_client.h" | |
| 26 #include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" | |
| 27 #include "content/test/content_browser_test.h" | 20 #include "content/test/content_browser_test.h" |
| 28 #include "content/test/content_browser_test_utils.h" | 21 #include "content/test/content_browser_test_utils.h" |
| 29 #include "net/base/escape.h" | |
| 30 #include "net/dns/mock_host_resolver.h" | 22 #include "net/dns/mock_host_resolver.h" |
| 31 #include "net/url_request/url_request.h" | |
| 32 #include "net/url_request/url_request_status.h" | |
| 33 | 23 |
| 34 namespace content { | 24 namespace content { |
| 35 | 25 |
| 36 class SitePerProcessWebContentsObserver: public WebContentsObserver { | 26 class SitePerProcessWebContentsObserver: public WebContentsObserver { |
| 37 public: | 27 public: |
| 38 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) | 28 explicit SitePerProcessWebContentsObserver(WebContents* web_contents) |
| 39 : WebContentsObserver(web_contents), | 29 : WebContentsObserver(web_contents), |
| 40 navigation_succeeded_(false) {} | 30 navigation_succeeded_(false) {} |
| 41 virtual ~SitePerProcessWebContentsObserver() {} | 31 virtual ~SitePerProcessWebContentsObserver() {} |
| 42 | 32 |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 details_ = details; | 148 details_ = details; |
| 159 seen_twice_ = seen_; | 149 seen_twice_ = seen_; |
| 160 seen_ = true; | 150 seen_ = true; |
| 161 if (!running_) | 151 if (!running_) |
| 162 return; | 152 return; |
| 163 | 153 |
| 164 message_loop_runner_->Quit(); | 154 message_loop_runner_->Quit(); |
| 165 running_ = false; | 155 running_ = false; |
| 166 } | 156 } |
| 167 | 157 |
| 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 | |
| 312 class SitePerProcessBrowserTest : public ContentBrowserTest { | 158 class SitePerProcessBrowserTest : public ContentBrowserTest { |
| 313 public: | 159 public: |
| 314 SitePerProcessBrowserTest() : old_delegate_(NULL) { | 160 SitePerProcessBrowserTest() {} |
| 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 | 161 |
| 334 protected: | 162 protected: |
| 335 // Start at a data URL so each extra navigation creates a navigation entry. | 163 // Start at a data URL so each extra navigation creates a navigation entry. |
| 336 // (The first navigation will silently be classified as AUTO_SUBFRAME.) | 164 // (The first navigation will silently be classified as AUTO_SUBFRAME.) |
| 337 // TODO(creis): This won't be necessary when we can wait for LOAD_STOP. | 165 // TODO(creis): This won't be necessary when we can wait for LOAD_STOP. |
| 338 void StartFrameAtDataURL() { | 166 void StartFrameAtDataURL() { |
| 339 std::string data_url_script = | 167 std::string data_url_script = |
| 340 "var iframes = document.getElementById('test');iframes.src=" | 168 "var iframes = document.getElementById('test');iframes.src=" |
| 341 "'data:text/html,dataurl';"; | 169 "'data:text/html,dataurl';"; |
| 342 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script)); | 170 ASSERT_TRUE(ExecuteScript(shell()->web_contents(), data_url_script)); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 357 iframe_id.c_str(), url.spec().c_str()); | 185 iframe_id.c_str(), url.spec().c_str()); |
| 358 WindowedNotificationObserver load_observer( | 186 WindowedNotificationObserver load_observer( |
| 359 NOTIFICATION_NAV_ENTRY_COMMITTED, | 187 NOTIFICATION_NAV_ENTRY_COMMITTED, |
| 360 Source<NavigationController>( | 188 Source<NavigationController>( |
| 361 &window->web_contents()->GetController())); | 189 &window->web_contents()->GetController())); |
| 362 bool result = ExecuteScript(window->web_contents(), script); | 190 bool result = ExecuteScript(window->web_contents(), script); |
| 363 load_observer.Wait(); | 191 load_observer.Wait(); |
| 364 return result; | 192 return result; |
| 365 } | 193 } |
| 366 | 194 |
| 367 void NavigateToURLContentInitiated(Shell* window, | |
| 368 const GURL& url, | |
| 369 bool should_replace_current_entry, | |
| 370 bool should_wait_for_navigation) { | |
| 371 std::string script; | |
| 372 if (should_replace_current_entry) | |
| 373 script = base::StringPrintf("location.replace('%s')", url.spec().c_str()); | |
| 374 else | |
| 375 script = base::StringPrintf("location.href = '%s'", url.spec().c_str()); | |
| 376 TestNavigationObserver load_observer(shell()->web_contents(), 1); | |
| 377 bool result = ExecuteScript(window->web_contents(), script); | |
| 378 EXPECT_TRUE(result); | |
| 379 if (should_wait_for_navigation) | |
| 380 load_observer.Wait(); | |
| 381 } | |
| 382 | |
| 383 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { | 195 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { |
| 384 command_line->AppendSwitch(switches::kSitePerProcess); | 196 command_line->AppendSwitch(switches::kSitePerProcess); |
| 385 | 197 |
| 386 // TODO(creis): Remove this when GTK is no longer a supported platform. | 198 // TODO(creis): Remove this when GTK is no longer a supported platform. |
| 387 command_line->AppendSwitch(switches::kForceCompositingMode); | 199 command_line->AppendSwitch(switches::kForceCompositingMode); |
| 388 } | 200 } |
| 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_; | |
| 409 }; | 201 }; |
| 410 | 202 |
| 411 // Ensure that we can complete a cross-process subframe navigation. | 203 // Ensure that we can complete a cross-process subframe navigation. |
| 412 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) { | 204 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossSiteIframe) { |
| 413 host_resolver()->AddRule("*", "127.0.0.1"); | 205 host_resolver()->AddRule("*", "127.0.0.1"); |
| 414 ASSERT_TRUE(test_server()->Start()); | 206 ASSERT_TRUE(test_server()->Start()); |
| 415 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); | 207 GURL main_url(test_server()->GetURL("files/site_per_process_main.html")); |
| 416 NavigateToURL(shell(), main_url); | 208 NavigateToURL(shell(), main_url); |
| 417 | 209 |
| 418 StartFrameAtDataURL(); | 210 StartFrameAtDataURL(); |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 GURL server_redirect_http_url(test_server()->GetURL( | 509 GURL server_redirect_http_url(test_server()->GetURL( |
| 718 "server-redirect?" + client_redirect_http_url.spec())); | 510 "server-redirect?" + client_redirect_http_url.spec())); |
| 719 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test")); | 511 EXPECT_TRUE(NavigateIframeToURL(shell(), server_redirect_http_url, "test")); |
| 720 | 512 |
| 721 // DidFailProvisionalLoad when navigating to client_redirect_http_url. | 513 // DidFailProvisionalLoad when navigating to client_redirect_http_url. |
| 722 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); | 514 EXPECT_EQ(observer.navigation_url(), client_redirect_http_url); |
| 723 EXPECT_FALSE(observer.navigation_succeeded()); | 515 EXPECT_FALSE(observer.navigation_succeeded()); |
| 724 } | 516 } |
| 725 } | 517 } |
| 726 | 518 |
| 727 // Tests that the |should_replace_current_entry| flag persists correctly across | |
| 728 // request transfers that began with a cross-process navigation. | |
| 729 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 730 ReplaceEntryCrossProcessThenTransfer) { | |
| 731 const NavigationController& controller = | |
| 732 shell()->web_contents()->GetController(); | |
| 733 host_resolver()->AddRule("*", "127.0.0.1"); | |
| 734 ASSERT_TRUE(test_server()->Start()); | |
| 735 | |
| 736 // These must all stay in scope with replace_host. | |
| 737 GURL::Replacements replace_host; | |
| 738 std::string a_com("A.com"); | |
| 739 std::string b_com("B.com"); | |
| 740 | |
| 741 // Navigate to a starting URL, so there is a history entry to replace. | |
| 742 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); | |
| 743 NavigateToURL(shell(), url1); | |
| 744 | |
| 745 // Force all future navigations to transfer. Note that this includes same-site | |
| 746 // navigiations which may cause double process swaps (via OpenURL and then via | |
| 747 // transfer). This test intentionally exercises that case. | |
| 748 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); | |
| 749 | |
| 750 // Navigate to a page on A.com with entry replacement. This navigation is | |
| 751 // cross-site, so the renderer will send it to the browser via OpenURL to give | |
| 752 // to a new process. It will then be transferred into yet another process due | |
| 753 // to the call above. | |
| 754 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); | |
| 755 replace_host.SetHostStr(a_com); | |
| 756 url2 = url2.ReplaceComponents(replace_host); | |
| 757 // Used to make sure the request for url2 succeeds, and there was only one of | |
| 758 // them. | |
| 759 tracking_delegate().SetTrackedURL(url2); | |
| 760 NavigateToURLContentInitiated(shell(), url2, true, true); | |
| 761 | |
| 762 // There should be one history entry. url2 should have replaced url1. | |
| 763 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | |
| 764 EXPECT_EQ(1, controller.GetEntryCount()); | |
| 765 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | |
| 766 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | |
| 767 // Make sure the request succeeded. | |
| 768 EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); | |
| 769 | |
| 770 // Now navigate as before to a page on B.com, but normally (without | |
| 771 // replacement). This will still perform a double process-swap as above, via | |
| 772 // OpenURL and then transfer. | |
| 773 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); | |
| 774 replace_host.SetHostStr(b_com); | |
| 775 url3 = url3.ReplaceComponents(replace_host); | |
| 776 // Used to make sure the request for url3 succeeds, and there was only one of | |
| 777 // them. | |
| 778 tracking_delegate().SetTrackedURL(url3); | |
| 779 NavigateToURLContentInitiated(shell(), url3, false, true); | |
| 780 | |
| 781 // There should be two history entries. url2 should have replaced url1. url2 | |
| 782 // should not have replaced url3. | |
| 783 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | |
| 784 EXPECT_EQ(2, controller.GetEntryCount()); | |
| 785 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | |
| 786 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | |
| 787 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); | |
| 788 | |
| 789 // Make sure the request succeeded. | |
| 790 EXPECT_TRUE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); | |
| 791 } | |
| 792 | |
| 793 // Tests that the |should_replace_current_entry| flag persists correctly across | |
| 794 // request transfers that began with a content-initiated in-process | |
| 795 // navigation. This test is the same as the test above, except transfering from | |
| 796 // in-process. | |
| 797 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 798 ReplaceEntryInProcessThenTranfers) { | |
| 799 const NavigationController& controller = | |
| 800 shell()->web_contents()->GetController(); | |
| 801 ASSERT_TRUE(test_server()->Start()); | |
| 802 | |
| 803 // Navigate to a starting URL, so there is a history entry to replace. | |
| 804 GURL url = test_server()->GetURL("files/site_isolation/blank.html?1"); | |
| 805 NavigateToURL(shell(), url); | |
| 806 | |
| 807 // Force all future navigations to transfer. Note that this includes same-site | |
| 808 // navigiations which may cause double process swaps (via OpenURL and then via | |
| 809 // transfer). All navigations in this test are same-site, so it only swaps | |
| 810 // processes via request transfer. | |
| 811 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); | |
| 812 | |
| 813 // Navigate in-process with entry replacement. It will then be transferred | |
| 814 // into a new one due to the call above. | |
| 815 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); | |
| 816 NavigateToURLContentInitiated(shell(), url2, true, true); | |
| 817 | |
| 818 // There should be one history entry. url2 should have replaced url1. | |
| 819 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | |
| 820 EXPECT_EQ(1, controller.GetEntryCount()); | |
| 821 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | |
| 822 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | |
| 823 | |
| 824 // Now navigate as before, but without replacement. | |
| 825 GURL url3 = test_server()->GetURL("files/site_isolation/blank.html?3"); | |
| 826 NavigateToURLContentInitiated(shell(), url3, false, true); | |
| 827 | |
| 828 // There should be two history entries. url2 should have replaced url1. url2 | |
| 829 // should not have replaced url3. | |
| 830 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | |
| 831 EXPECT_EQ(2, controller.GetEntryCount()); | |
| 832 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | |
| 833 EXPECT_EQ(url2, controller.GetEntryAtIndex(0)->GetURL()); | |
| 834 EXPECT_EQ(url3, controller.GetEntryAtIndex(1)->GetURL()); | |
| 835 } | |
| 836 | |
| 837 // Tests that the |should_replace_current_entry| flag persists correctly across | |
| 838 // request transfers that cross processes twice from renderer policy. | |
| 839 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, | |
| 840 ReplaceEntryCrossProcessTwice) { | |
| 841 const NavigationController& controller = | |
| 842 shell()->web_contents()->GetController(); | |
| 843 host_resolver()->AddRule("*", "127.0.0.1"); | |
| 844 ASSERT_TRUE(test_server()->Start()); | |
| 845 | |
| 846 // These must all stay in scope with replace_host. | |
| 847 GURL::Replacements replace_host; | |
| 848 std::string a_com("A.com"); | |
| 849 std::string b_com("B.com"); | |
| 850 | |
| 851 // Navigate to a starting URL, so there is a history entry to replace. | |
| 852 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); | |
| 853 NavigateToURL(shell(), url1); | |
| 854 | |
| 855 // Navigate to a page on A.com which redirects to B.com with entry | |
| 856 // replacement. This will switch processes via OpenURL twice. First to A.com, | |
| 857 // and second in response to the server redirect to B.com. The second swap is | |
| 858 // also renderer-initiated via OpenURL because decidePolicyForNavigation is | |
| 859 // currently applied on redirects. | |
| 860 GURL url2b = test_server()->GetURL("files/site_isolation/blank.html?2"); | |
| 861 replace_host.SetHostStr(b_com); | |
| 862 url2b = url2b.ReplaceComponents(replace_host); | |
| 863 GURL url2a = test_server()->GetURL( | |
| 864 "server-redirect?" + net::EscapeQueryParamValue(url2b.spec(), false)); | |
| 865 replace_host.SetHostStr(a_com); | |
| 866 url2a = url2a.ReplaceComponents(replace_host); | |
| 867 NavigateToURLContentInitiated(shell(), url2a, true, true); | |
| 868 | |
| 869 // There should be one history entry. url2b should have replaced url1. | |
| 870 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | |
| 871 EXPECT_EQ(1, controller.GetEntryCount()); | |
| 872 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | |
| 873 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); | |
| 874 | |
| 875 // Now repeat without replacement. | |
| 876 GURL url3b = test_server()->GetURL("files/site_isolation/blank.html?3"); | |
| 877 replace_host.SetHostStr(b_com); | |
| 878 url3b = url3b.ReplaceComponents(replace_host); | |
| 879 GURL url3a = test_server()->GetURL( | |
| 880 "server-redirect?" + net::EscapeQueryParamValue(url3b.spec(), false)); | |
| 881 replace_host.SetHostStr(a_com); | |
| 882 url3a = url3a.ReplaceComponents(replace_host); | |
| 883 NavigateToURLContentInitiated(shell(), url3a, false, true); | |
| 884 | |
| 885 // There should be two history entries. url2b should have replaced url1. url2b | |
| 886 // should not have replaced url3b. | |
| 887 EXPECT_TRUE(controller.GetPendingEntry() == NULL); | |
| 888 EXPECT_EQ(2, controller.GetEntryCount()); | |
| 889 EXPECT_EQ(1, controller.GetCurrentEntryIndex()); | |
| 890 EXPECT_EQ(url2b, controller.GetEntryAtIndex(0)->GetURL()); | |
| 891 EXPECT_EQ(url3b, controller.GetEntryAtIndex(1)->GetURL()); | |
| 892 } | |
| 893 | |
| 894 // Tests that the request is destroyed when a cross process navigation is | |
| 895 // cancelled. | |
| 896 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, NoLeakOnCrossSiteCancel) { | |
| 897 const NavigationController& controller = | |
| 898 shell()->web_contents()->GetController(); | |
| 899 host_resolver()->AddRule("*", "127.0.0.1"); | |
| 900 ASSERT_TRUE(test_server()->Start()); | |
| 901 | |
| 902 // These must all stay in scope with replace_host. | |
| 903 GURL::Replacements replace_host; | |
| 904 std::string a_com("A.com"); | |
| 905 std::string b_com("B.com"); | |
| 906 | |
| 907 // Navigate to a starting URL, so there is a history entry to replace. | |
| 908 GURL url1 = test_server()->GetURL("files/site_isolation/blank.html?1"); | |
| 909 NavigateToURL(shell(), url1); | |
| 910 | |
| 911 // Force all future navigations to transfer. | |
| 912 ShellContentBrowserClient::SetSwapProcessesForRedirect(true); | |
| 913 | |
| 914 NoTransferRequestDelegate no_transfer_request_delegate; | |
| 915 WebContentsDelegate* old_delegate = shell()->web_contents()->GetDelegate(); | |
| 916 shell()->web_contents()->SetDelegate(&no_transfer_request_delegate); | |
| 917 | |
| 918 // Navigate to a page on A.com with entry replacement. This navigation is | |
| 919 // cross-site, so the renderer will send it to the browser via OpenURL to give | |
| 920 // to a new process. It will then be transferred into yet another process due | |
| 921 // to the call above. | |
| 922 GURL url2 = test_server()->GetURL("files/site_isolation/blank.html?2"); | |
| 923 replace_host.SetHostStr(a_com); | |
| 924 url2 = url2.ReplaceComponents(replace_host); | |
| 925 // Used to make sure the second request is cancelled, and there is only one | |
| 926 // request for url2. | |
| 927 tracking_delegate().SetTrackedURL(url2); | |
| 928 | |
| 929 // Don't wait for the navigation to complete, since that never happens in | |
| 930 // this case. | |
| 931 NavigateToURLContentInitiated(shell(), url2, false, false); | |
| 932 | |
| 933 // There should be one history entry, with url1. | |
| 934 EXPECT_EQ(1, controller.GetEntryCount()); | |
| 935 EXPECT_EQ(0, controller.GetCurrentEntryIndex()); | |
| 936 EXPECT_EQ(url1, controller.GetEntryAtIndex(0)->GetURL()); | |
| 937 | |
| 938 // Make sure the request for url2 did not complete. | |
| 939 EXPECT_FALSE(tracking_delegate().WaitForTrackedURLAndGetCompleted()); | |
| 940 | |
| 941 shell()->web_contents()->SetDelegate(old_delegate); | |
| 942 } | |
| 943 | |
| 944 } // namespace content | 519 } // namespace content |
| OLD | NEW |