1 // Copyright (c) 2012 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/callback.h"
7 #include "base/strings/stringprintf.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/extensions/api/permissions/permissions_api.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/extension_service.h"
12 #include "chrome/browser/extensions/test_extension_dir.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/test/base/ui_test_utils.h"
17 #include "components/app_modal/javascript_dialog_extensions_client.h"
18 #include "components/app_modal/javascript_dialog_manager.h"
19 #include "content/public/browser/javascript_dialog_manager.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_delegate.h"
23 #include "content/public/test/browser_test_utils.h"
24 #include "extensions/browser/notification_types.h"
25 #include "extensions/common/extension.h"
26 #include "extensions/test/extension_test_message_listener.h"
27 #include "extensions/test/result_catcher.h"
28 #include "net/dns/mock_host_resolver.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
32 namespace extensions
{
36 // A fake webstore domain.
37 const char kWebstoreDomain
[] = "cws.com";
39 // Check whether or not style was injected, with |expected_injection| indicating
40 // the expected result. Also ensure that no CSS was added to the
41 // document.styleSheets array.
42 testing::AssertionResult
CheckStyleInjection(Browser
* browser
,
44 bool expected_injection
) {
45 ui_test_utils::NavigateToURL(browser
, url
);
47 bool css_injected
= false;
48 if (!content::ExecuteScriptAndExtractBool(
49 browser
->tab_strip_model()->GetActiveWebContents(),
50 "window.domAutomationController.send("
51 " document.defaultView.getComputedStyle(document.body, null)."
52 " getPropertyValue('display') == 'none');",
54 return testing::AssertionFailure()
55 << "Failed to execute script and extract bool for injection status.";
58 if (css_injected
!= expected_injection
) {
61 message
= "CSS injected when no injection was expected.";
63 message
= "CSS not injected when injection was expected.";
64 return testing::AssertionFailure() << message
;
67 bool css_doesnt_add_to_list
= false;
68 if (!content::ExecuteScriptAndExtractBool(
69 browser
->tab_strip_model()->GetActiveWebContents(),
70 "window.domAutomationController.send("
71 " document.styleSheets.length == 0);",
72 &css_doesnt_add_to_list
)) {
73 return testing::AssertionFailure()
74 << "Failed to execute script and extract bool for stylesheets length.";
76 if (!css_doesnt_add_to_list
) {
77 return testing::AssertionFailure()
78 << "CSS injection added to number of stylesheets.";
81 return testing::AssertionSuccess();
86 // A helper class to hijack the dialog manager's ExtensionsClient, so that we
87 // know when dialogs are being opened.
88 // NOTE: The default implementation of the JavaScriptDialogExtensionsClient
89 // doesn't do anything, so it's safe to override it. If, at some stage, this
90 // has behavior (like if we move this into app shell), we'll need to update
91 // this (by, e.g., making DialogClient a wrapper around the implementation).
94 explicit DialogHelper(content::WebContents
* web_contents
);
97 // Notifies the DialogHelper that a dialog was opened. Runs |quit_closure_|,
101 // Closes any active dialogs.
104 void set_quit_closure(const base::Closure
& quit_closure
) {
105 quit_closure_
= quit_closure
;
107 size_t dialog_count() const { return dialog_count_
; }
110 // The number of dialogs to appear.
111 size_t dialog_count_
;
113 // The WebContents this helper is associated with.
114 content::WebContents
* web_contents_
;
116 // The dialog manager for |web_contents_|.
117 content::JavaScriptDialogManager
* dialog_manager_
;
119 // The dialog client override.
120 DialogClient
* client_
;
122 // The quit closure to run when a dialog appears.
123 base::Closure quit_closure_
;
125 DISALLOW_COPY_AND_ASSIGN(DialogHelper
);
128 // The client override for the DialogHelper.
129 class DialogClient
: public app_modal::JavaScriptDialogExtensionsClient
{
131 explicit DialogClient(DialogHelper
* helper
) : helper_(helper
) {}
132 ~DialogClient() override
{}
134 void set_helper(DialogHelper
* helper
) { helper_
= helper
; }
137 // app_modal::JavaScriptDialogExtensionsClient:
138 void OnDialogOpened(content::WebContents
* web_contents
) override
{
140 helper_
->DialogOpened();
142 void OnDialogClosed(content::WebContents
* web_contents
) override
{}
143 bool GetExtensionName(content::WebContents
* web_contents
,
144 const GURL
& origin_url
,
145 std::string
* name_out
) override
{
149 // The dialog helper to notify of any open dialogs.
150 DialogHelper
* helper_
;
152 DISALLOW_COPY_AND_ASSIGN(DialogClient
);
155 DialogHelper::DialogHelper(content::WebContents
* web_contents
)
157 web_contents_(web_contents
),
158 dialog_manager_(nullptr),
160 app_modal::JavaScriptDialogManager
* dialog_manager_impl
=
161 app_modal::JavaScriptDialogManager::GetInstance();
163 web_contents_
->GetDelegate()->GetJavaScriptDialogManager(web_contents_
);
164 DCHECK_EQ(dialog_manager_impl
, dialog_manager_
);
166 client_
= new DialogClient(this);
167 dialog_manager_impl
->SetExtensionsClient(make_scoped_ptr(client_
));
170 DialogHelper::~DialogHelper() {
171 client_
->set_helper(nullptr);
174 void DialogHelper::CloseDialogs() {
175 dialog_manager_
->CancelActiveAndPendingDialogs(web_contents_
);
178 void DialogHelper::DialogOpened() {
180 if (!quit_closure_
.is_null()) {
182 quit_closure_
= base::Closure();
186 // Runs all pending tasks in the renderer associated with |web_contents|, and
187 // then all pending tasks in the browser process.
188 // Returns true on success.
189 bool RunAllPending(content::WebContents
* web_contents
) {
190 // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs
191 // are sent synchronously, anything started prior to this method will finish
192 // before this method returns (as content::ExecuteScript() is synchronous).
193 if (!content::ExecuteScript(web_contents
, "1 == 1;"))
195 base::RunLoop().RunUntilIdle();
199 // A simple extension manifest with content scripts on all pages.
200 const char kManifest
[] =
203 " \"version\": \"1.0\","
204 " \"manifest_version\": 2,"
205 " \"content_scripts\": [{"
206 " \"matches\": [\"*://*/*\"],"
207 " \"js\": [\"script.js\"],"
208 " \"run_at\": \"%s\""
212 // A (blocking) content script that pops up an alert.
213 const char kBlockingScript
[] = "alert('ALERT');";
215 // A (non-blocking) content script that sends a message.
216 const char kNonBlockingScript
[] = "chrome.test.sendMessage('done');";
218 const char kNewTabOverrideManifest
[] =
220 " \"name\": \"New tab override\","
221 " \"version\": \"0.1\","
222 " \"manifest_version\": 2,"
223 " \"description\": \"Foo!\","
224 " \"chrome_url_overrides\": {\"newtab\": \"newtab.html\"}"
227 const char kNewTabHtml
[] = "<html>NewTabOverride!</html>";
231 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptAllFrames
) {
232 ASSERT_TRUE(StartEmbeddedTestServer());
233 ASSERT_TRUE(RunExtensionTest("content_scripts/all_frames")) << message_
;
236 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptAboutBlankIframes
) {
237 ASSERT_TRUE(StartEmbeddedTestServer());
239 RunExtensionTest("content_scripts/about_blank_iframes")) << message_
;
242 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptAboutBlankAndSrcdoc
) {
243 // The optional "*://*/*" permission is requested after verifying that
244 // content script insertion solely depends on content_scripts[*].matches.
245 // The permission is needed for chrome.tabs.executeScript tests.
246 PermissionsRequestFunction::SetAutoConfirmForTests(true);
247 PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
249 ASSERT_TRUE(StartEmbeddedTestServer());
250 ASSERT_TRUE(RunExtensionTest("content_scripts/about_blank_srcdoc"))
254 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptExtensionIframe
) {
255 ASSERT_TRUE(StartEmbeddedTestServer());
256 ASSERT_TRUE(RunExtensionTest("content_scripts/extension_iframe")) << message_
;
259 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptExtensionProcess
) {
260 ASSERT_TRUE(StartEmbeddedTestServer());
262 RunExtensionTest("content_scripts/extension_process")) << message_
;
265 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptFragmentNavigation
) {
266 ASSERT_TRUE(StartEmbeddedTestServer());
267 const char extension_name
[] = "content_scripts/fragment";
268 ASSERT_TRUE(RunExtensionTest(extension_name
)) << message_
;
271 // Times out on Linux: http://crbug.com/163097
272 #if defined(OS_LINUX)
273 #define MAYBE_ContentScriptIsolatedWorlds DISABLED_ContentScriptIsolatedWorlds
275 #define MAYBE_ContentScriptIsolatedWorlds ContentScriptIsolatedWorlds
277 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, MAYBE_ContentScriptIsolatedWorlds
) {
278 // This extension runs various bits of script and tests that they all run in
279 // the same isolated world.
280 ASSERT_TRUE(StartEmbeddedTestServer());
281 ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world1")) << message_
;
283 // Now load a different extension, inject into same page, verify worlds aren't
285 ASSERT_TRUE(RunExtensionTest("content_scripts/isolated_world2")) << message_
;
288 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptIgnoreHostPermissions
) {
289 host_resolver()->AddRule("a.com", "127.0.0.1");
290 host_resolver()->AddRule("b.com", "127.0.0.1");
291 ASSERT_TRUE(StartEmbeddedTestServer());
292 ASSERT_TRUE(RunExtensionTest(
293 "content_scripts/dont_match_host_permissions")) << message_
;
296 // crbug.com/39249 -- content scripts js should not run on view source.
297 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptViewSource
) {
298 ASSERT_TRUE(StartEmbeddedTestServer());
299 ASSERT_TRUE(RunExtensionTest("content_scripts/view_source")) << message_
;
302 // crbug.com/126257 -- content scripts should not get injected into other
304 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptOtherExtensions
) {
305 host_resolver()->AddRule("a.com", "127.0.0.1");
306 ASSERT_TRUE(StartEmbeddedTestServer());
307 // First, load extension that sets up content script.
308 ASSERT_TRUE(RunExtensionTest("content_scripts/other_extensions/injector"))
310 // Then load targeted extension to make sure its content isn't changed.
311 ASSERT_TRUE(RunExtensionTest("content_scripts/other_extensions/victim"))
315 class ContentScriptCssInjectionTest
: public ExtensionApiTest
{
317 // TODO(rdevlin.cronin): Make a testing switch that looks like FeatureSwitch,
318 // but takes in an optional value so that we don't have to do this.
319 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
320 ExtensionApiTest::SetUpCommandLine(command_line
);
321 // We change the Webstore URL to be http://cws.com. We need to do this so
322 // we can check that css injection is not allowed on the webstore (which
323 // could lead to spoofing). Unfortunately, host_resolver seems to have
324 // problems with redirecting "chrome.google.com" to the test server, so we
325 // can't use the real Webstore's URL. If this changes, we could clean this
327 command_line
->AppendSwitchASCII(
328 switches::kAppsGalleryURL
,
329 base::StringPrintf("http://%s", kWebstoreDomain
));
333 IN_PROC_BROWSER_TEST_F(ContentScriptCssInjectionTest
,
334 ContentScriptInjectsStyles
) {
335 ASSERT_TRUE(StartEmbeddedTestServer());
336 host_resolver()->AddRule(kWebstoreDomain
, "127.0.0.1");
338 ASSERT_TRUE(LoadExtension(test_data_dir_
.AppendASCII("content_scripts")
339 .AppendASCII("css_injection")));
341 // CSS injection should be allowed on an aribitrary web page.
343 embedded_test_server()->GetURL("/extensions/test_file_with_body.html");
344 EXPECT_TRUE(CheckStyleInjection(browser(), url
, true));
346 // The loaded extension has an exclude match for "extensions/test_file.html",
347 // so no CSS should be injected.
348 url
= embedded_test_server()->GetURL("/extensions/test_file.html");
349 EXPECT_TRUE(CheckStyleInjection(browser(), url
, false));
351 // We disallow all injection on the webstore.
352 GURL::Replacements replacements
;
353 replacements
.SetHostStr(kWebstoreDomain
);
354 url
= embedded_test_server()->GetURL("/extensions/test_file_with_body.html")
355 .ReplaceComponents(replacements
);
356 EXPECT_TRUE(CheckStyleInjection(browser(), url
, false));
360 IN_PROC_BROWSER_TEST_F(
362 DISABLED_ContentScriptStylesInjectedIntoExistingRenderers
) {
363 ASSERT_TRUE(StartEmbeddedTestServer());
365 content::WindowedNotificationObserver
signal(
366 extensions::NOTIFICATION_USER_SCRIPTS_UPDATED
,
367 content::Source
<Profile
>(browser()->profile()));
369 // Start with a renderer already open at a URL.
370 GURL
url(test_server()->GetURL("file/extensions/test_file.html"));
371 ui_test_utils::NavigateToURL(browser(), url
);
374 test_data_dir_
.AppendASCII("content_scripts/existing_renderers"));
378 // And check that its styles were affected by the styles that just got loaded.
379 bool styles_injected
;
380 ASSERT_TRUE(content::ExecuteScriptAndExtractBool(
381 browser()->tab_strip_model()->GetActiveWebContents(),
382 "window.domAutomationController.send("
383 " document.defaultView.getComputedStyle(document.body, null)."
384 " getPropertyValue('background-color') == 'rgb(255, 0, 0)')",
386 ASSERT_TRUE(styles_injected
);
389 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
,
390 ContentScriptCSSLocalization
) {
391 ASSERT_TRUE(StartEmbeddedTestServer());
392 ASSERT_TRUE(RunExtensionTest("content_scripts/css_l10n")) << message_
;
395 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptExtensionAPIs
) {
396 ASSERT_TRUE(StartEmbeddedTestServer());
398 const extensions::Extension
* extension
= LoadExtension(
399 test_data_dir_
.AppendASCII("content_scripts/extension_api"));
401 ResultCatcher catcher
;
402 ui_test_utils::NavigateToURL(
404 embedded_test_server()->GetURL(
405 "/extensions/api_test/content_scripts/extension_api/functions.html"));
406 EXPECT_TRUE(catcher
.GetNextResult());
408 // Navigate to a page that will cause a content script to run that starts
409 // listening for an extension event.
410 ui_test_utils::NavigateToURL(
412 embedded_test_server()->GetURL(
413 "/extensions/api_test/content_scripts/extension_api/events.html"));
415 // Navigate to an extension page that will fire the event events.js is
417 ui_test_utils::NavigateToURLWithDisposition(
418 browser(), extension
->GetResourceURL("fire_event.html"),
419 NEW_FOREGROUND_TAB
, ui_test_utils::BROWSER_TEST_NONE
);
420 EXPECT_TRUE(catcher
.GetNextResult());
423 // Flaky on Windows. http://crbug.com/248418
425 #define MAYBE_ContentScriptPermissionsApi DISABLED_ContentScriptPermissionsApi
427 #define MAYBE_ContentScriptPermissionsApi ContentScriptPermissionsApi
429 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, MAYBE_ContentScriptPermissionsApi
) {
430 extensions::PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
431 extensions::PermissionsRequestFunction::SetAutoConfirmForTests(true);
432 host_resolver()->AddRule("*.com", "127.0.0.1");
433 ASSERT_TRUE(StartEmbeddedTestServer());
434 ASSERT_TRUE(RunExtensionTest("content_scripts/permissions")) << message_
;
437 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptBypassPageCSP
) {
438 ASSERT_TRUE(StartEmbeddedTestServer());
439 ASSERT_TRUE(RunExtensionTest("content_scripts/bypass_page_csp")) << message_
;
442 // Test that when injecting a blocking content script, other scripts don't run
443 // until the blocking script finishes.
444 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptBlockingScript
) {
445 ASSERT_TRUE(StartEmbeddedTestServer());
447 // Load up two extensions.
448 TestExtensionDir ext_dir1
;
449 ext_dir1
.WriteManifest(
450 base::StringPrintf(kManifest
, "ext1", "document_start"));
451 ext_dir1
.WriteFile(FILE_PATH_LITERAL("script.js"), kBlockingScript
);
452 const Extension
* ext1
= LoadExtension(ext_dir1
.unpacked_path());
455 TestExtensionDir ext_dir2
;
456 ext_dir2
.WriteManifest(base::StringPrintf(kManifest
, "ext2", "document_end"));
457 ext_dir2
.WriteFile(FILE_PATH_LITERAL("script.js"), kNonBlockingScript
);
458 const Extension
* ext2
= LoadExtension(ext_dir2
.unpacked_path());
461 content::WebContents
* web_contents
=
462 browser()->tab_strip_model()->GetActiveWebContents();
463 DialogHelper
dialog_helper(web_contents
);
464 base::RunLoop run_loop
;
465 dialog_helper
.set_quit_closure(run_loop
.QuitClosure());
467 ExtensionTestMessageListener
listener("done", false);
468 listener
.set_extension_id(ext2
->id());
470 // Navigate! Both extensions will try to inject.
471 ui_test_utils::NavigateToURLWithDisposition(
473 embedded_test_server()->GetURL("/empty.html"),
475 ui_test_utils::BROWSER_TEST_NONE
);
478 // Right now, the alert dialog is showing and blocking injection of anything
479 // after it, so the listener shouldn't be satisfied.
480 EXPECT_TRUE(RunAllPending(web_contents
));
481 EXPECT_FALSE(listener
.was_satisfied());
482 EXPECT_EQ(1u, dialog_helper
.dialog_count());
483 dialog_helper
.CloseDialogs();
485 // After closing the dialog, the rest of the scripts should be able to
487 EXPECT_TRUE(listener
.WaitUntilSatisfied());
490 // Test that closing a tab with a blocking script results in no further scripts
491 // running (and we don't crash).
492 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
, ContentScriptBlockingScriptTabClosed
) {
493 ASSERT_TRUE(StartEmbeddedTestServer());
495 // We're going to close a tab in this test, so make a new one (to ensure
496 // we don't close the browser).
497 ui_test_utils::NavigateToURLWithDisposition(
499 embedded_test_server()->GetURL("/empty.html"),
501 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
503 // Set up the same as the previous test case.
504 TestExtensionDir ext_dir1
;
505 ext_dir1
.WriteManifest(
506 base::StringPrintf(kManifest
, "ext1", "document_start"));
507 ext_dir1
.WriteFile(FILE_PATH_LITERAL("script.js"), kBlockingScript
);
508 const Extension
* ext1
= LoadExtension(ext_dir1
.unpacked_path());
511 TestExtensionDir ext_dir2
;
512 ext_dir2
.WriteManifest(base::StringPrintf(kManifest
, "ext2", "document_end"));
513 ext_dir2
.WriteFile(FILE_PATH_LITERAL("script.js"), kNonBlockingScript
);
514 const Extension
* ext2
= LoadExtension(ext_dir2
.unpacked_path());
517 content::WebContents
* web_contents
=
518 browser()->tab_strip_model()->GetActiveWebContents();
519 DialogHelper
dialog_helper(web_contents
);
520 base::RunLoop run_loop
;
521 dialog_helper
.set_quit_closure(run_loop
.QuitClosure());
523 ExtensionTestMessageListener
listener("done", false);
524 listener
.set_extension_id(ext2
->id());
527 ui_test_utils::NavigateToURLWithDisposition(
529 embedded_test_server()->GetURL("/empty.html"),
531 ui_test_utils::BROWSER_TEST_NONE
);
533 // Now, instead of closing the dialog, just close the tab. Later scripts
534 // should never get a chance to run (and we shouldn't crash).
536 EXPECT_TRUE(RunAllPending(web_contents
));
537 EXPECT_FALSE(listener
.was_satisfied());
538 EXPECT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt(
539 browser()->tab_strip_model()->active_index(), 0));
540 EXPECT_FALSE(listener
.was_satisfied());
543 // There was a bug by which content scripts that blocked and ran on
544 // document_idle could be injected twice (crbug.com/431263). Test for
546 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
,
547 ContentScriptBlockingScriptsDontRunTwice
) {
548 ASSERT_TRUE(StartEmbeddedTestServer());
550 // Load up an extension.
551 TestExtensionDir ext_dir1
;
552 ext_dir1
.WriteManifest(
553 base::StringPrintf(kManifest
, "ext1", "document_idle"));
554 ext_dir1
.WriteFile(FILE_PATH_LITERAL("script.js"), kBlockingScript
);
555 const Extension
* ext1
= LoadExtension(ext_dir1
.unpacked_path());
558 content::WebContents
* web_contents
=
559 browser()->tab_strip_model()->GetActiveWebContents();
560 DialogHelper
dialog_helper(web_contents
);
561 base::RunLoop run_loop
;
562 dialog_helper
.set_quit_closure(run_loop
.QuitClosure());
565 ui_test_utils::NavigateToURLWithDisposition(
567 embedded_test_server()->GetURL("/empty.html"),
569 ui_test_utils::BROWSER_TEST_NONE
);
573 // The extension will have injected at idle, but it should only inject once.
574 EXPECT_TRUE(RunAllPending(web_contents
));
575 EXPECT_EQ(1u, dialog_helper
.dialog_count());
576 dialog_helper
.CloseDialogs();
577 EXPECT_TRUE(RunAllPending(web_contents
));
578 EXPECT_EQ(1u, dialog_helper
.dialog_count());
581 // Bug fix for crbug.com/507461.
582 IN_PROC_BROWSER_TEST_F(ExtensionApiTest
,
583 DocumentStartInjectionFromExtensionTabNavigation
) {
584 ASSERT_TRUE(StartEmbeddedTestServer());
586 TestExtensionDir new_tab_override_dir
;
587 new_tab_override_dir
.WriteManifest(kNewTabOverrideManifest
);
588 new_tab_override_dir
.WriteFile(FILE_PATH_LITERAL("newtab.html"), kNewTabHtml
);
589 const Extension
* new_tab_override
=
590 LoadExtension(new_tab_override_dir
.unpacked_path());
591 ASSERT_TRUE(new_tab_override
);
593 TestExtensionDir injector_dir
;
594 injector_dir
.WriteManifest(
595 base::StringPrintf(kManifest
, "injector", "document_start"));
596 injector_dir
.WriteFile(FILE_PATH_LITERAL("script.js"), kNonBlockingScript
);
597 const Extension
* injector
= LoadExtension(injector_dir
.unpacked_path());
598 ASSERT_TRUE(injector
);
600 ExtensionTestMessageListener
listener("done", false);
601 AddTabAtIndex(0, GURL("chrome://newtab"), ui::PAGE_TRANSITION_LINK
);
602 browser()->tab_strip_model()->ActivateTabAt(0, false);
603 content::WebContents
* tab_contents
=
604 browser()->tab_strip_model()->GetActiveWebContents();
606 EXPECT_EQ(new_tab_override
->GetResourceURL("newtab.html"),
607 tab_contents
->GetMainFrame()->GetLastCommittedURL());
608 EXPECT_FALSE(listener
.was_satisfied());
611 ui_test_utils::NavigateToURLWithDisposition(
612 browser(), embedded_test_server()->GetURL("/empty.html"),
613 CURRENT_TAB
, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
614 base::RunLoop().RunUntilIdle();
615 EXPECT_TRUE(listener
.was_satisfied());
618 } // namespace extensions