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