Pass ResourceResponse and StreamHandle in CommitNavigation.
[chromium-blink-merge.git] / content / browser / frame_host / navigator_impl_unittest.cc
blobe9b5452b3c08c6f8fb713cd639d6725a4fc2bc95
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.
5 #include "base/command_line.h"
6 #include "base/test/histogram_tester.h"
7 #include "base/time/time.h"
8 #include "content/browser/frame_host/navigation_controller_impl.h"
9 #include "content/browser/frame_host/navigation_entry_impl.h"
10 #include "content/browser/frame_host/navigation_request.h"
11 #include "content/browser/frame_host/navigation_request_info.h"
12 #include "content/browser/frame_host/navigator.h"
13 #include "content/browser/frame_host/navigator_impl.h"
14 #include "content/browser/frame_host/render_frame_host_manager.h"
15 #include "content/browser/site_instance_impl.h"
16 #include "content/common/navigation_params.h"
17 #include "content/public/browser/stream_handle.h"
18 #include "content/public/common/content_switches.h"
19 #include "content/public/common/url_constants.h"
20 #include "content/public/common/url_utils.h"
21 #include "content/test/test_render_frame_host.h"
22 #include "content/test/test_web_contents.h"
23 #include "net/base/load_flags.h"
24 #include "ui/base/page_transition_types.h"
26 namespace content {
28 namespace {
30 // Mocked out stream handle to commit the navigation with.
31 class TestStreamHandle : public StreamHandle {
32 public:
33 TestStreamHandle() : url_("test:stream") {}
35 virtual const GURL& GetURL() override {
36 return url_;
39 virtual const GURL& GetOriginalURL() override {
40 NOTREACHED();
41 return original_url_;
44 virtual const std::string& GetMimeType() override {
45 NOTREACHED();
46 return mime_type_;
49 virtual scoped_refptr<net::HttpResponseHeaders>
50 GetResponseHeaders() override {
51 NOTREACHED();
52 return NULL;
55 virtual void AddCloseListener(const base::Closure& callback) override {
56 NOTREACHED();
59 private:
60 GURL url_;
61 GURL original_url_;
62 std::string mime_type_;
64 DISALLOW_COPY_AND_ASSIGN(TestStreamHandle);
69 class NavigatorTest
70 : public RenderViewHostImplTestHarness {
71 public:
72 NavigationRequest* GetNavigationRequestForFrameTreeNode(
73 FrameTreeNode* frame_tree_node) const {
74 NavigatorImpl* navigator =
75 static_cast<NavigatorImpl*>(frame_tree_node->navigator());
76 return navigator->navigation_request_map_.get(
77 frame_tree_node->frame_tree_node_id());
80 void EnableBrowserSideNavigation() {
81 CommandLine::ForCurrentProcess()->AppendSwitch(
82 switches::kEnableBrowserSideNavigation);
85 void SendRequestNavigation(FrameTreeNode* node,
86 const GURL& url) {
87 SendRequestNavigationWithParameters(
88 node, url, Referrer(), ui::PAGE_TRANSITION_LINK,
89 NavigationController::NO_RELOAD);
92 void SendRequestNavigationWithParameters(
93 FrameTreeNode* node,
94 const GURL& url,
95 const Referrer& referrer,
96 ui::PageTransition transition_type,
97 NavigationController::ReloadType reload_type) {
98 scoped_ptr<NavigationEntryImpl> entry(
99 NavigationEntryImpl::FromNavigationEntry(
100 NavigationController::CreateNavigationEntry(
101 url,
102 referrer,
103 transition_type,
104 false,
105 std::string(),
106 controller().GetBrowserContext())));
107 static_cast<NavigatorImpl*>(node->navigator())->RequestNavigation(
108 node, *entry, reload_type, base::TimeTicks::Now());
112 // PlzNavigate: Test that a proper NavigationRequest is created by
113 // BeginNavigation.
114 // Note that all PlzNavigate methods on the browser side require the use of the
115 // flag kEnableBrowserSideNavigation.
116 TEST_F(NavigatorTest, BrowserSideNavigationBeginNavigation) {
117 const GURL kUrl1("http://www.google.com/");
118 const GURL kUrl2("http://www.chromium.org/");
119 const GURL kUrl3("http://www.gmail.com/");
121 contents()->NavigateAndCommit(kUrl1);
123 EnableBrowserSideNavigation();
125 // Add a subframe.
126 TestRenderFrameHost* subframe_rfh = static_cast<TestRenderFrameHost*>(
127 contents()->GetFrameTree()->AddFrame(
128 contents()->GetFrameTree()->root(), 14, "Child"));
130 FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node();
131 SendRequestNavigation(subframe_rfh->frame_tree_node(), kUrl2);
132 // There is no previous renderer in the subframe, so BeginNavigation is
133 // handled already.
134 NavigationRequest* subframe_request =
135 GetNavigationRequestForFrameTreeNode(subframe_node);
136 ASSERT_TRUE(subframe_request);
137 EXPECT_EQ(kUrl2, subframe_request->common_params().url);
138 // First party for cookies url should be that of the main frame.
139 EXPECT_EQ(kUrl1, subframe_request->info_for_test()->first_party_for_cookies);
140 EXPECT_FALSE(subframe_request->info_for_test()->is_main_frame);
141 EXPECT_TRUE(subframe_request->info_for_test()->parent_is_main_frame);
143 FrameTreeNode* main_frame_node =
144 contents()->GetMainFrame()->frame_tree_node();
145 SendRequestNavigation(main_frame_node, kUrl3);
146 // Simulate a BeginNavigation IPC on the main frame.
147 contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl3);
148 NavigationRequest* main_request =
149 GetNavigationRequestForFrameTreeNode(main_frame_node);
150 ASSERT_TRUE(main_request);
151 EXPECT_EQ(kUrl3, main_request->common_params().url);
152 EXPECT_EQ(kUrl3, main_request->info_for_test()->first_party_for_cookies);
153 EXPECT_TRUE(main_request->info_for_test()->is_main_frame);
154 EXPECT_FALSE(main_request->info_for_test()->parent_is_main_frame);
157 // PlzNavigate: Test that RequestNavigation creates a NavigationRequest and that
158 // RenderFrameHost is not modified when the navigation commits.
159 TEST_F(NavigatorTest, BrowserSideNavigationRequestNavigationNoLiveRenderer) {
160 const GURL kUrl("http://www.google.com/");
162 EnableBrowserSideNavigation();
163 EXPECT_FALSE(main_test_rfh()->render_view_host()->IsRenderViewLive());
164 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
165 SendRequestNavigation(node, kUrl);
166 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
167 // A NavigationRequest should have been generated.
168 EXPECT_TRUE(main_request != NULL);
169 RenderFrameHostImpl* rfh = main_test_rfh();
171 // Now commit the same url.
172 scoped_refptr<ResourceResponse> response(new ResourceResponse);
173 node->navigator()->CommitNavigation(
174 node, response.get(), scoped_ptr<StreamHandle>(new TestStreamHandle));
175 main_request = GetNavigationRequestForFrameTreeNode(node);
177 // The main RFH should not have been changed, and the renderer should have
178 // been initialized.
179 EXPECT_EQ(rfh, main_test_rfh());
180 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive());
181 EXPECT_TRUE(main_test_rfh()->render_view_host()->IsRenderViewLive());
184 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross
185 // site navigation.
186 TEST_F(NavigatorTest, BrowserSideNavigationCrossSiteNavigation) {
187 const GURL kUrl1("http://www.chromium.org/");
188 const GURL kUrl2("http://www.google.com/");
190 contents()->NavigateAndCommit(kUrl1);
191 RenderFrameHostImpl* rfh = main_test_rfh();
192 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh->rfh_state());
193 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
195 EnableBrowserSideNavigation();
197 // Navigate to a different site.
198 SendRequestNavigation(node, kUrl2);
199 main_test_rfh()->SendBeginNavigationWithURL(kUrl2);
200 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node);
201 ASSERT_TRUE(main_request);
203 scoped_refptr<ResourceResponse> response(new ResourceResponse);
204 node->navigator()->CommitNavigation(
205 node, response.get(), scoped_ptr<StreamHandle>(new TestStreamHandle));
206 RenderFrameHostImpl* pending_rfh =
207 node->render_manager()->pending_frame_host();
208 ASSERT_TRUE(pending_rfh);
209 EXPECT_NE(pending_rfh, rfh);
210 EXPECT_TRUE(pending_rfh->IsRenderFrameLive());
211 EXPECT_TRUE(pending_rfh->render_view_host()->IsRenderViewLive());
214 // PlzNavigate: Test that a navigation is cancelled if another request has been
215 // issued in the meantime.
216 TEST_F(NavigatorTest, BrowserSideNavigationReplacePendingNavigation) {
217 const GURL kUrl0("http://www.wikipedia.org/");
218 const GURL kUrl0_site = SiteInstance::GetSiteForURL(browser_context(), kUrl0);
219 const GURL kUrl1("http://www.chromium.org/");
220 const GURL kUrl2("http://www.google.com/");
221 const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2);
223 // Initialization.
224 contents()->NavigateAndCommit(kUrl0);
225 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
226 EnableBrowserSideNavigation();
227 EXPECT_EQ(kUrl0_site, main_test_rfh()->GetSiteInstance()->GetSiteURL());
229 // Request navigation to the 1st URL.
230 SendRequestNavigation(node, kUrl1);
231 main_test_rfh()->SendBeginNavigationWithURL(kUrl1);
232 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node);
233 ASSERT_TRUE(request1);
234 EXPECT_EQ(kUrl1, request1->common_params().url);
236 // Request navigation to the 2nd URL; the NavigationRequest must have been
237 // replaced by a new one with a different URL.
238 SendRequestNavigation(node, kUrl2);
239 main_test_rfh()->SendBeginNavigationWithURL(kUrl2);
240 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node);
241 ASSERT_TRUE(request2);
242 EXPECT_EQ(kUrl2, request2->common_params().url);
244 // Confirm that the commit corresonds to the new request.
245 scoped_refptr<ResourceResponse> response(new ResourceResponse);
246 node->navigator()->CommitNavigation(
247 node, response.get(), scoped_ptr<StreamHandle>(new TestStreamHandle));
248 RenderFrameHostImpl* pending_rfh =
249 node->render_manager()->pending_frame_host();
250 ASSERT_TRUE(pending_rfh);
251 EXPECT_EQ(kUrl2_site, pending_rfh->GetSiteInstance()->GetSiteURL());
254 // PlzNavigate: Tests that the navigation histograms are correctly tracked both
255 // when PlzNavigate is enabled and disabled, and also ignores in-tab renderer
256 // initiated navigation for the non-enabled case.
257 // Note: the related histogram, Navigation.TimeToURLJobStart, cannot be tracked
258 // by this test as the IO thread is not running.
259 TEST_F(NavigatorTest, BrowserSideNavigationHistogramTest) {
260 const GURL kUrl0("http://www.google.com/");
261 const GURL kUrl1("http://www.chromium.org/");
262 base::HistogramTester histo_tester;
264 // Performs a "normal" non-PlzNavigate navigation
265 contents()->NavigateAndCommit(kUrl0);
266 histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 1);
268 // Performs an in-tab renderer initiated navigation
269 int32 new_page_id = 1 + contents()->GetMaxPageIDForSiteInstance(
270 main_test_rfh()->GetSiteInstance());
271 main_test_rfh()->SendNavigate(new_page_id, kUrl0);
272 histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 1);
274 // Performs a PlzNavigate navigation
275 EnableBrowserSideNavigation();
276 contents()->NavigateAndCommit(kUrl1);
277 histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 2);
280 // PlzNavigate: Test that a reload navigation is properly signaled to the
281 // renderer when the navigation can commit.
282 TEST_F(NavigatorTest, BrowserSideNavigationReload) {
283 const GURL kUrl("http://www.google.com/");
284 contents()->NavigateAndCommit(kUrl);
286 EnableBrowserSideNavigation();
287 FrameTreeNode* node = main_test_rfh()->frame_tree_node();
288 SendRequestNavigationWithParameters(
289 node, kUrl, Referrer(), ui::PAGE_TRANSITION_LINK,
290 NavigationController::RELOAD);
291 contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl);
292 // A NavigationRequest should have been generated.
293 NavigationRequest* main_request =
294 GetNavigationRequestForFrameTreeNode(node);
295 ASSERT_TRUE(main_request != NULL);
296 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD,
297 main_request->common_params().navigation_type);
298 int page_id = contents()->GetMaxPageIDForSiteInstance(
299 main_test_rfh()->GetSiteInstance()) + 1;
300 main_test_rfh()->SendNavigate(page_id, kUrl);
302 // Now do a shift+reload.
303 SendRequestNavigationWithParameters(
304 node, kUrl, Referrer(), ui::PAGE_TRANSITION_LINK,
305 NavigationController::RELOAD_IGNORING_CACHE);
306 contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl);
307 // A NavigationRequest should have been generated.
308 main_request = GetNavigationRequestForFrameTreeNode(node);
309 ASSERT_TRUE(main_request != NULL);
310 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE,
311 main_request->common_params().navigation_type);
314 } // namespace content