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/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"
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
;
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";
84 void RunTestFunction(DevToolsWindow
* window
, const char* test_name
) {
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.
91 content::ExecuteScriptAndExtractString(
92 window
->web_contents_for_test()->GetRenderViewHost(),
93 "window.domAutomationController.send("
94 " '' + (window.uiTests && (typeof uiTests.runTest)));",
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
),
102 EXPECT_EQ("[OK]", result
);
107 class DevToolsSanityTest
: public InProcessBrowserTest
{
111 inspected_rvh_(NULL
) {}
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();
120 void LoadTestPage(const std::string
& test_page
) {
121 GURL url
= test_server()->GetURL(test_page
);
122 ui_test_utils::NavigateToURL(browser(), url
);
125 void OpenDevToolsWindow(const std::string
& test_page
, bool is_docked
) {
126 ASSERT_TRUE(test_server()->Start());
127 LoadTestPage(test_page
);
129 inspected_rvh_
= GetInspectedTab()->GetRenderViewHost();
131 DevToolsWindow::OpenDevToolsWindowForTest(inspected_rvh_
, is_docked
);
132 ui_test_utils::WaitUntilDevToolsWindowLoaded(window_
);
135 WebContents
* GetInspectedTab() {
136 return browser()->tab_strip_model()->GetWebContentsAt(0);
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();
149 void ToggleDevToolsWindowDontWait() {
150 DevToolsWindow::ToggleDevToolsWindow(inspected_rvh_
, false,
151 DevToolsToggleAction::Toggle());
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();
164 DevToolsWindow
* window_
;
165 RenderViewHost
* inspected_rvh_
;
168 // Used to block until a dev tools window gets beforeunload event.
169 class DevToolsWindowBeforeUnloadObserver
170 : public content::WebContentsObserver
{
172 explicit DevToolsWindowBeforeUnloadObserver(DevToolsWindow
*);
175 // Invoked when the beforeunload handler fires.
176 virtual void BeforeUnloadFired(const base::TimeTicks
& proceed_time
) OVERRIDE
;
179 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
180 DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBeforeUnloadObserver
);
183 DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver(
184 DevToolsWindow
* devtools_window
)
185 : WebContentsObserver(devtools_window
->web_contents_for_test()),
189 void DevToolsWindowBeforeUnloadObserver::Wait() {
192 message_loop_runner_
= new content::MessageLoopRunner
;
193 message_loop_runner_
->Run();
196 void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired(
197 const base::TimeTicks
& proceed_time
) {
199 if (message_loop_runner_
.get())
200 message_loop_runner_
->Quit();
203 class DevToolsBeforeUnloadTest
: public DevToolsSanityTest
{
205 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
206 command_line
->AppendSwitch(
207 switches::kDisableHangMonitor
);
210 void CloseInspectedTab() {
211 browser()->tab_strip_model()->CloseWebContentsAt(0,
212 TabStripModel::CLOSE_NONE
);
215 void CloseDockedDevTools() {
216 ToggleDevToolsWindowDontWait();
219 void CloseUndockedDevTools() {
220 chrome::CloseWindow(window_
->browser_for_test());
223 void CloseInspectedBrowser() {
224 chrome::CloseWindow(browser());
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'; });"));
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());
243 DevToolsWindowBeforeUnloadObserver
before_unload_observer(window_
);
246 before_unload_observer
.Wait();
249 content::WindowedNotificationObserver
close_observer(
250 chrome::NOTIFICATION_BROWSER_CLOSED
,
251 content::Source
<Browser
>(browser()));
254 if (wait_for_browser_close
)
255 close_observer
.Wait();
257 devtools_close_observer
.Wait();
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
);
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\");"));
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
) {
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();
298 void AcceptModalDialog() {
299 NativeAppModalDialog
* native_dialog
= GetDialog();
300 native_dialog
->AcceptAppModalDialog();
303 void CancelModalDialog() {
304 NativeAppModalDialog
* native_dialog
= GetDialog();
305 native_dialog
->CancelAppModalDialog();
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
;
319 class DevToolsUnresponsiveBeforeUnloadTest
: public DevToolsBeforeUnloadTest
{
321 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{}
324 void TimeoutCallback(const std::string
& timeout_message
) {
325 ADD_FAILURE() << timeout_message
;
326 base::MessageLoop::current()->Quit();
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
{
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");
341 // Load an extension from test\data\devtools\extensions\<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.";
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();
353 content::NotificationRegistrar registrar
;
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();
365 size_t num_after
= service
->extensions()->size();
366 if (num_after
!= (num_before
+ 1))
369 return 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.
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());
385 extensions::ProcessManager
* manager
=
386 extensions::ExtensionSystem::Get(browser()->profile())->
388 extensions::ProcessManager::ViewSet all_views
= manager
->GetAllViews();
389 for (extensions::ProcessManager::ViewSet::const_iterator iter
=
391 iter
!= all_views
.end();) {
392 if (!(*iter
)->IsLoading())
395 content::RunMessageLoop();
402 virtual void Observe(int type
,
403 const content::NotificationSource
& source
,
404 const content::NotificationDetails
& details
) OVERRIDE
{
406 case chrome::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
:
407 case chrome::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING
:
408 base::MessageLoopForUI::current()->Quit();
416 base::FilePath test_extensions_dir_
;
419 class DevToolsExperimentalExtensionTest
: public DevToolsExtensionTest
{
421 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
422 command_line
->AppendSwitch(
423 extensions::switches::kEnableExperimentalExtensionApis
);
427 class WorkerDevToolsSanityTest
: public InProcessBrowserTest
{
429 WorkerDevToolsSanityTest() : window_(NULL
) {}
432 class WorkerData
: public base::RefCountedThreadSafe
<WorkerData
> {
434 WorkerData() : worker_process_id(0), worker_route_id(0) {}
435 int worker_process_id
;
439 friend class base::RefCountedThreadSafe
<WorkerData
>;
443 class WorkerCreationObserver
: public WorkerServiceObserver
{
445 explicit WorkerCreationObserver(WorkerData
* worker_data
)
446 : worker_data_(worker_data
) {
450 virtual ~WorkerCreationObserver() {}
452 virtual void WorkerCreated (
454 const base::string16
& name
,
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());
464 scoped_refptr
<WorkerData
> worker_data_
;
467 class WorkerTerminationObserver
: public WorkerServiceObserver
{
469 explicit WorkerTerminationObserver(WorkerData
* worker_data
)
470 : worker_data_(worker_data
) {
474 virtual ~WorkerTerminationObserver() {}
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());
484 scoped_refptr
<WorkerData
> worker_data_
;
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
);
492 scoped_refptr
<WorkerData
> worker_data
= WaitForFirstSharedWorker();
493 OpenDevToolsWindowForSharedWorker(worker_data
.get());
494 RunTestFunction(window_
, test_name
);
495 CloseDevToolsWindow();
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()));
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();
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());
525 WorkerService::GetInstance()->AddObserver(
526 new WorkerCreationObserver(worker_data
.get()));
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();
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());
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();
558 DevToolsWindow
* window_
;
561 // Tests that BeforeUnload event gets called on docked devtools if
562 // we try to close them.
563 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
, TestDockedDevToolsClose
) {
564 RunBeforeUnloadSanityTest(true, base::Bind(
565 &DevToolsBeforeUnloadTest::CloseDockedDevTools
, this), false);
568 // Tests that BeforeUnload event gets called on docked devtools if
569 // we try to close the inspected page.
570 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
571 TestDockedDevToolsInspectedTabClose
) {
572 RunBeforeUnloadSanityTest(true, base::Bind(
573 &DevToolsBeforeUnloadTest::CloseInspectedTab
, this));
576 // Tests that BeforeUnload event gets called on docked devtools if
577 // we try to close the inspected browser.
578 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
579 TestDockedDevToolsInspectedBrowserClose
) {
580 RunBeforeUnloadSanityTest(true, base::Bind(
581 &DevToolsBeforeUnloadTest::CloseInspectedBrowser
, this));
584 // Tests that BeforeUnload event gets called on undocked devtools if
585 // we try to close them.
586 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
, TestUndockedDevToolsClose
) {
587 RunBeforeUnloadSanityTest(false, base::Bind(
588 &DevToolsBeforeUnloadTest::CloseUndockedDevTools
, this), false);
591 // Tests that BeforeUnload event gets called on undocked devtools if
592 // we try to close the inspected page.
593 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
594 TestUndockedDevToolsInspectedTabClose
) {
595 RunBeforeUnloadSanityTest(false, base::Bind(
596 &DevToolsBeforeUnloadTest::CloseInspectedTab
, this));
599 // Tests that BeforeUnload event gets called on undocked devtools if
600 // we try to close the inspected browser.
601 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
602 TestUndockedDevToolsInspectedBrowserClose
) {
603 RunBeforeUnloadSanityTest(false, base::Bind(
604 &DevToolsBeforeUnloadTest::CloseInspectedBrowser
, this));
607 // Tests that BeforeUnload event gets called on undocked devtools if
608 // we try to exit application.
609 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
610 TestUndockedDevToolsApplicationClose
) {
611 RunBeforeUnloadSanityTest(false, base::Bind(
612 &chrome::CloseAllBrowsers
));
615 // Tests that inspected tab gets closed if devtools renderer
616 // becomes unresponsive during beforeunload event interception.
617 // @see http://crbug.com/322380
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()));
629 ASSERT_TRUE(content::ExecuteScript(
630 devtools_window
->web_contents_for_test()->GetRenderViewHost(),
631 "window.addEventListener('beforeunload',"
632 "function(event) { while (true); });"));
634 devtools_close_observer
.Wait();
637 // Tests that closing worker inspector window does not cause browser crash
638 // @see http://crbug.com/323031
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()));
650 OpenDevToolsPopupWindow(devtools_window
);
651 CloseDevToolsPopupWindow(devtools_window
);
654 // Tests that BeforeUnload event gets called on devtools that are opened
655 // on another devtools.
656 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
657 TestDevToolsOnDevTools
) {
658 ASSERT_TRUE(test_server()->Start());
659 LoadTestPage(kDebuggerTestPage
);
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();
677 InjectBeforeUnloadListener(windows
[0]->web_contents_for_test());
678 InjectBeforeUnloadListener(windows
[2]->web_contents_for_test());
679 // Try to close second devtools.
681 content::WindowedNotificationObserver
cancel_browser(
682 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
,
683 content::NotificationService::AllSources());
684 chrome::CloseWindow(windows
[1]->browser_for_test());
686 cancel_browser
.Wait();
688 // Try to close browser window.
690 content::WindowedNotificationObserver
cancel_browser(
691 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
,
692 content::NotificationService::AllSources());
693 chrome::CloseWindow(browser());
696 cancel_browser
.Wait();
698 // Try to exit application.
700 content::WindowedNotificationObserver
close_observer(
701 chrome::NOTIFICATION_BROWSER_CLOSED
,
702 content::Source
<Browser
>(browser()));
703 chrome::IncrementKeepAliveCount();
704 chrome::CloseAllBrowsers();
707 close_observer
.Wait();
709 for (size_t i
= 0; i
< close_observers
.size(); ++i
) {
710 close_observers
[i
]->Wait();
711 delete close_observers
[i
];
715 // Tests scripts panel showing.
716 // TODO(pfeldman): figure out flake.
717 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, DISABLED_TestShowScriptsTab
) {
718 RunTest("testShowScriptsTab", kDebuggerTestPage
);
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
724 IN_PROC_BROWSER_TEST_F(
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
);
734 RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh",
738 // Tests that chrome.devtools extension is correctly exposed.
739 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest
,
740 TestDevToolsExtensionAPI
) {
741 LoadExtension("devtools_extension");
742 RunTest("waitForTestResultsInConsole", std::string());
745 // Disabled on Windows due to flakiness. http://crbug.com/183649
747 #define MAYBE_TestDevToolsExtensionMessaging DISABLED_TestDevToolsExtensionMessaging
749 #define MAYBE_TestDevToolsExtensionMessaging TestDevToolsExtensionMessaging
752 // Tests that chrome.devtools extension can communicate with background page
753 // using extension messaging.
754 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest
,
755 MAYBE_TestDevToolsExtensionMessaging
) {
756 LoadExtension("devtools_messaging");
757 RunTest("waitForTestResultsInConsole", std::string());
760 // Tests that chrome.experimental.devtools extension is correctly exposed
761 // when the extension has experimental permission.
762 IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest
,
763 TestDevToolsExperimentalExtensionAPI
) {
764 LoadExtension("devtools_experimental");
765 RunTest("waitForTestResultsInConsole", std::string());
768 // Tests that a content script is in the scripts list.
769 // History of flakiness: http://crbug.com/114104, http://crbug.com/315288.
770 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest
,
771 DISABLED_TestContentScriptIsPresent
) {
772 LoadExtension("simple_content_script");
773 RunTest("testContentScriptIsPresent", kPageWithContentScript
);
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
781 #define MAYBE_TestNoScriptDuplicatesOnPanelSwitch \
782 TestNoScriptDuplicatesOnPanelSwitch
785 // Tests that scripts are not duplicated after Scripts Panel switch.
786 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
,
787 MAYBE_TestNoScriptDuplicatesOnPanelSwitch
) {
788 RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage
);
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
794 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
,
795 DISABLED_TestPauseWhenLoadingDevTools
) {
796 RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools
);
799 // Tests that pressing 'Pause' will pause script execution if the script
800 // is already running.
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
808 #define MAYBE_TestPauseWhenScriptIsRunning TestPauseWhenScriptIsRunning
810 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
,
811 MAYBE_TestPauseWhenScriptIsRunning
) {
812 RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning
);
815 // Tests network timing.
816 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkTiming
) {
817 RunTest("testNetworkTiming", kSlowTestPage
);
820 // Tests network size.
821 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkSize
) {
822 RunTest("testNetworkSize", kChunkedTestPage
);
825 // Tests raw headers text.
826 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkSyncSize
) {
827 RunTest("testNetworkSyncSize", kChunkedTestPage
);
830 // Tests raw headers text.
831 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkRawHeadersText
) {
832 RunTest("testNetworkRawHeadersText", kChunkedTestPage
);
835 // Tests that console messages are not duplicated on navigation back.
836 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestConsoleOnNavigateBack
) {
837 RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage
);
841 #if defined(OS_CHROMEOS)
842 #define MAYBE_TestDeviceEmulation DISABLED_TestDeviceEmulation
844 #define MAYBE_TestDeviceEmulation TestDeviceEmulation
846 // ChromeOS has --enable-pinch-virtual-viewport on by default: crbug.com/370035.
847 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, MAYBE_TestDeviceEmulation
) {
848 RunTest("testDeviceMetricsOverrides", "about:blank");
852 // Tests that external navigation from inspector page is always handled by
853 // DevToolsWindow and results in inspected page navigation.
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
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() + "\""));
870 ASSERT_TRUE(window_
->web_contents_for_test()->GetURL().
871 SchemeIs(content::kChromeDevToolsScheme
));
872 ASSERT_EQ(url
, GetInspectedTab()->GetURL());
873 CloseDevToolsWindow();
876 // Tests that inspector will reattach to inspected page when it is reloaded
877 // after a crash. See http://crbug.com/101952
878 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestReattachAfterCrash
) {
879 RunTest("testReattachAfterCrash", std::string());
882 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestPageWithNoJavaScript
) {
883 OpenDevToolsWindow("about:blank", false);
886 content::ExecuteScriptAndExtractString(
887 window_
->web_contents_for_test()->GetRenderViewHost(),
888 "window.domAutomationController.send("
889 " '' + (window.uiTests && (typeof uiTests.runTest)));",
891 ASSERT_EQ("function", result
) << "DevTools front-end is broken.";
892 CloseDevToolsWindow();
895 #if defined(OS_MACOSX)
896 #define MAYBE_InspectSharedWorker DISABLED_InspectSharedWorker
898 #define MAYBE_InspectSharedWorker InspectSharedWorker
900 // Flakily fails with 25s timeout: http://crbug.com/89845
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
))
908 RunTest("testSharedWorker", kSharedWorkerTestPage
);
911 // http://crbug.com/100538
912 #if defined(OS_MACOSX) || defined(OS_WIN)
913 #define MAYBE_PauseInSharedWorkerInitialization DISABLED_PauseInSharedWorkerInitialization
915 #define MAYBE_PauseInSharedWorkerInitialization PauseInSharedWorkerInitialization
918 // http://crbug.com/106114 is masking
919 // MAYBE_PauseInSharedWorkerInitialization into
920 // DISABLED_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
);
927 scoped_refptr
<WorkerData
> worker_data
= WaitForFirstSharedWorker();
928 OpenDevToolsWindowForSharedWorker(worker_data
.get());
930 TerminateWorker(worker_data
);
932 // Reload page to restart the worker.
933 ui_test_utils::NavigateToURL(browser(), url
);
935 // Wait until worker script is paused on the debugger statement.
936 RunTestFunction(window_
, "testPauseInSharedWorkerInitialization");
937 CloseDevToolsWindow();
940 class DevToolsAgentHostTest
: public InProcessBrowserTest
{};
942 // Tests DevToolsAgentHost retention by its target.
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)->
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";
957 class RemoteDebuggingTest
: public ExtensionApiTest
{
958 virtual void SetUpCommandLine(CommandLine
* command_line
) OVERRIDE
{
959 ExtensionApiTest::SetUpCommandLine(command_line
);
960 command_line
->AppendSwitchASCII(switches::kRemoteDebuggingPort
, "9222");
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");
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
))
975 ASSERT_TRUE(RunExtensionTest("target_list")) << message_
;