OLD | NEW |
---|---|
(Empty) | |
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/command_line.h" | |
6 #include "base/test/histogram_tester.h" | |
7 #include "base/time/time.h" | |
8 #include "content/browser/frame_host/navigation_before_commit_info.h" | |
9 #include "content/browser/frame_host/navigation_controller_impl.h" | |
10 #include "content/browser/frame_host/navigation_entry_impl.h" | |
11 #include "content/browser/frame_host/navigation_request.h" | |
12 #include "content/browser/frame_host/navigation_request_info.h" | |
13 #include "content/browser/frame_host/navigator.h" | |
14 #include "content/browser/frame_host/navigator_impl.h" | |
15 #include "content/browser/frame_host/render_frame_host_manager.h" | |
16 #include "content/browser/site_instance_impl.h" | |
17 #include "content/common/navigation_params.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" | |
25 | |
26 namespace content { | |
27 | |
28 class NavigatorTest | |
29 : public RenderViewHostImplTestHarness { | |
30 public: | |
31 NavigationRequest* GetNavigationRequestForFrameTreeNode( | |
32 FrameTreeNode* frame_tree_node) const { | |
33 NavigatorImpl* navigator = | |
34 static_cast<NavigatorImpl*>(frame_tree_node->navigator()); | |
35 return navigator->navigation_request_map_.get( | |
36 frame_tree_node->frame_tree_node_id()); | |
37 } | |
38 | |
39 void EnableBrowserSideNavigation() { | |
40 CommandLine::ForCurrentProcess()->AppendSwitch( | |
41 switches::kEnableBrowserSideNavigation); | |
42 } | |
43 | |
44 void SendRequestNavigation(FrameTreeNode* node, | |
45 const GURL& url) { | |
46 SendRequestNavigationWithParameters( | |
47 node, url, Referrer(), ui::PAGE_TRANSITION_LINK, | |
48 NavigationController::NO_RELOAD); | |
49 } | |
50 | |
51 void SendRequestNavigationWithParameters( | |
52 FrameTreeNode* node, | |
53 const GURL& url, | |
54 const Referrer& referrer, | |
55 ui::PageTransition transition_type, | |
56 NavigationController::ReloadType reload_type) { | |
57 scoped_ptr<NavigationEntryImpl> entry( | |
58 NavigationEntryImpl::FromNavigationEntry( | |
59 NavigationController::CreateNavigationEntry( | |
60 url, | |
61 referrer, | |
62 transition_type, | |
63 false, | |
64 std::string(), | |
65 controller().GetBrowserContext()))); | |
66 static_cast<NavigatorImpl*>(node->navigator())->RequestNavigation( | |
67 node, *entry, reload_type, base::TimeTicks::Now()); | |
68 } | |
69 }; | |
70 | |
71 // PlzNavigate: Test that a proper NavigationRequest is created by | |
72 // BeginNavigation. | |
73 // Note that all PlzNavigate methods on the browser side require the use of the | |
74 // flag kEnableBrowserSideNavigation. | |
75 TEST_F(NavigatorTest, BrowserSideNavigationBeginNavigation) { | |
76 const GURL kUrl1("http://www.google.com/"); | |
77 const GURL kUrl2("http://www.chromium.org/"); | |
78 const GURL kUrl3("http://www.gmail.com/"); | |
79 const int64 kFirstNavRequestID = 1; | |
80 | |
81 EnableBrowserSideNavigation(); | |
82 contents()->NavigateAndCommit(kUrl1); | |
83 | |
84 // Add a subframe. | |
85 TestRenderFrameHost* subframe_rfh = static_cast<TestRenderFrameHost*>( | |
86 contents()->GetFrameTree()->AddFrame( | |
87 contents()->GetFrameTree()->root(), 14, "Child")); | |
88 | |
89 FrameTreeNode* subframe_node = subframe_rfh->frame_tree_node(); | |
90 SendRequestNavigation(subframe_rfh->frame_tree_node(), kUrl2); | |
91 // Simulate a BeginNavigation IPC on the subframe. | |
92 subframe_rfh->SendBeginNavigationWithURL(kUrl2); | |
93 NavigationRequest* subframe_request = | |
94 GetNavigationRequestForFrameTreeNode(subframe_node); | |
95 ASSERT_TRUE(subframe_request); | |
96 EXPECT_EQ(kUrl2, subframe_request->common_params().url); | |
97 // First party for cookies url should be that of the main frame. | |
98 EXPECT_EQ(kUrl1, subframe_request->info_for_test()->first_party_for_cookies); | |
99 EXPECT_FALSE(subframe_request->info_for_test()->is_main_frame); | |
100 EXPECT_TRUE(subframe_request->info_for_test()->parent_is_main_frame); | |
101 EXPECT_EQ(kFirstNavRequestID + 1, subframe_request->navigation_request_id()); | |
102 | |
103 FrameTreeNode* main_frame_node = | |
104 contents()->GetMainFrame()->frame_tree_node(); | |
105 SendRequestNavigation(main_frame_node, kUrl3); | |
106 // Simulate a BeginNavigation IPC on the main frame. | |
107 contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl3); | |
108 NavigationRequest* main_request = | |
109 GetNavigationRequestForFrameTreeNode(main_frame_node); | |
110 ASSERT_TRUE(main_request); | |
111 EXPECT_EQ(kUrl3, main_request->common_params().url); | |
112 EXPECT_EQ(kUrl3, main_request->info_for_test()->first_party_for_cookies); | |
113 EXPECT_TRUE(main_request->info_for_test()->is_main_frame); | |
114 EXPECT_FALSE(main_request->info_for_test()->parent_is_main_frame); | |
115 EXPECT_EQ(kFirstNavRequestID + 2, main_request->navigation_request_id()); | |
116 } | |
117 | |
118 // PlzNavigate: Test that RequestNavigation creates a NavigationRequest and that | |
119 // RenderFrameHost is not modified when the navigation commits. | |
120 TEST_F(NavigatorTest, | |
121 BrowserSideNavigationRequestNavigationNoLiveRenderer) { | |
122 const GURL kUrl("http://www.google.com/"); | |
123 | |
124 EnableBrowserSideNavigation(); | |
125 EXPECT_FALSE(main_test_rfh()->render_view_host()->IsRenderViewLive()); | |
126 FrameTreeNode* node = main_test_rfh()->frame_tree_node(); | |
127 SendRequestNavigation(node, kUrl); | |
128 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node); | |
129 // A NavigationRequest should have been generated. | |
130 EXPECT_TRUE(main_request != NULL); | |
131 RenderFrameHostImpl* rfh = main_test_rfh(); | |
132 | |
133 // Now commit the same url. | |
134 NavigationBeforeCommitInfo commit_info; | |
135 commit_info.navigation_url = kUrl; | |
136 commit_info.navigation_request_id = main_request->navigation_request_id(); | |
137 node->navigator()->CommitNavigation(node, commit_info); | |
138 main_request = GetNavigationRequestForFrameTreeNode(node); | |
139 | |
140 // The main RFH should not have been changed, and the renderer should have | |
141 // been initialized. | |
142 EXPECT_EQ(rfh, main_test_rfh()); | |
143 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive()); | |
144 EXPECT_TRUE(main_test_rfh()->render_view_host()->IsRenderViewLive()); | |
145 } | |
146 | |
147 // PlzNavigate: Test that a new RenderFrameHost is created when doing a cross | |
148 // site navigation. | |
149 TEST_F(NavigatorTest, | |
150 BrowserSideNavigationCrossSiteNavigation) { | |
151 const GURL kUrl1("http://www.chromium.org/"); | |
152 const GURL kUrl2("http://www.google.com/"); | |
153 | |
154 EnableBrowserSideNavigation(); | |
155 contents()->NavigateAndCommit(kUrl1); | |
156 RenderFrameHostImpl* rfh = main_test_rfh(); | |
157 EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh->rfh_state()); | |
158 FrameTreeNode* node = main_test_rfh()->frame_tree_node(); | |
159 | |
160 // Navigate to a different site. | |
161 SendRequestNavigation(node, kUrl2); | |
162 main_test_rfh()->SendBeginNavigationWithURL(kUrl2); | |
163 NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node); | |
164 ASSERT_TRUE(main_request); | |
165 | |
166 NavigationBeforeCommitInfo commit_info; | |
167 commit_info.navigation_url = kUrl2; | |
168 commit_info.navigation_request_id = main_request->navigation_request_id(); | |
169 node->navigator()->CommitNavigation(node, commit_info); | |
170 EXPECT_NE(main_test_rfh(), rfh); | |
171 EXPECT_TRUE(main_test_rfh()->IsRenderFrameLive()); | |
172 EXPECT_TRUE(main_test_rfh()->render_view_host()->IsRenderViewLive()); | |
173 } | |
174 | |
175 // PlzNavigate: Test that a navigation commit is ignored if another request has | |
176 // been issued in the meantime. | |
177 // TODO(carlosk): add checks to assert that the cancel call was sent to | |
178 // ResourceDispatcherHost in the IO thread by extending | |
179 // ResourceDispatcherHostDelegate (like in cross_site_transfer_browsertest.cc | |
180 // and plugin_browsertest.cc). | |
181 TEST_F(NavigatorTest, | |
182 BrowserSideNavigationIgnoreStaleNavigationCommit) { | |
183 const GURL kUrl0("http://www.wikipedia.org/"); | |
184 const GURL kUrl0_site = SiteInstance::GetSiteForURL(browser_context(), kUrl0); | |
185 const GURL kUrl1("http://www.chromium.org/"); | |
186 const GURL kUrl2("http://www.google.com/"); | |
187 const GURL kUrl2_site = SiteInstance::GetSiteForURL(browser_context(), kUrl2); | |
188 | |
189 // Initialization. | |
190 contents()->NavigateAndCommit(kUrl0); | |
191 FrameTreeNode* node = main_test_rfh()->frame_tree_node(); | |
192 EnableBrowserSideNavigation(); | |
193 EXPECT_EQ(kUrl0_site, main_test_rfh()->GetSiteInstance()->GetSiteURL()); | |
194 | |
195 // Request navigation to the 1st URL and gather data. | |
196 SendRequestNavigation(node, kUrl1); | |
197 main_test_rfh()->SendBeginNavigationWithURL(kUrl1); | |
198 NavigationRequest* request1 = GetNavigationRequestForFrameTreeNode(node); | |
199 ASSERT_TRUE(request1); | |
200 int64 request_id1 = request1->navigation_request_id(); | |
201 | |
202 // Request navigation to the 2nd URL and gather more data. | |
203 SendRequestNavigation(node, kUrl2); | |
204 main_test_rfh()->SendBeginNavigationWithURL(kUrl2); | |
205 NavigationRequest* request2 = GetNavigationRequestForFrameTreeNode(node); | |
206 ASSERT_TRUE(request2); | |
207 int64 request_id2 = request2->navigation_request_id(); | |
208 EXPECT_NE(request_id1, request_id2); | |
209 | |
210 // Confirms that a stale commit is ignored by the Navigator. | |
211 NavigationBeforeCommitInfo nbc_info; | |
212 nbc_info.navigation_url = kUrl1; | |
213 nbc_info.navigation_request_id = request_id1; | |
214 node->navigator()->CommitNavigation(node, nbc_info); | |
215 EXPECT_FALSE(node->render_manager()->pending_frame_host()); | |
clamy
2014/10/01 22:30:47
This was changed from the original unit test since
| |
216 EXPECT_EQ(kUrl0_site, main_test_rfh()->GetSiteInstance()->GetSiteURL()); | |
217 | |
218 // Confirms that a valid, request-matching commit is correctly processed. | |
219 nbc_info.navigation_url = kUrl2; | |
220 nbc_info.navigation_request_id = request_id2; | |
221 node->navigator()->CommitNavigation(node, nbc_info); | |
222 RenderFrameHostImpl* pending_rfh = | |
223 node->render_manager()->pending_frame_host(); | |
224 ASSERT_TRUE(pending_rfh); | |
225 EXPECT_EQ(kUrl2_site, pending_rfh->GetSiteInstance()->GetSiteURL()); | |
226 } | |
227 | |
228 // PlzNavigate: Tests that the navigation histograms are correctly tracked both | |
229 // when PlzNavigate is enabled and disabled, and also ignores in-tab renderer | |
230 // initiated navigation for the non-enabled case. | |
231 // Note: the related histogram, Navigation.TimeToURLJobStart, cannot be tracked | |
232 // by this test as the IO thread is not running. | |
233 TEST_F(NavigatorTest, BrowserSideNavigationHistogramTest) { | |
234 const GURL kUrl0("http://www.google.com/"); | |
235 const GURL kUrl1("http://www.chromium.org/"); | |
236 base::HistogramTester histo_tester; | |
237 | |
238 // Performs a "normal" non-PlzNavigate navigation | |
239 contents()->NavigateAndCommit(kUrl0); | |
240 histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 1); | |
241 | |
242 // Performs an in-tab renderer initiated navigation | |
243 int32 new_page_id = 1 + contents()->GetMaxPageIDForSiteInstance( | |
244 main_test_rfh()->GetSiteInstance()); | |
245 main_test_rfh()->SendNavigate(new_page_id, kUrl0); | |
246 histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 1); | |
247 | |
248 // Performs a PlzNavigate navigation | |
249 EnableBrowserSideNavigation(); | |
250 contents()->NavigateAndCommit(kUrl1); | |
251 histo_tester.ExpectTotalCount("Navigation.TimeToCommit", 2); | |
252 } | |
253 | |
254 // PlzNavigate: Test that a reload navigation is properly signaled to the | |
255 // renderer when the navigation can commit. | |
256 TEST_F(NavigatorTest, BrowserSideNavigationReload) { | |
257 const GURL kUrl("http://www.google.com/"); | |
258 contents()->NavigateAndCommit(kUrl); | |
259 | |
260 EnableBrowserSideNavigation(); | |
261 FrameTreeNode* node = main_test_rfh()->frame_tree_node(); | |
262 SendRequestNavigationWithParameters( | |
263 node, kUrl, Referrer(), ui::PAGE_TRANSITION_LINK, | |
264 NavigationController::RELOAD); | |
265 contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl); | |
266 // A NavigationRequest should have been generated. | |
267 NavigationRequest* main_request = | |
268 GetNavigationRequestForFrameTreeNode(node); | |
269 ASSERT_TRUE(main_request != NULL); | |
270 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD, | |
271 main_request->common_params().navigation_type); | |
272 int page_id = contents()->GetMaxPageIDForSiteInstance( | |
273 main_test_rfh()->GetSiteInstance()) + 1; | |
274 main_test_rfh()->SendNavigate(page_id, kUrl); | |
275 | |
276 // Now do a shift+reload. | |
277 SendRequestNavigationWithParameters( | |
278 node, kUrl, Referrer(), ui::PAGE_TRANSITION_LINK, | |
279 NavigationController::RELOAD_IGNORING_CACHE); | |
280 contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl); | |
281 // A NavigationRequest should have been generated. | |
282 main_request = GetNavigationRequestForFrameTreeNode(node); | |
283 ASSERT_TRUE(main_request != NULL); | |
284 EXPECT_EQ(FrameMsg_Navigate_Type::RELOAD_IGNORING_CACHE, | |
285 main_request->common_params().navigation_type); | |
286 } | |
287 | |
288 } // namespace content | |
OLD | NEW |