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