• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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/string_util.h"
6 #include "chrome/common/url_constants.h"
7 #include "chrome/test/automation/tab_proxy.h"
8 #include "chrome/test/automation/browser_proxy.h"
9 #include "chrome/test/ui/ui_test.h"
10 #include "grit/generated_resources.h"
11 #include "net/base/net_util.h"
12 #include "net/test/test_server.h"
13 
14 namespace {
15 
16 class SessionHistoryTest : public UITest {
17  protected:
SessionHistoryTest()18   SessionHistoryTest()
19       : test_server_(net::TestServer::TYPE_HTTP,
20                      FilePath(FILE_PATH_LITERAL("chrome/test/data"))) {
21     dom_automation_enabled_ = true;
22   }
23 
SetUp()24   virtual void SetUp() {
25     UITest::SetUp();
26 
27     window_ = automation()->GetBrowserWindow(0);
28     ASSERT_TRUE(window_.get());
29 
30     tab_ = window_->GetActiveTab();
31     ASSERT_TRUE(tab_.get());
32   }
33 
34   // Simulate clicking a link.  Only works on the frames.html testserver page.
ClickLink(std::string node_id)35   void ClickLink(std::string node_id) {
36     GURL url("javascript:clickLink('" + node_id + "')");
37     ASSERT_TRUE(tab_->NavigateToURL(url));
38   }
39 
40   // Simulate filling in form data.  Only works on the frames.html page with
41   // subframe = form.html, and on form.html itself.
FillForm(std::string node_id,std::string value)42   void FillForm(std::string node_id, std::string value) {
43     GURL url("javascript:fillForm('" + node_id + "', '" + value + "')");
44     // This will return immediately, but since the JS executes synchronously
45     // on the renderer, it will complete before the next navigate message is
46     // processed.
47     ASSERT_TRUE(tab_->NavigateToURLAsync(url));
48   }
49 
50   // Simulate submitting a form.  Only works on the frames.html page with
51   // subframe = form.html, and on form.html itself.
SubmitForm(std::string node_id)52   void SubmitForm(std::string node_id) {
53     GURL url("javascript:submitForm('" + node_id + "')");
54     ASSERT_TRUE(tab_->NavigateToURL(url));
55   }
56 
57   // Navigate session history using history.go(distance).
JavascriptGo(std::string distance)58   void JavascriptGo(std::string distance) {
59     GURL url("javascript:history.go('" + distance + "')");
60     ASSERT_TRUE(tab_->NavigateToURL(url));
61   }
62 
GetTabTitle()63   std::wstring GetTabTitle() {
64     std::wstring title;
65     EXPECT_TRUE(tab_->GetTabTitle(&title));
66     return title;
67   }
68 
GetTabURL()69   GURL GetTabURL() {
70     GURL url;
71     EXPECT_TRUE(tab_->GetCurrentURL(&url));
72     return url;
73   }
74 
75  protected:
76   scoped_refptr<BrowserProxy> window_;
77   scoped_refptr<TabProxy> tab_;
78 
79   net::TestServer test_server_;
80 };
81 
82 #if defined(OS_WIN)
83 // See http://crbug.com/61619
84 #define MAYBE_BasicBackForward FLAKY_BasicBackForward
85 #else
86 #define MAYBE_BasicBackForward BasicBackForward
87 #endif
88 
TEST_F(SessionHistoryTest,MAYBE_BasicBackForward)89 TEST_F(SessionHistoryTest, MAYBE_BasicBackForward) {
90   ASSERT_TRUE(test_server_.Start());
91 
92   // about:blank should be loaded first.
93   ASSERT_FALSE(tab_->GoBack());
94   EXPECT_EQ(L"about:blank", GetTabTitle());
95 
96   ASSERT_TRUE(tab_->NavigateToURL(
97       test_server_.GetURL("files/session_history/bot1.html")));
98   EXPECT_EQ(L"bot1", GetTabTitle());
99 
100   ASSERT_TRUE(tab_->NavigateToURL(
101       test_server_.GetURL("files/session_history/bot2.html")));
102   EXPECT_EQ(L"bot2", GetTabTitle());
103 
104   ASSERT_TRUE(tab_->NavigateToURL(
105       test_server_.GetURL("files/session_history/bot3.html")));
106   EXPECT_EQ(L"bot3", GetTabTitle());
107 
108   // history is [blank, bot1, bot2, *bot3]
109 
110   ASSERT_TRUE(tab_->GoBack());
111   EXPECT_EQ(L"bot2", GetTabTitle());
112 
113   ASSERT_TRUE(tab_->GoBack());
114   EXPECT_EQ(L"bot1", GetTabTitle());
115 
116   ASSERT_TRUE(tab_->GoForward());
117   EXPECT_EQ(L"bot2", GetTabTitle());
118 
119   ASSERT_TRUE(tab_->GoBack());
120   EXPECT_EQ(L"bot1", GetTabTitle());
121 
122   ASSERT_TRUE(tab_->NavigateToURL(
123       test_server_.GetURL("files/session_history/bot3.html")));
124   EXPECT_EQ(L"bot3", GetTabTitle());
125 
126   // history is [blank, bot1, *bot3]
127 
128   ASSERT_FALSE(tab_->GoForward());
129   EXPECT_EQ(L"bot3", GetTabTitle());
130 
131   ASSERT_TRUE(tab_->GoBack());
132   EXPECT_EQ(L"bot1", GetTabTitle());
133 
134   ASSERT_TRUE(tab_->GoBack());
135   EXPECT_EQ(L"about:blank", GetTabTitle());
136 
137   ASSERT_FALSE(tab_->GoBack());
138   EXPECT_EQ(L"about:blank", GetTabTitle());
139 
140   ASSERT_TRUE(tab_->GoForward());
141   EXPECT_EQ(L"bot1", GetTabTitle());
142 
143   ASSERT_TRUE(tab_->GoForward());
144   EXPECT_EQ(L"bot3", GetTabTitle());
145 }
146 
147 #if defined(OS_WIN)
148 // See http://crbug.com/61619
149 #define MAYBE_FrameBackForward FLAKY_FrameBackForward
150 #else
151 #define MAYBE_FrameBackForward FrameBackForward
152 #endif
153 
154 // Test that back/forward works when navigating in subframes.
TEST_F(SessionHistoryTest,MAYBE_FrameBackForward)155 TEST_F(SessionHistoryTest, MAYBE_FrameBackForward) {
156   ASSERT_TRUE(test_server_.Start());
157 
158   // about:blank should be loaded first.
159   GURL home(homepage());
160   ASSERT_FALSE(tab_->GoBack());
161   EXPECT_EQ(L"about:blank", GetTabTitle());
162   EXPECT_EQ(home, GetTabURL());
163 
164   GURL frames(test_server_.GetURL("files/session_history/frames.html"));
165   ASSERT_TRUE(tab_->NavigateToURL(frames));
166   EXPECT_EQ(L"bot1", GetTabTitle());
167   EXPECT_EQ(frames, GetTabURL());
168 
169   ClickLink("abot2");
170   EXPECT_EQ(L"bot2", GetTabTitle());
171   EXPECT_EQ(frames, GetTabURL());
172 
173   ClickLink("abot3");
174   EXPECT_EQ(L"bot3", GetTabTitle());
175   EXPECT_EQ(frames, GetTabURL());
176 
177   // history is [blank, bot1, bot2, *bot3]
178 
179   ASSERT_TRUE(tab_->GoBack());
180   EXPECT_EQ(L"bot2", GetTabTitle());
181   EXPECT_EQ(frames, GetTabURL());
182 
183   ASSERT_TRUE(tab_->GoBack());
184   EXPECT_EQ(L"bot1", GetTabTitle());
185   EXPECT_EQ(frames, GetTabURL());
186 
187   ASSERT_TRUE(tab_->GoBack());
188   EXPECT_EQ(L"about:blank", GetTabTitle());
189   EXPECT_EQ(home, GetTabURL());
190 
191   ASSERT_TRUE(tab_->GoForward());
192   EXPECT_EQ(L"bot1", GetTabTitle());
193   EXPECT_EQ(frames, GetTabURL());
194 
195   ASSERT_TRUE(tab_->GoForward());
196   EXPECT_EQ(L"bot2", GetTabTitle());
197   EXPECT_EQ(frames, GetTabURL());
198 
199   ClickLink("abot1");
200   EXPECT_EQ(L"bot1", GetTabTitle());
201   EXPECT_EQ(frames, GetTabURL());
202 
203   // history is [blank, bot1, bot2, *bot1]
204 
205   ASSERT_FALSE(tab_->GoForward());
206   EXPECT_EQ(L"bot1", GetTabTitle());
207   EXPECT_EQ(frames, GetTabURL());
208 
209   ASSERT_TRUE(tab_->GoBack());
210   EXPECT_EQ(L"bot2", GetTabTitle());
211   EXPECT_EQ(frames, GetTabURL());
212 
213   ASSERT_TRUE(tab_->GoBack());
214   EXPECT_EQ(L"bot1", GetTabTitle());
215   EXPECT_EQ(frames, GetTabURL());
216 }
217 
218 // See http://crbug.com/61619
219 // Test that back/forward preserves POST data and document state in subframes.
TEST_F(SessionHistoryTest,FLAKY_FrameFormBackForward)220 TEST_F(SessionHistoryTest, FLAKY_FrameFormBackForward) {
221   ASSERT_TRUE(test_server_.Start());
222 
223   // about:blank should be loaded first.
224   ASSERT_FALSE(tab_->GoBack());
225   EXPECT_EQ(L"", GetTabTitle());
226 
227   GURL frames(test_server_.GetURL("files/session_history/frames.html"));
228   ASSERT_TRUE(tab_->NavigateToURL(frames));
229   EXPECT_EQ(L"bot1", GetTabTitle());
230 
231   ClickLink("aform");
232   EXPECT_EQ(L"form", GetTabTitle());
233   EXPECT_EQ(frames, GetTabURL());
234 
235   SubmitForm("isubmit");
236   EXPECT_EQ(L"text=&select=a", GetTabTitle());
237   EXPECT_EQ(frames, GetTabURL());
238 
239   ASSERT_TRUE(tab_->GoBack());
240   EXPECT_EQ(L"form", GetTabTitle());
241   EXPECT_EQ(frames, GetTabURL());
242 
243   // history is [blank, bot1, *form, post]
244 
245   ClickLink("abot2");
246   EXPECT_EQ(L"bot2", GetTabTitle());
247   EXPECT_EQ(frames, GetTabURL());
248 
249   // history is [blank, bot1, form, *bot2]
250 
251   ASSERT_TRUE(tab_->GoBack());
252   EXPECT_EQ(L"form", GetTabTitle());
253   EXPECT_EQ(frames, GetTabURL());
254 
255   SubmitForm("isubmit");
256   EXPECT_EQ(L"text=&select=a", GetTabTitle());
257   EXPECT_EQ(frames, GetTabURL());
258 
259   // history is [blank, bot1, form, *post]
260 
261   if (false) {
262     // TODO(mpcomplete): reenable this when WebKit bug 10199 is fixed:
263     // "returning to a POST result within a frame does a GET instead of a POST"
264     ClickLink("abot2");
265     EXPECT_EQ(L"bot2", GetTabTitle());
266     EXPECT_EQ(frames, GetTabURL());
267 
268     ASSERT_TRUE(tab_->GoBack());
269     EXPECT_EQ(L"text=&select=a", GetTabTitle());
270     EXPECT_EQ(frames, GetTabURL());
271   }
272 }
273 
274 // TODO(mpcomplete): enable this when Bug 734372 is fixed:
275 // "Doing a session history navigation does not restore newly-created subframe
276 // document state"
277 // Test that back/forward preserves POST data and document state when navigating
278 // across frames (ie, from frame -> nonframe).
279 // Hangs, see http://crbug.com/45058.
TEST_F(SessionHistoryTest,DISABLED_CrossFrameFormBackForward)280 TEST_F(SessionHistoryTest, DISABLED_CrossFrameFormBackForward) {
281   ASSERT_TRUE(test_server_.Start());
282 
283   // about:blank should be loaded first.
284   ASSERT_FALSE(tab_->GoBack());
285   EXPECT_EQ(L"", GetTabTitle());
286 
287   GURL frames(test_server_.GetURL("files/session_history/frames.html"));
288   ASSERT_TRUE(tab_->NavigateToURL(frames));
289   EXPECT_EQ(L"bot1", GetTabTitle());
290 
291   ClickLink("aform");
292   EXPECT_EQ(L"form", GetTabTitle());
293   EXPECT_EQ(frames, GetTabURL());
294 
295   SubmitForm("isubmit");
296   EXPECT_EQ(L"text=&select=a", GetTabTitle());
297   EXPECT_EQ(frames, GetTabURL());
298 
299   ASSERT_TRUE(tab_->GoBack());
300   EXPECT_EQ(L"form", GetTabTitle());
301   EXPECT_EQ(frames, GetTabURL());
302 
303   // history is [blank, bot1, *form, post]
304 
305   // ClickLink(L"abot2");
306   GURL bot2("files/session_history/bot2.html");
307   ASSERT_TRUE(tab_->NavigateToURL(bot2));
308   EXPECT_EQ(L"bot2", GetTabTitle());
309   EXPECT_EQ(bot2, GetTabURL());
310 
311   // history is [blank, bot1, form, *bot2]
312 
313   ASSERT_TRUE(tab_->GoBack());
314   EXPECT_EQ(L"form", GetTabTitle());
315   EXPECT_EQ(frames, GetTabURL());
316 
317   SubmitForm("isubmit");
318   EXPECT_EQ(L"text=&select=a", GetTabTitle());
319   EXPECT_EQ(frames, GetTabURL());
320 }
321 
322 
323 #if defined(OS_WIN)
324 // See http://crbug.com/61619
325 #define MAYBE_FragmentBackForward FLAKY_FragmentBackForward
326 #else
327 #define MAYBE_FragmentBackForward FragmentBackForward
328 #endif
329 
330 // Test that back/forward entries are created for reference fragment
331 // navigations. Bug 730379.
TEST_F(SessionHistoryTest,MAYBE_FragmentBackForward)332 TEST_F(SessionHistoryTest, MAYBE_FragmentBackForward) {
333   ASSERT_TRUE(test_server_.Start());
334 
335   // about:blank should be loaded first.
336   ASSERT_FALSE(tab_->GoBack());
337   EXPECT_EQ(L"about:blank", GetTabTitle());
338 
339   GURL fragment(test_server_.GetURL("files/session_history/fragment.html"));
340   ASSERT_TRUE(tab_->NavigateToURL(fragment));
341   EXPECT_EQ(L"fragment", GetTabTitle());
342   EXPECT_EQ(fragment, GetTabURL());
343 
344   GURL::Replacements ref_params;
345 
346   ref_params.SetRef("a", url_parse::Component(0, 1));
347   GURL fragment_a(fragment.ReplaceComponents(ref_params));
348   ASSERT_TRUE(tab_->NavigateToURL(fragment_a));
349   EXPECT_EQ(L"fragment", GetTabTitle());
350   EXPECT_EQ(fragment_a, GetTabURL());
351 
352   ref_params.SetRef("b", url_parse::Component(0, 1));
353   GURL fragment_b(fragment.ReplaceComponents(ref_params));
354   ASSERT_TRUE(tab_->NavigateToURL(fragment_b));
355   EXPECT_EQ(L"fragment", GetTabTitle());
356   EXPECT_EQ(fragment_b, GetTabURL());
357 
358   ref_params.SetRef("c", url_parse::Component(0, 1));
359   GURL fragment_c(fragment.ReplaceComponents(ref_params));
360   ASSERT_TRUE(tab_->NavigateToURL(fragment_c));
361   EXPECT_EQ(L"fragment", GetTabTitle());
362   EXPECT_EQ(fragment_c, GetTabURL());
363 
364   // history is [blank, fragment, fragment#a, fragment#b, *fragment#c]
365 
366   ASSERT_TRUE(tab_->GoBack());
367   EXPECT_EQ(fragment_b, GetTabURL());
368 
369   ASSERT_TRUE(tab_->GoBack());
370   EXPECT_EQ(fragment_a, GetTabURL());
371 
372   ASSERT_TRUE(tab_->GoBack());
373   EXPECT_EQ(fragment, GetTabURL());
374 
375   ASSERT_TRUE(tab_->GoForward());
376   EXPECT_EQ(fragment_a, GetTabURL());
377 
378   GURL bot3(test_server_.GetURL("files/session_history/bot3.html"));
379   ASSERT_TRUE(tab_->NavigateToURL(bot3));
380   EXPECT_EQ(L"bot3", GetTabTitle());
381   EXPECT_EQ(bot3, GetTabURL());
382 
383   // history is [blank, fragment, fragment#a, bot3]
384 
385   ASSERT_FALSE(tab_->GoForward());
386   EXPECT_EQ(bot3, GetTabURL());
387 
388   ASSERT_TRUE(tab_->GoBack());
389   EXPECT_EQ(fragment_a, GetTabURL());
390 
391   ASSERT_TRUE(tab_->GoBack());
392   EXPECT_EQ(fragment, GetTabURL());
393 }
394 
395 // Test that the javascript window.history object works.
396 // NOTE: history.go(N) does not do anything if N is outside the bounds of the
397 // back/forward list (such as trigger our start/stop loading events).  This
398 // means the test will hang if it attempts to navigate too far forward or back,
399 // since we'll be waiting forever for a load stop event.
400 //
401 // TODO(brettw) bug 50648: fix flakyness. This test seems like it was failing
402 // about 1/4 of the time on Vista by failing to execute JavascriptGo (see bug).
TEST_F(SessionHistoryTest,FLAKY_JavascriptHistory)403 TEST_F(SessionHistoryTest, FLAKY_JavascriptHistory) {
404   ASSERT_TRUE(test_server_.Start());
405 
406   // about:blank should be loaded first.
407   ASSERT_FALSE(tab_->GoBack());
408   EXPECT_EQ(L"about:blank", GetTabTitle());
409 
410   ASSERT_TRUE(tab_->NavigateToURL(
411       test_server_.GetURL("files/session_history/bot1.html")));
412   EXPECT_EQ(L"bot1", GetTabTitle());
413 
414   ASSERT_TRUE(tab_->NavigateToURL(
415       test_server_.GetURL("files/session_history/bot2.html")));
416   EXPECT_EQ(L"bot2", GetTabTitle());
417 
418   ASSERT_TRUE(tab_->NavigateToURL(
419       test_server_.GetURL("files/session_history/bot3.html")));
420   EXPECT_EQ(L"bot3", GetTabTitle());
421 
422   // history is [blank, bot1, bot2, *bot3]
423 
424   JavascriptGo("-1");
425   EXPECT_EQ(L"bot2", GetTabTitle());
426 
427   JavascriptGo("-1");
428   EXPECT_EQ(L"bot1", GetTabTitle());
429 
430   JavascriptGo("1");
431   EXPECT_EQ(L"bot2", GetTabTitle());
432 
433   JavascriptGo("-1");
434   EXPECT_EQ(L"bot1", GetTabTitle());
435 
436   JavascriptGo("2");
437   EXPECT_EQ(L"bot3", GetTabTitle());
438 
439   // history is [blank, bot1, bot2, *bot3]
440 
441   JavascriptGo("-3");
442   EXPECT_EQ(L"about:blank", GetTabTitle());
443 
444   ASSERT_FALSE(tab_->GoBack());
445   EXPECT_EQ(L"about:blank", GetTabTitle());
446 
447   JavascriptGo("1");
448   EXPECT_EQ(L"bot1", GetTabTitle());
449 
450   ASSERT_TRUE(tab_->NavigateToURL(
451       test_server_.GetURL("files/session_history/bot3.html")));
452   EXPECT_EQ(L"bot3", GetTabTitle());
453 
454   // history is [blank, bot1, *bot3]
455 
456   ASSERT_FALSE(tab_->GoForward());
457   EXPECT_EQ(L"bot3", GetTabTitle());
458 
459   JavascriptGo("-1");
460   EXPECT_EQ(L"bot1", GetTabTitle());
461 
462   JavascriptGo("-1");
463   EXPECT_EQ(L"about:blank", GetTabTitle());
464 
465   ASSERT_FALSE(tab_->GoBack());
466   EXPECT_EQ(L"about:blank", GetTabTitle());
467 
468   JavascriptGo("1");
469   EXPECT_EQ(L"bot1", GetTabTitle());
470 
471   JavascriptGo("1");
472   EXPECT_EQ(L"bot3", GetTabTitle());
473 
474   // TODO(creis): Test that JavaScript history navigations work across tab
475   // types.  For example, load about:network in a tab, then a real page, then
476   // try to go back and forward with JavaScript.  Bug 1136715.
477   // (Hard to test right now, because pages like about:network cause the
478   // TabProxy to hang.  This is because they do not appear to use the
479   // NotificationService.)
480 }
481 
482 // This test is failing consistently. See http://crbug.com/22560
TEST_F(SessionHistoryTest,FAILS_LocationReplace)483 TEST_F(SessionHistoryTest, FAILS_LocationReplace) {
484   ASSERT_TRUE(test_server_.Start());
485 
486   // Test that using location.replace doesn't leave the title of the old page
487   // visible.
488   ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL(
489       "files/session_history/replace.html?no-title.html")));
490   EXPECT_EQ(L"", GetTabTitle());
491 }
492 
493 // This test is flaky. See bug 22111.
TEST_F(SessionHistoryTest,FLAKY_HistorySearchXSS)494 TEST_F(SessionHistoryTest, FLAKY_HistorySearchXSS) {
495   // about:blank should be loaded first.
496   ASSERT_FALSE(tab_->GoBack());
497   EXPECT_EQ(L"about:blank", GetTabTitle());
498 
499   GURL url(std::string(chrome::kChromeUIHistoryURL) +
500       "#q=%3Cimg%20src%3Dx%3Ax%20onerror%3D%22document.title%3D'XSS'%22%3E");
501   ASSERT_TRUE(tab_->NavigateToURL(url));
502   // Mainly, this is to ensure we send a synchronous message to the renderer
503   // so that we're not susceptible (less susceptible?) to a race condition.
504   // Should a race condition ever trigger, it won't result in flakiness.
505   int num = tab_->FindInPage(L"<img", FWD, CASE_SENSITIVE, false, NULL);
506   EXPECT_GT(num, 0);
507   EXPECT_EQ(L"History", GetTabTitle());
508 }
509 
510 #if defined(OS_WIN)
511 // See http://crbug.com/61619
512 #define MAYBE_LocationChangeInSubframe FLAKY_LocationChangeInSubframe
513 #else
514 #define MAYBE_LocationChangeInSubframe LocationChangeInSubframe
515 #endif
516 
TEST_F(SessionHistoryTest,MAYBE_LocationChangeInSubframe)517 TEST_F(SessionHistoryTest, MAYBE_LocationChangeInSubframe) {
518   ASSERT_TRUE(test_server_.Start());
519 
520   ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL(
521       "files/session_history/location_redirect.html")));
522   EXPECT_EQ(L"Default Title", GetTabTitle());
523 
524   ASSERT_TRUE(tab_->NavigateToURL(GURL(
525       "javascript:void(frames[0].navigate())")));
526   EXPECT_EQ(L"foo", GetTabTitle());
527 
528   ASSERT_TRUE(tab_->GoBack());
529   EXPECT_EQ(L"Default Title", GetTabTitle());
530 }
531 
532 // http://code.google.com/p/chromium/issues/detail?id=56267
TEST_F(SessionHistoryTest,DISABLED_HistoryLength)533 TEST_F(SessionHistoryTest, DISABLED_HistoryLength) {
534   ASSERT_TRUE(test_server_.Start());
535 
536   int length;
537   ASSERT_TRUE(tab_->ExecuteAndExtractInt(
538       L"", L"domAutomationController.send(history.length)", &length));
539   EXPECT_EQ(1, length);
540 
541   ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title1.html")));
542 
543   ASSERT_TRUE(tab_->ExecuteAndExtractInt(
544       L"", L"domAutomationController.send(history.length)", &length));
545   EXPECT_EQ(2, length);
546 
547   // Now test that history.length is updated when the navigation is committed.
548   ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL(
549       "files/session_history/record_length.html")));
550   ASSERT_TRUE(tab_->ExecuteAndExtractInt(
551       L"", L"domAutomationController.send(history.length)", &length));
552   EXPECT_EQ(3, length);
553   ASSERT_TRUE(tab_->ExecuteAndExtractInt(
554       L"", L"domAutomationController.send(history_length)", &length));
555   EXPECT_EQ(3, length);
556 
557   ASSERT_TRUE(tab_->GoBack());
558   ASSERT_TRUE(tab_->GoBack());
559 
560   // Ensure history.length is properly truncated.
561   ASSERT_TRUE(tab_->NavigateToURL(test_server_.GetURL("files/title2.html")));
562   ASSERT_TRUE(tab_->ExecuteAndExtractInt(
563       L"", L"domAutomationController.send(history.length)", &length));
564   EXPECT_EQ(2, length);
565 }
566 
567 }  // namespace
568