• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/bind.h"
6 #include "base/cancelable_callback.h"
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/path_service.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/test/test_timeouts.h"
15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/devtools/browser_list_tabcontents_provider.h"
17 #include "chrome/browser/devtools/devtools_window.h"
18 #include "chrome/browser/extensions/extension_apitest.h"
19 #include "chrome/browser/extensions/extension_browsertest.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/unpacked_installer.h"
22 #include "chrome/browser/lifetime/application_lifetime.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h"
25 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_commands.h"
28 #include "chrome/browser/ui/browser_iterator.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/common/chrome_paths.h"
31 #include "chrome/common/chrome_switches.h"
32 #include "chrome/common/pref_names.h"
33 #include "chrome/common/url_constants.h"
34 #include "chrome/test/base/in_process_browser_test.h"
35 #include "chrome/test/base/test_switches.h"
36 #include "chrome/test/base/ui_test_utils.h"
37 #include "content/public/browser/child_process_data.h"
38 #include "content/public/browser/content_browser_client.h"
39 #include "content/public/browser/devtools_agent_host.h"
40 #include "content/public/browser/devtools_client_host.h"
41 #include "content/public/browser/devtools_http_handler.h"
42 #include "content/public/browser/devtools_manager.h"
43 #include "content/public/browser/notification_registrar.h"
44 #include "content/public/browser/notification_service.h"
45 #include "content/public/browser/render_view_host.h"
46 #include "content/public/browser/web_contents.h"
47 #include "content/public/browser/worker_service.h"
48 #include "content/public/browser/worker_service_observer.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/test/browser_test_utils.h"
51 #include "extensions/browser/extension_system.h"
52 #include "extensions/common/switches.h"
53 #include "net/socket/tcp_listen_socket.h"
54 #include "net/test/spawned_test_server/spawned_test_server.h"
55 
56 using content::BrowserThread;
57 using content::DevToolsManager;
58 using content::DevToolsAgentHost;
59 using content::NavigationController;
60 using content::RenderViewHost;
61 using content::WebContents;
62 using content::WorkerService;
63 using content::WorkerServiceObserver;
64 
65 namespace {
66 
67 const char kDebuggerTestPage[] = "files/devtools/debugger_test_page.html";
68 const char kPauseWhenLoadingDevTools[] =
69     "files/devtools/pause_when_loading_devtools.html";
70 const char kPauseWhenScriptIsRunning[] =
71     "files/devtools/pause_when_script_is_running.html";
72 const char kPageWithContentScript[] =
73     "files/devtools/page_with_content_script.html";
74 const char kNavigateBackTestPage[] =
75     "files/devtools/navigate_back.html";
76 const char kChunkedTestPage[] = "chunked";
77 const char kSlowTestPage[] =
78     "chunked?waitBeforeHeaders=100&waitBetweenChunks=100&chunksNumber=2";
79 const char kSharedWorkerTestPage[] =
80     "files/workers/workers_ui_shared_worker.html";
81 const char kReloadSharedWorkerTestPage[] =
82     "files/workers/debug_shared_worker_initialization.html";
83 
RunTestFunction(DevToolsWindow * window,const char * test_name)84 void RunTestFunction(DevToolsWindow* window, const char* test_name) {
85   std::string result;
86 
87   // At first check that JavaScript part of the front-end is loaded by
88   // checking that global variable uiTests exists(it's created after all js
89   // files have been loaded) and has runTest method.
90   ASSERT_TRUE(
91       content::ExecuteScriptAndExtractString(
92           window->web_contents_for_test()->GetRenderViewHost(),
93           "window.domAutomationController.send("
94           "    '' + (window.uiTests && (typeof uiTests.runTest)));",
95           &result));
96 
97   ASSERT_EQ("function", result) << "DevTools front-end is broken.";
98   ASSERT_TRUE(content::ExecuteScriptAndExtractString(
99       window->web_contents_for_test()->GetRenderViewHost(),
100       base::StringPrintf("uiTests.runTest('%s')", test_name),
101       &result));
102   EXPECT_EQ("[OK]", result);
103 }
104 
105 }  // namespace
106 
107 class DevToolsSanityTest : public InProcessBrowserTest {
108  public:
DevToolsSanityTest()109   DevToolsSanityTest()
110       : window_(NULL),
111         inspected_rvh_(NULL) {}
112 
113  protected:
RunTest(const std::string & test_name,const std::string & test_page)114   void RunTest(const std::string& test_name, const std::string& test_page) {
115     OpenDevToolsWindow(test_page, false);
116     RunTestFunction(window_, test_name.c_str());
117     CloseDevToolsWindow();
118   }
119 
LoadTestPage(const std::string & test_page)120   void LoadTestPage(const std::string& test_page) {
121     GURL url = test_server()->GetURL(test_page);
122     ui_test_utils::NavigateToURL(browser(), url);
123   }
124 
OpenDevToolsWindow(const std::string & test_page,bool is_docked)125   void OpenDevToolsWindow(const std::string& test_page, bool is_docked) {
126     ASSERT_TRUE(test_server()->Start());
127     LoadTestPage(test_page);
128 
129     inspected_rvh_ = GetInspectedTab()->GetRenderViewHost();
130     window_ =
131         DevToolsWindow::OpenDevToolsWindowForTest(inspected_rvh_, is_docked);
132     ui_test_utils::WaitUntilDevToolsWindowLoaded(window_);
133   }
134 
GetInspectedTab()135   WebContents* GetInspectedTab() {
136     return browser()->tab_strip_model()->GetWebContentsAt(0);
137   }
138 
ToggleDevToolsWindow()139   void ToggleDevToolsWindow() {
140     content::WindowedNotificationObserver close_observer(
141         content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
142         content::Source<content::WebContents>(
143             window_->web_contents_for_test()));
144     DevToolsWindow::ToggleDevToolsWindow(inspected_rvh_, false,
145         DevToolsToggleAction::Toggle());
146     close_observer.Wait();
147   }
148 
ToggleDevToolsWindowDontWait()149   void ToggleDevToolsWindowDontWait() {
150     DevToolsWindow::ToggleDevToolsWindow(inspected_rvh_, false,
151         DevToolsToggleAction::Toggle());
152   }
153 
CloseDevToolsWindow()154   void CloseDevToolsWindow() {
155     DevToolsManager* devtools_manager = DevToolsManager::GetInstance();
156     content::WindowedNotificationObserver close_observer(
157         content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
158         content::Source<content::WebContents>(
159             window_->web_contents_for_test()));
160     devtools_manager->CloseAllClientHosts();
161     close_observer.Wait();
162   }
163 
164   DevToolsWindow* window_;
165   RenderViewHost* inspected_rvh_;
166 };
167 
168 // Used to block until a dev tools window gets beforeunload event.
169 class DevToolsWindowBeforeUnloadObserver
170     : public content::WebContentsObserver {
171  public:
172   explicit DevToolsWindowBeforeUnloadObserver(DevToolsWindow*);
173   void Wait();
174  private:
175   // Invoked when the beforeunload handler fires.
176   virtual void BeforeUnloadFired(const base::TimeTicks& proceed_time) OVERRIDE;
177 
178   bool m_fired;
179   scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
180   DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBeforeUnloadObserver);
181 };
182 
DevToolsWindowBeforeUnloadObserver(DevToolsWindow * devtools_window)183 DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver(
184     DevToolsWindow* devtools_window)
185     : WebContentsObserver(devtools_window->web_contents_for_test()),
186       m_fired(false) {
187 }
188 
Wait()189 void DevToolsWindowBeforeUnloadObserver::Wait() {
190   if (m_fired)
191     return;
192   message_loop_runner_ = new content::MessageLoopRunner;
193   message_loop_runner_->Run();
194 }
195 
BeforeUnloadFired(const base::TimeTicks & proceed_time)196 void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired(
197     const base::TimeTicks& proceed_time) {
198   m_fired = true;
199   if (message_loop_runner_.get())
200     message_loop_runner_->Quit();
201 }
202 
203 class DevToolsBeforeUnloadTest: public DevToolsSanityTest {
204  public:
SetUpCommandLine(CommandLine * command_line)205   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
206     command_line->AppendSwitch(
207         switches::kDisableHangMonitor);
208   }
209 
CloseInspectedTab()210   void CloseInspectedTab() {
211     browser()->tab_strip_model()->CloseWebContentsAt(0,
212         TabStripModel::CLOSE_NONE);
213   }
214 
CloseDockedDevTools()215   void CloseDockedDevTools() {
216     ToggleDevToolsWindowDontWait();
217   }
218 
CloseUndockedDevTools()219   void CloseUndockedDevTools() {
220     chrome::CloseWindow(window_->browser_for_test());
221   }
222 
CloseInspectedBrowser()223   void CloseInspectedBrowser() {
224     chrome::CloseWindow(browser());
225   }
226  protected:
InjectBeforeUnloadListener(content::WebContents * web_contents)227   void InjectBeforeUnloadListener(content::WebContents* web_contents) {
228     ASSERT_TRUE(content::ExecuteScript(web_contents->GetRenderViewHost(),
229         "window.addEventListener('beforeunload',"
230         "function(event) { event.returnValue = 'Foo'; });"));
231   }
232 
RunBeforeUnloadSanityTest(bool is_docked,base::Callback<void (void)> close_method,bool wait_for_browser_close=true)233   void RunBeforeUnloadSanityTest(bool is_docked,
234                                  base::Callback<void(void)> close_method,
235                                  bool wait_for_browser_close = true) {
236     OpenDevToolsWindow(kDebuggerTestPage, is_docked);
237     content::WindowedNotificationObserver devtools_close_observer(
238         content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
239         content::Source<content::WebContents>(
240             window_->web_contents_for_test()));
241     InjectBeforeUnloadListener(window_->web_contents_for_test());
242     {
243       DevToolsWindowBeforeUnloadObserver before_unload_observer(window_);
244       close_method.Run();
245       CancelModalDialog();
246       before_unload_observer.Wait();
247     }
248     {
249       content::WindowedNotificationObserver close_observer(
250           chrome::NOTIFICATION_BROWSER_CLOSED,
251           content::Source<Browser>(browser()));
252       close_method.Run();
253       AcceptModalDialog();
254       if (wait_for_browser_close)
255         close_observer.Wait();
256     }
257     devtools_close_observer.Wait();
258   }
259 
OpenDevToolWindowOnWebContents(content::WebContents * contents,bool is_docked)260   DevToolsWindow* OpenDevToolWindowOnWebContents(
261       content::WebContents* contents, bool is_docked) {
262     DevToolsWindow* window = DevToolsWindow::OpenDevToolsWindowForTest(
263         contents->GetRenderViewHost(), is_docked);
264     ui_test_utils::WaitUntilDevToolsWindowLoaded(window);
265     return window;
266   }
267 
OpenDevToolsPopupWindow(DevToolsWindow * devtools_window)268   void OpenDevToolsPopupWindow(DevToolsWindow* devtools_window) {
269     content::WindowedNotificationObserver observer(
270         content::NOTIFICATION_LOAD_STOP,
271         content::NotificationService::AllSources());
272     ASSERT_TRUE(content::ExecuteScript(
273         devtools_window->web_contents_for_test()->GetRenderViewHost(),
274         "window.open(\"\", \"\", \"location=0\");"));
275     observer.Wait();
276   }
277 
CloseDevToolsPopupWindow(DevToolsWindow * devtools_window)278   void CloseDevToolsPopupWindow(DevToolsWindow* devtools_window) {
279     Browser* popup_browser = NULL;
280     for (chrome::BrowserIterator it; !it.done(); it.Next()) {
281       if (it->is_devtools()) {
282         content::WebContents* contents =
283             it->tab_strip_model()->GetWebContentsAt(0);
284         if (devtools_window->web_contents_for_test() != contents) {
285           popup_browser = *it;
286           break;
287         }
288       }
289     }
290     ASSERT_FALSE(popup_browser == NULL);
291     content::WindowedNotificationObserver close_observer(
292         chrome::NOTIFICATION_BROWSER_CLOSED,
293         content::Source<Browser>(popup_browser));
294     chrome::CloseWindow(popup_browser);
295     close_observer.Wait();
296   }
297 
AcceptModalDialog()298   void AcceptModalDialog() {
299     NativeAppModalDialog* native_dialog = GetDialog();
300     native_dialog->AcceptAppModalDialog();
301   }
302 
CancelModalDialog()303   void CancelModalDialog() {
304     NativeAppModalDialog* native_dialog = GetDialog();
305     native_dialog->CancelAppModalDialog();
306   }
307 
GetDialog()308   NativeAppModalDialog* GetDialog() {
309     AppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog();
310     EXPECT_TRUE(dialog->IsJavaScriptModalDialog());
311     JavaScriptAppModalDialog* js_dialog =
312         static_cast<JavaScriptAppModalDialog*>(dialog);
313     NativeAppModalDialog* native_dialog = js_dialog->native_dialog();
314     EXPECT_TRUE(native_dialog);
315     return native_dialog;
316   }
317 };
318 
319 class DevToolsUnresponsiveBeforeUnloadTest: public DevToolsBeforeUnloadTest {
320  public:
SetUpCommandLine(CommandLine * command_line)321   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {}
322 };
323 
TimeoutCallback(const std::string & timeout_message)324 void TimeoutCallback(const std::string& timeout_message) {
325   ADD_FAILURE() << timeout_message;
326   base::MessageLoop::current()->Quit();
327 }
328 
329 // Base class for DevTools tests that test devtools functionality for
330 // extensions and content scripts.
331 class DevToolsExtensionTest : public DevToolsSanityTest,
332                               public content::NotificationObserver {
333  public:
DevToolsExtensionTest()334   DevToolsExtensionTest() : DevToolsSanityTest() {
335     PathService::Get(chrome::DIR_TEST_DATA, &test_extensions_dir_);
336     test_extensions_dir_ = test_extensions_dir_.AppendASCII("devtools");
337     test_extensions_dir_ = test_extensions_dir_.AppendASCII("extensions");
338   }
339 
340  protected:
341   // Load an extension from test\data\devtools\extensions\<extension_name>
LoadExtension(const char * extension_name)342   void LoadExtension(const char* extension_name) {
343     base::FilePath path = test_extensions_dir_.AppendASCII(extension_name);
344     ASSERT_TRUE(LoadExtensionFromPath(path)) << "Failed to load extension.";
345   }
346 
347  private:
LoadExtensionFromPath(const base::FilePath & path)348   bool LoadExtensionFromPath(const base::FilePath& path) {
349     ExtensionService* service = extensions::ExtensionSystem::Get(
350         browser()->profile())->extension_service();
351     size_t num_before = service->extensions()->size();
352     {
353       content::NotificationRegistrar registrar;
354       registrar.Add(this,
355                     chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
356                     content::NotificationService::AllSources());
357       base::CancelableClosure timeout(
358           base::Bind(&TimeoutCallback, "Extension load timed out."));
359       base::MessageLoop::current()->PostDelayedTask(
360           FROM_HERE, timeout.callback(), TestTimeouts::action_timeout());
361       extensions::UnpackedInstaller::Create(service)->Load(path);
362       content::RunMessageLoop();
363       timeout.Cancel();
364     }
365     size_t num_after = service->extensions()->size();
366     if (num_after != (num_before + 1))
367       return false;
368 
369     return WaitForExtensionViewsToLoad();
370   }
371 
WaitForExtensionViewsToLoad()372   bool WaitForExtensionViewsToLoad() {
373     // Wait for all the extension render views that exist to finish loading.
374     // NOTE: This assumes that the extension views list is not changing while
375     // this method is running.
376 
377     content::NotificationRegistrar registrar;
378     registrar.Add(this, chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING,
379                   content::NotificationService::AllSources());
380     base::CancelableClosure timeout(
381         base::Bind(&TimeoutCallback, "Extension host load timed out."));
382     base::MessageLoop::current()->PostDelayedTask(
383         FROM_HERE, timeout.callback(), TestTimeouts::action_timeout());
384 
385     extensions::ProcessManager* manager =
386         extensions::ExtensionSystem::Get(browser()->profile())->
387             process_manager();
388     extensions::ProcessManager::ViewSet all_views = manager->GetAllViews();
389     for (extensions::ProcessManager::ViewSet::const_iterator iter =
390              all_views.begin();
391          iter != all_views.end();) {
392       if (!(*iter)->IsLoading())
393         ++iter;
394       else
395         content::RunMessageLoop();
396     }
397 
398     timeout.Cancel();
399     return true;
400   }
401 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)402   virtual void Observe(int type,
403                        const content::NotificationSource& source,
404                        const content::NotificationDetails& details) OVERRIDE {
405     switch (type) {
406       case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED:
407       case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING:
408         base::MessageLoopForUI::current()->Quit();
409         break;
410       default:
411         NOTREACHED();
412         break;
413     }
414   }
415 
416   base::FilePath test_extensions_dir_;
417 };
418 
419 class DevToolsExperimentalExtensionTest : public DevToolsExtensionTest {
420  public:
SetUpCommandLine(CommandLine * command_line)421   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
422     command_line->AppendSwitch(
423         extensions::switches::kEnableExperimentalExtensionApis);
424   }
425 };
426 
427 class WorkerDevToolsSanityTest : public InProcessBrowserTest {
428  public:
WorkerDevToolsSanityTest()429   WorkerDevToolsSanityTest() : window_(NULL) {}
430 
431  protected:
432   class WorkerData : public base::RefCountedThreadSafe<WorkerData> {
433    public:
WorkerData()434     WorkerData() : worker_process_id(0), worker_route_id(0) {}
435     int worker_process_id;
436     int worker_route_id;
437 
438    private:
439     friend class base::RefCountedThreadSafe<WorkerData>;
~WorkerData()440     ~WorkerData() {}
441   };
442 
443   class WorkerCreationObserver : public WorkerServiceObserver {
444    public:
WorkerCreationObserver(WorkerData * worker_data)445     explicit WorkerCreationObserver(WorkerData* worker_data)
446         : worker_data_(worker_data) {
447     }
448 
449    private:
~WorkerCreationObserver()450     virtual ~WorkerCreationObserver() {}
451 
WorkerCreated(const GURL & url,const base::string16 & name,int process_id,int route_id)452     virtual void WorkerCreated (
453         const GURL& url,
454         const base::string16& name,
455         int process_id,
456         int route_id) OVERRIDE {
457       worker_data_->worker_process_id = process_id;
458       worker_data_->worker_route_id = route_id;
459       WorkerService::GetInstance()->RemoveObserver(this);
460       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
461           base::MessageLoop::QuitClosure());
462       delete this;
463     }
464     scoped_refptr<WorkerData> worker_data_;
465   };
466 
467   class WorkerTerminationObserver : public WorkerServiceObserver {
468    public:
WorkerTerminationObserver(WorkerData * worker_data)469     explicit WorkerTerminationObserver(WorkerData* worker_data)
470         : worker_data_(worker_data) {
471     }
472 
473    private:
~WorkerTerminationObserver()474     virtual ~WorkerTerminationObserver() {}
475 
WorkerDestroyed(int process_id,int route_id)476     virtual void WorkerDestroyed(int process_id, int route_id) OVERRIDE {
477       ASSERT_EQ(worker_data_->worker_process_id, process_id);
478       ASSERT_EQ(worker_data_->worker_route_id, route_id);
479       WorkerService::GetInstance()->RemoveObserver(this);
480       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
481           base::MessageLoop::QuitClosure());
482       delete this;
483     }
484     scoped_refptr<WorkerData> worker_data_;
485   };
486 
RunTest(const char * test_name,const char * test_page)487   void RunTest(const char* test_name, const char* test_page) {
488     ASSERT_TRUE(test_server()->Start());
489     GURL url = test_server()->GetURL(test_page);
490     ui_test_utils::NavigateToURL(browser(), url);
491 
492     scoped_refptr<WorkerData> worker_data = WaitForFirstSharedWorker();
493     OpenDevToolsWindowForSharedWorker(worker_data.get());
494     RunTestFunction(window_, test_name);
495     CloseDevToolsWindow();
496   }
497 
TerminateWorkerOnIOThread(scoped_refptr<WorkerData> worker_data)498   static void TerminateWorkerOnIOThread(scoped_refptr<WorkerData> worker_data) {
499     if (!WorkerService::GetInstance()->TerminateWorker(
500         worker_data->worker_process_id, worker_data->worker_route_id))
501       FAIL() << "Failed to terminate worker.\n";
502     WorkerService::GetInstance()->AddObserver(
503         new WorkerTerminationObserver(worker_data.get()));
504   }
505 
TerminateWorker(scoped_refptr<WorkerData> worker_data)506   static void TerminateWorker(scoped_refptr<WorkerData> worker_data) {
507     BrowserThread::PostTask(
508         BrowserThread::IO, FROM_HERE,
509         base::Bind(&TerminateWorkerOnIOThread, worker_data));
510     content::RunMessageLoop();
511   }
512 
WaitForFirstSharedWorkerOnIOThread(scoped_refptr<WorkerData> worker_data)513   static void WaitForFirstSharedWorkerOnIOThread(
514       scoped_refptr<WorkerData> worker_data) {
515     std::vector<WorkerService::WorkerInfo> worker_info =
516         WorkerService::GetInstance()->GetWorkers();
517     if (!worker_info.empty()) {
518       worker_data->worker_process_id = worker_info[0].process_id;
519       worker_data->worker_route_id = worker_info[0].route_id;
520       BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
521           base::MessageLoop::QuitClosure());
522       return;
523     }
524 
525     WorkerService::GetInstance()->AddObserver(
526         new WorkerCreationObserver(worker_data.get()));
527   }
528 
WaitForFirstSharedWorker()529   static scoped_refptr<WorkerData> WaitForFirstSharedWorker() {
530     scoped_refptr<WorkerData> worker_data(new WorkerData());
531     BrowserThread::PostTask(
532         BrowserThread::IO, FROM_HERE,
533         base::Bind(&WaitForFirstSharedWorkerOnIOThread, worker_data));
534     content::RunMessageLoop();
535     return worker_data;
536   }
537 
OpenDevToolsWindowForSharedWorker(WorkerData * worker_data)538   void OpenDevToolsWindowForSharedWorker(WorkerData* worker_data) {
539     Profile* profile = browser()->profile();
540     scoped_refptr<DevToolsAgentHost> agent_host(
541         DevToolsAgentHost::GetForWorker(
542             worker_data->worker_process_id,
543             worker_data->worker_route_id));
544     window_ = DevToolsWindow::OpenDevToolsWindowForWorker(profile, agent_host);
545     content::WaitForLoadStop(window_->web_contents_for_test());
546   }
547 
CloseDevToolsWindow()548   void CloseDevToolsWindow() {
549     Browser* browser = window_->browser_for_test();
550     content::WindowedNotificationObserver close_observer(
551         content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
552         content::Source<content::WebContents>(
553             window_->web_contents_for_test()));
554     browser->tab_strip_model()->CloseAllTabs();
555     close_observer.Wait();
556   }
557 
558   DevToolsWindow* window_;
559 };
560 
561 // Tests that BeforeUnload event gets called on docked devtools if
562 // we try to close them.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestDockedDevToolsClose)563 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestDockedDevToolsClose) {
564   RunBeforeUnloadSanityTest(true, base::Bind(
565       &DevToolsBeforeUnloadTest::CloseDockedDevTools, this), false);
566 }
567 
568 // Tests that BeforeUnload event gets called on docked devtools if
569 // we try to close the inspected page.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestDockedDevToolsInspectedTabClose)570 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
571                        TestDockedDevToolsInspectedTabClose) {
572   RunBeforeUnloadSanityTest(true, base::Bind(
573       &DevToolsBeforeUnloadTest::CloseInspectedTab, this));
574 }
575 
576 // Tests that BeforeUnload event gets called on docked devtools if
577 // we try to close the inspected browser.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestDockedDevToolsInspectedBrowserClose)578 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
579                        TestDockedDevToolsInspectedBrowserClose) {
580   RunBeforeUnloadSanityTest(true, base::Bind(
581       &DevToolsBeforeUnloadTest::CloseInspectedBrowser, this));
582 }
583 
584 // Tests that BeforeUnload event gets called on undocked devtools if
585 // we try to close them.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestUndockedDevToolsClose)586 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestUndockedDevToolsClose) {
587   RunBeforeUnloadSanityTest(false, base::Bind(
588       &DevToolsBeforeUnloadTest::CloseUndockedDevTools, this), false);
589 }
590 
591 // Tests that BeforeUnload event gets called on undocked devtools if
592 // we try to close the inspected page.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestUndockedDevToolsInspectedTabClose)593 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
594                        TestUndockedDevToolsInspectedTabClose) {
595   RunBeforeUnloadSanityTest(false, base::Bind(
596       &DevToolsBeforeUnloadTest::CloseInspectedTab, this));
597 }
598 
599 // Tests that BeforeUnload event gets called on undocked devtools if
600 // we try to close the inspected browser.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestUndockedDevToolsInspectedBrowserClose)601 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
602                        TestUndockedDevToolsInspectedBrowserClose) {
603   RunBeforeUnloadSanityTest(false, base::Bind(
604       &DevToolsBeforeUnloadTest::CloseInspectedBrowser, this));
605 }
606 
607 // Tests that BeforeUnload event gets called on undocked devtools if
608 // we try to exit application.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestUndockedDevToolsApplicationClose)609 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
610                        TestUndockedDevToolsApplicationClose) {
611   RunBeforeUnloadSanityTest(false, base::Bind(
612       &chrome::CloseAllBrowsers));
613 }
614 
615 // Tests that inspected tab gets closed if devtools renderer
616 // becomes unresponsive during beforeunload event interception.
617 // @see http://crbug.com/322380
IN_PROC_BROWSER_TEST_F(DevToolsUnresponsiveBeforeUnloadTest,TestUndockedDevToolsUnresponsive)618 IN_PROC_BROWSER_TEST_F(DevToolsUnresponsiveBeforeUnloadTest,
619                        TestUndockedDevToolsUnresponsive) {
620   ASSERT_TRUE(test_server()->Start());
621   LoadTestPage(kDebuggerTestPage);
622   DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
623       GetInspectedTab(), false);
624   content::WindowedNotificationObserver devtools_close_observer(
625       content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
626       content::Source<content::WebContents>(
627           devtools_window->web_contents_for_test()));
628 
629   ASSERT_TRUE(content::ExecuteScript(
630       devtools_window->web_contents_for_test()->GetRenderViewHost(),
631       "window.addEventListener('beforeunload',"
632       "function(event) { while (true); });"));
633   CloseInspectedTab();
634   devtools_close_observer.Wait();
635 }
636 
637 // Tests that closing worker inspector window does not cause browser crash
638 // @see http://crbug.com/323031
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestWorkerWindowClosing)639 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
640                        TestWorkerWindowClosing) {
641   ASSERT_TRUE(test_server()->Start());
642   LoadTestPage(kDebuggerTestPage);
643   DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
644       GetInspectedTab(), false);
645   content::WindowedNotificationObserver devtools_close_observer(
646       content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
647       content::Source<content::WebContents>(
648           devtools_window->web_contents_for_test()));
649 
650   OpenDevToolsPopupWindow(devtools_window);
651   CloseDevToolsPopupWindow(devtools_window);
652 }
653 
654 // Tests that BeforeUnload event gets called on devtools that are opened
655 // on another devtools.
IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,TestDevToolsOnDevTools)656 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
657                        TestDevToolsOnDevTools) {
658   ASSERT_TRUE(test_server()->Start());
659   LoadTestPage(kDebuggerTestPage);
660 
661   std::vector<DevToolsWindow*> windows;
662   std::vector<content::WindowedNotificationObserver*> close_observers;
663   content::WebContents* inspected_web_contents = GetInspectedTab();
664   for (int i = 0; i < 3; ++i) {
665     DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
666       inspected_web_contents, i == 0);
667     windows.push_back(devtools_window);
668     content::WindowedNotificationObserver* close_observer =
669         new content::WindowedNotificationObserver(
670                 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
671                 content::Source<content::WebContents>(
672                     devtools_window->web_contents_for_test()));
673     close_observers.push_back(close_observer);
674     inspected_web_contents = devtools_window->web_contents_for_test();
675   }
676 
677   InjectBeforeUnloadListener(windows[0]->web_contents_for_test());
678   InjectBeforeUnloadListener(windows[2]->web_contents_for_test());
679   // Try to close second devtools.
680   {
681     content::WindowedNotificationObserver cancel_browser(
682         chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
683         content::NotificationService::AllSources());
684     chrome::CloseWindow(windows[1]->browser_for_test());
685     CancelModalDialog();
686     cancel_browser.Wait();
687   }
688   // Try to close browser window.
689   {
690     content::WindowedNotificationObserver cancel_browser(
691         chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
692         content::NotificationService::AllSources());
693     chrome::CloseWindow(browser());
694     AcceptModalDialog();
695     CancelModalDialog();
696     cancel_browser.Wait();
697   }
698   // Try to exit application.
699   {
700     content::WindowedNotificationObserver close_observer(
701         chrome::NOTIFICATION_BROWSER_CLOSED,
702         content::Source<Browser>(browser()));
703     chrome::IncrementKeepAliveCount();
704     chrome::CloseAllBrowsers();
705     AcceptModalDialog();
706     AcceptModalDialog();
707     close_observer.Wait();
708   }
709   for (size_t i = 0; i < close_observers.size(); ++i) {
710     close_observers[i]->Wait();
711     delete close_observers[i];
712   }
713 }
714 
715 // Tests scripts panel showing.
716 // TODO(pfeldman): figure out flake.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,DISABLED_TestShowScriptsTab)717 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DISABLED_TestShowScriptsTab) {
718   RunTest("testShowScriptsTab", kDebuggerTestPage);
719 }
720 
721 // Tests that scripts tab is populated with inspected scripts even if it
722 // hadn't been shown by the moment inspected paged refreshed.
723 // @see http://crbug.com/26312
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestScriptsTabIsPopulatedOnInspectedPageRefresh)724 IN_PROC_BROWSER_TEST_F(
725     DevToolsSanityTest,
726     TestScriptsTabIsPopulatedOnInspectedPageRefresh) {
727   // Clear inspector settings to ensure that Elements will be
728   // current panel when DevTools window is open.
729   content::BrowserContext* browser_context =
730       GetInspectedTab()->GetBrowserContext();
731   Profile::FromBrowserContext(browser_context)->GetPrefs()->
732       ClearPref(prefs::kWebKitInspectorSettings);
733 
734   RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh",
735           kDebuggerTestPage);
736 }
737 
738 // Tests that chrome.devtools extension is correctly exposed.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,TestDevToolsExtensionAPI)739 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
740                        TestDevToolsExtensionAPI) {
741   LoadExtension("devtools_extension");
742   RunTest("waitForTestResultsInConsole", std::string());
743 }
744 
745 // Disabled on Windows due to flakiness. http://crbug.com/183649
746 #if defined(OS_WIN)
747 #define MAYBE_TestDevToolsExtensionMessaging DISABLED_TestDevToolsExtensionMessaging
748 #else
749 #define MAYBE_TestDevToolsExtensionMessaging TestDevToolsExtensionMessaging
750 #endif
751 
752 // Tests that chrome.devtools extension can communicate with background page
753 // using extension messaging.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,MAYBE_TestDevToolsExtensionMessaging)754 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
755                        MAYBE_TestDevToolsExtensionMessaging) {
756   LoadExtension("devtools_messaging");
757   RunTest("waitForTestResultsInConsole", std::string());
758 }
759 
760 // Tests that chrome.experimental.devtools extension is correctly exposed
761 // when the extension has experimental permission.
IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest,TestDevToolsExperimentalExtensionAPI)762 IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest,
763                        TestDevToolsExperimentalExtensionAPI) {
764   LoadExtension("devtools_experimental");
765   RunTest("waitForTestResultsInConsole", std::string());
766 }
767 
768 // Tests that a content script is in the scripts list.
769 // History of flakiness: http://crbug.com/114104, http://crbug.com/315288.
IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,DISABLED_TestContentScriptIsPresent)770 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
771                        DISABLED_TestContentScriptIsPresent) {
772   LoadExtension("simple_content_script");
773   RunTest("testContentScriptIsPresent", kPageWithContentScript);
774 }
775 
776 // Fails quite consistently on Win XP: crbug.com/317725.
777 #if defined(OS_WIN) || defined(OS_MACOSX)
778 #define MAYBE_TestNoScriptDuplicatesOnPanelSwitch \
779   DISABLED_TestNoScriptDuplicatesOnPanelSwitch
780 #else
781 #define MAYBE_TestNoScriptDuplicatesOnPanelSwitch \
782   TestNoScriptDuplicatesOnPanelSwitch
783 #endif
784 
785 // Tests that scripts are not duplicated after Scripts Panel switch.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,MAYBE_TestNoScriptDuplicatesOnPanelSwitch)786 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
787                        MAYBE_TestNoScriptDuplicatesOnPanelSwitch) {
788   RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage);
789 }
790 
791 // Tests that debugger works correctly if pause event occurs when DevTools
792 // frontend is being loaded.
793 // Disabled because of flakiness on all platforms: crbug.com/329036
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,DISABLED_TestPauseWhenLoadingDevTools)794 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
795                        DISABLED_TestPauseWhenLoadingDevTools) {
796   RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools);
797 }
798 
799 // Tests that pressing 'Pause' will pause script execution if the script
800 // is already running.
801 #if defined(OS_WIN)
802 // Timing out on windows tryservers: http://crbug.com/219515
803 #define MAYBE_TestPauseWhenScriptIsRunning DISABLED_TestPauseWhenScriptIsRunning
804 #elif defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
805 // Timing out on linux ARM bot: https://crbug/238453
806 #define MAYBE_TestPauseWhenScriptIsRunning DISABLED_TestPauseWhenScriptIsRunning
807 #else
808 #define MAYBE_TestPauseWhenScriptIsRunning TestPauseWhenScriptIsRunning
809 #endif
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,MAYBE_TestPauseWhenScriptIsRunning)810 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
811                        MAYBE_TestPauseWhenScriptIsRunning) {
812   RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning);
813 }
814 
815 // Tests network timing.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestNetworkTiming)816 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkTiming) {
817   RunTest("testNetworkTiming", kSlowTestPage);
818 }
819 
820 // Tests network size.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestNetworkSize)821 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSize) {
822   RunTest("testNetworkSize", kChunkedTestPage);
823 }
824 
825 // Tests raw headers text.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestNetworkSyncSize)826 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSyncSize) {
827   RunTest("testNetworkSyncSize", kChunkedTestPage);
828 }
829 
830 // Tests raw headers text.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestNetworkRawHeadersText)831 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkRawHeadersText) {
832   RunTest("testNetworkRawHeadersText", kChunkedTestPage);
833 }
834 
835 // Tests that console messages are not duplicated on navigation back.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestConsoleOnNavigateBack)836 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestConsoleOnNavigateBack) {
837   RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage);
838 }
839 
840 
841 #if defined(OS_CHROMEOS)
842 #define MAYBE_TestDeviceEmulation DISABLED_TestDeviceEmulation
843 #else
844 #define MAYBE_TestDeviceEmulation TestDeviceEmulation
845 #endif
846 // ChromeOS has --enable-pinch-virtual-viewport on by default: crbug.com/370035.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,MAYBE_TestDeviceEmulation)847 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, MAYBE_TestDeviceEmulation) {
848   RunTest("testDeviceMetricsOverrides", "about:blank");
849 }
850 
851 
852 // Tests that external navigation from inspector page is always handled by
853 // DevToolsWindow and results in inspected page navigation.
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestDevToolsExternalNavigation)854 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestDevToolsExternalNavigation) {
855   OpenDevToolsWindow(kDebuggerTestPage, true);
856   GURL url = test_server()->GetURL(kNavigateBackTestPage);
857   // TODO(dgozman): remove this once notifications are gone.
858   // Right now notifications happen after observers, so DevTools window is
859   // already loaded, but we still catch it's notification when looking for
860   // all sources.
861   content::WaitForLoadStop(window_->web_contents_for_test());
862   content::WindowedNotificationObserver observer(
863       content::NOTIFICATION_LOAD_STOP,
864       content::NotificationService::AllSources());
865   ASSERT_TRUE(content::ExecuteScript(
866       window_->web_contents_for_test(),
867       std::string("window.location = \"") + url.spec() + "\""));
868   observer.Wait();
869 
870   ASSERT_TRUE(window_->web_contents_for_test()->GetURL().
871                   SchemeIs(content::kChromeDevToolsScheme));
872   ASSERT_EQ(url, GetInspectedTab()->GetURL());
873   CloseDevToolsWindow();
874 }
875 
876 // Tests that inspector will reattach to inspected page when it is reloaded
877 // after a crash. See http://crbug.com/101952
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestReattachAfterCrash)878 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestReattachAfterCrash) {
879   RunTest("testReattachAfterCrash", std::string());
880 }
881 
IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,TestPageWithNoJavaScript)882 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPageWithNoJavaScript) {
883   OpenDevToolsWindow("about:blank", false);
884   std::string result;
885   ASSERT_TRUE(
886       content::ExecuteScriptAndExtractString(
887           window_->web_contents_for_test()->GetRenderViewHost(),
888           "window.domAutomationController.send("
889           "    '' + (window.uiTests && (typeof uiTests.runTest)));",
890           &result));
891   ASSERT_EQ("function", result) << "DevTools front-end is broken.";
892   CloseDevToolsWindow();
893 }
894 
895 #if defined(OS_MACOSX)
896 #define MAYBE_InspectSharedWorker DISABLED_InspectSharedWorker
897 #else
898 #define MAYBE_InspectSharedWorker InspectSharedWorker
899 #endif
900 // Flakily fails with 25s timeout: http://crbug.com/89845
IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest,MAYBE_InspectSharedWorker)901 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, MAYBE_InspectSharedWorker) {
902 #if defined(OS_WIN) && defined(USE_ASH)
903   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
904   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
905     return;
906 #endif
907 
908   RunTest("testSharedWorker", kSharedWorkerTestPage);
909 }
910 
911 // http://crbug.com/100538
912 #if defined(OS_MACOSX) || defined(OS_WIN)
913 #define MAYBE_PauseInSharedWorkerInitialization DISABLED_PauseInSharedWorkerInitialization
914 #else
915 #define MAYBE_PauseInSharedWorkerInitialization PauseInSharedWorkerInitialization
916 #endif
917 
918 // http://crbug.com/106114 is masking
919 // MAYBE_PauseInSharedWorkerInitialization into
920 // DISABLED_PauseInSharedWorkerInitialization
IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest,MAYBE_PauseInSharedWorkerInitialization)921 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest,
922                        MAYBE_PauseInSharedWorkerInitialization) {
923   ASSERT_TRUE(test_server()->Start());
924   GURL url = test_server()->GetURL(kReloadSharedWorkerTestPage);
925   ui_test_utils::NavigateToURL(browser(), url);
926 
927   scoped_refptr<WorkerData> worker_data = WaitForFirstSharedWorker();
928   OpenDevToolsWindowForSharedWorker(worker_data.get());
929 
930   TerminateWorker(worker_data);
931 
932   // Reload page to restart the worker.
933   ui_test_utils::NavigateToURL(browser(), url);
934 
935   // Wait until worker script is paused on the debugger statement.
936   RunTestFunction(window_, "testPauseInSharedWorkerInitialization");
937   CloseDevToolsWindow();
938 }
939 
940 class DevToolsAgentHostTest : public InProcessBrowserTest {};
941 
942 // Tests DevToolsAgentHost retention by its target.
IN_PROC_BROWSER_TEST_F(DevToolsAgentHostTest,TestAgentHostReleased)943 IN_PROC_BROWSER_TEST_F(DevToolsAgentHostTest, TestAgentHostReleased) {
944   ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
945   RenderViewHost* rvh = browser()->tab_strip_model()->GetWebContentsAt(0)->
946       GetRenderViewHost();
947   DevToolsAgentHost* agent_raw = DevToolsAgentHost::GetOrCreateFor(rvh).get();
948   const std::string agent_id = agent_raw->GetId();
949   ASSERT_EQ(agent_raw, DevToolsAgentHost::GetForId(agent_id)) <<
950       "DevToolsAgentHost cannot be found by id";
951   browser()->tab_strip_model()->
952       CloseWebContentsAt(0, TabStripModel::CLOSE_NONE);
953   ASSERT_FALSE(DevToolsAgentHost::GetForId(agent_id).get())
954       << "DevToolsAgentHost is not released when the tab is closed";
955 }
956 
957 class RemoteDebuggingTest: public ExtensionApiTest {
SetUpCommandLine(CommandLine * command_line)958   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
959     ExtensionApiTest::SetUpCommandLine(command_line);
960     command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort, "9222");
961 
962     // Override the extension root path.
963     PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
964     test_data_dir_ = test_data_dir_.AppendASCII("devtools");
965   }
966 };
967 
IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest,RemoteDebugger)968 IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest, RemoteDebugger) {
969 #if defined(OS_WIN) && defined(USE_ASH)
970   // Disable this test in Metro+Ash for now (http://crbug.com/262796).
971   if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests))
972     return;
973 #endif
974 
975   ASSERT_TRUE(RunExtensionTest("target_list")) << message_;
976 }
977