1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/bind.h" 6#include "base/command_line.h" 7#include "content/browser/loader/cross_site_resource_handler.h" 8#include "content/browser/loader/resource_dispatcher_host_impl.h" 9#include "content/browser/loader/resource_request_info_impl.h" 10#include "content/browser/transition_request_manager.h" 11#include "content/browser/web_contents/web_contents_impl.h" 12#include "content/public/browser/web_contents_observer.h" 13#include "content/public/common/content_switches.h" 14#include "content/public/test/browser_test_utils.h" 15#include "content/public/test/content_browser_test.h" 16#include "content/public/test/content_browser_test_utils.h" 17#include "content/public/test/test_utils.h" 18#include "content/shell/browser/shell.h" 19#include "content/shell/browser/shell_resource_dispatcher_host_delegate.h" 20#include "net/test/embedded_test_server/embedded_test_server.h" 21#include "net/url_request/url_request.h" 22 23namespace content { 24 25class TransitionBrowserTest : public ContentBrowserTest { 26 public: 27 TransitionBrowserTest() {} 28 29 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 30 command_line->AppendSwitch( 31 switches::kEnableExperimentalWebPlatformFeatures); 32 } 33 34 private: 35 DISALLOW_COPY_AND_ASSIGN(TransitionBrowserTest); 36}; 37 38class TransitionBrowserTestObserver 39 : public WebContentsObserver, 40 public ShellResourceDispatcherHostDelegate { 41 public: 42 TransitionBrowserTestObserver(WebContents* web_contents) 43 : WebContentsObserver(web_contents), 44 request_(NULL), 45 did_defer_response_(false), 46 is_transition_request_(false) { 47 } 48 49 virtual void RequestBeginning( 50 net::URLRequest* request, 51 ResourceContext* resource_context, 52 AppCacheService* appcache_service, 53 ResourceType resource_type, 54 ScopedVector<ResourceThrottle>* throttles) OVERRIDE { 55 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 56 ShellResourceDispatcherHostDelegate::RequestBeginning(request, 57 resource_context, 58 appcache_service, 59 resource_type, 60 throttles); 61 request_ = request; 62 63 ResourceRequestInfoImpl* info = 64 ResourceRequestInfoImpl::ForRequest(request_); 65 66 if (is_transition_request_) { 67 TransitionRequestManager::GetInstance()->AddPendingTransitionRequestData( 68 info->GetChildID(), info->GetRenderFrameID(), "*", "", ""); 69 } 70 } 71 72 virtual void OnResponseStarted( 73 net::URLRequest* request, 74 ResourceContext* resource_context, 75 ResourceResponse* response, 76 IPC::Sender* sender) OVERRIDE { 77 ResourceRequestInfoImpl* info = 78 ResourceRequestInfoImpl::ForRequest(request_); 79 80 did_defer_response_ = info->cross_site_handler()->did_defer_for_testing(); 81 } 82 83 void set_pending_transition_request(bool is_transition_request) { 84 is_transition_request_ = is_transition_request; 85 } 86 87 bool did_defer_response() const { return did_defer_response_; } 88 89 private: 90 net::URLRequest* request_; 91 bool did_defer_response_; 92 bool is_transition_request_; 93}; 94 95// This tests that normal navigations don't defer at first response. 96IN_PROC_BROWSER_TEST_F(TransitionBrowserTest, 97 NormalNavigationNotDeferred) { 98 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 99 scoped_ptr<TransitionBrowserTestObserver> observer( 100 new TransitionBrowserTestObserver(shell()->web_contents())); 101 102 ResourceDispatcherHost::Get()->SetDelegate(observer.get()); 103 104 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); 105 106 EXPECT_FALSE(observer->did_defer_response()); 107} 108 109// This tests that when a navigation transition is detected, the response is 110// deferred. 111IN_PROC_BROWSER_TEST_F(TransitionBrowserTest, 112 TransitionNavigationIsDeferred) { 113 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 114 scoped_ptr<TransitionBrowserTestObserver> observer( 115 new TransitionBrowserTestObserver(shell()->web_contents())); 116 117 ResourceDispatcherHost::Get()->SetDelegate(observer.get()); 118 observer->set_pending_transition_request(true); 119 120 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); 121 122 EXPECT_TRUE(observer->did_defer_response()); 123} 124 125// This tests that the renderer is reused between the outgoing and transition. 126IN_PROC_BROWSER_TEST_F(TransitionBrowserTest, 127 TransitionNavigationSharesRenderer) { 128 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady()); 129 130 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")); 131 132 int outgoing_process_id = 133 shell()->web_contents()->GetRenderProcessHost()->GetID(); 134 135 WebContents::CreateParams create_params( 136 shell()->web_contents()->GetBrowserContext(), 137 shell()->web_contents()->GetSiteInstance()); 138 scoped_ptr<WebContents> transition_web_contents( 139 WebContents::Create(create_params)); 140 141 GURL about_blank(url::kAboutBlankURL); 142 NavigationController::LoadURLParams params(about_blank); 143 transition_web_contents->GetController().LoadURLWithParams(params); 144 transition_web_contents->Focus(); 145 146 WaitForLoadStop(transition_web_contents.get()); 147 148 int transition_process_id = 149 transition_web_contents->GetRenderProcessHost()->GetID(); 150 151 EXPECT_EQ(outgoing_process_id, transition_process_id); 152} 153 154} // namespace content 155