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.
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"
25 class TransitionBrowserTest
: public ContentBrowserTest
{
27 TransitionBrowserTest() {}
29 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
30 command_line
->AppendSwitch(
31 switches::kEnableExperimentalWebPlatformFeatures
);
35 DISALLOW_COPY_AND_ASSIGN(TransitionBrowserTest
);
38 class TransitionBrowserTestObserver
39 : public WebContentsObserver
,
40 public ShellResourceDispatcherHostDelegate
{
42 TransitionBrowserTestObserver(WebContents
* web_contents
)
43 : WebContentsObserver(web_contents
),
45 did_defer_response_(false),
46 is_transition_request_(false),
47 did_clear_data_(false) {
50 void RequestBeginning(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
,
63 ResourceRequestInfoImpl
* info
=
64 ResourceRequestInfoImpl::ForRequest(request_
);
66 if (is_transition_request_
) {
67 TransitionRequestManager::GetInstance(
68 )->AddPendingTransitionRequestDataForTesting(
69 info
->GetChildID(), info
->GetRenderFrameID());
73 void OnResponseStarted(net::URLRequest
* request
,
74 ResourceContext
* resource_context
,
75 ResourceResponse
* response
,
76 IPC::Sender
* sender
) override
{
77 ResourceRequestInfoImpl
* info
=
78 ResourceRequestInfoImpl::ForRequest(request_
);
80 did_defer_response_
= info
->cross_site_handler()->did_defer_for_testing();
83 void RequestComplete(net::URLRequest
* url_request
) override
{
84 if (is_transition_request_
) {
85 ResourceRequestInfoImpl
* info
=
86 ResourceRequestInfoImpl::ForRequest(request_
);
87 TransitionLayerData transition_data
;
88 did_clear_data_
= !TransitionRequestManager::GetInstance(
89 )->GetPendingTransitionRequest(info
->GetChildID(),
90 info
->GetRenderFrameID(),
96 void set_pending_transition_request(bool is_transition_request
) {
97 is_transition_request_
= is_transition_request
;
100 bool did_defer_response() const { return did_defer_response_
; }
101 bool did_clear_data() const { return did_clear_data_
; }
104 net::URLRequest
* request_
;
105 bool did_defer_response_
;
106 bool is_transition_request_
;
107 bool did_clear_data_
;
110 // This tests that normal navigations don't defer at first response.
111 IN_PROC_BROWSER_TEST_F(TransitionBrowserTest
,
112 NormalNavigationNotDeferred
) {
113 // This test shouldn't run in --site-per-process mode, where normal
114 // navigations are also deferred.
115 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
116 switches::kSitePerProcess
))
119 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
120 scoped_ptr
<TransitionBrowserTestObserver
> observer(
121 new TransitionBrowserTestObserver(shell()->web_contents()));
123 ResourceDispatcherHost::Get()->SetDelegate(observer
.get());
125 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
127 EXPECT_FALSE(observer
->did_defer_response());
130 // This tests that when a navigation transition is detected, the response is
132 IN_PROC_BROWSER_TEST_F(TransitionBrowserTest
,
133 TransitionNavigationIsDeferred
) {
134 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
135 scoped_ptr
<TransitionBrowserTestObserver
> observer(
136 new TransitionBrowserTestObserver(shell()->web_contents()));
138 ResourceDispatcherHost::Get()->SetDelegate(observer
.get());
139 observer
->set_pending_transition_request(true);
141 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
143 EXPECT_TRUE(observer
->did_defer_response());
146 // This tests that the renderer is reused between the outgoing and transition.
147 IN_PROC_BROWSER_TEST_F(TransitionBrowserTest
,
148 TransitionNavigationSharesRenderer
) {
149 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
151 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
153 int outgoing_process_id
=
154 shell()->web_contents()->GetRenderProcessHost()->GetID();
156 WebContents::CreateParams
create_params(
157 shell()->web_contents()->GetBrowserContext(),
158 shell()->web_contents()->GetSiteInstance());
159 scoped_ptr
<WebContents
> transition_web_contents(
160 WebContents::Create(create_params
));
162 GURL
about_blank(url::kAboutBlankURL
);
163 NavigationController::LoadURLParams
params(about_blank
);
164 transition_web_contents
->GetController().LoadURLWithParams(params
);
165 transition_web_contents
->Focus();
167 WaitForLoadStop(transition_web_contents
.get());
169 int transition_process_id
=
170 transition_web_contents
->GetRenderProcessHost()->GetID();
172 EXPECT_EQ(outgoing_process_id
, transition_process_id
);
175 // This tests that the transition data is cleared after the transition.
176 IN_PROC_BROWSER_TEST_F(TransitionBrowserTest
,
177 TransitionNavigationDataIsCleared
) {
178 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
179 scoped_ptr
<TransitionBrowserTestObserver
> observer(
180 new TransitionBrowserTestObserver(shell()->web_contents()));
182 ResourceDispatcherHost::Get()->SetDelegate(observer
.get());
183 observer
->set_pending_transition_request(true);
185 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html"));
186 WaitForLoadStop(shell()->web_contents());
188 EXPECT_TRUE(observer
->did_clear_data());
191 } // namespace content