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_testing.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/browser.h"
25 #include "chrome/browser/ui/browser_commands.h"
26 #include "chrome/browser/ui/browser_iterator.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/common/chrome_paths.h"
29 #include "chrome/common/chrome_switches.h"
30 #include "chrome/common/url_constants.h"
31 #include "chrome/test/base/in_process_browser_test.h"
32 #include "chrome/test/base/test_switches.h"
33 #include "chrome/test/base/ui_test_utils.h"
34 #include "components/app_modal/javascript_app_modal_dialog.h"
35 #include "components/app_modal/native_app_modal_dialog.h"
36 #include "content/public/browser/child_process_data.h"
37 #include "content/public/browser/content_browser_client.h"
38 #include "content/public/browser/devtools_agent_host.h"
39 #include "content/public/browser/devtools_http_handler.h"
40 #include "content/public/browser/notification_registrar.h"
41 #include "content/public/browser/notification_service.h"
42 #include "content/public/browser/render_view_host.h"
43 #include "content/public/browser/web_contents.h"
44 #include "content/public/browser/worker_service.h"
45 #include "content/public/browser/worker_service_observer.h"
46 #include "content/public/common/content_switches.h"
47 #include "content/public/test/browser_test_utils.h"
48 #include "extensions/browser/extension_registry.h"
49 #include "extensions/browser/extension_system.h"
50 #include "extensions/browser/notification_types.h"
51 #include "extensions/common/switches.h"
52 #include "net/socket/tcp_listen_socket.h"
53 #include "net/test/spawned_test_server/spawned_test_server.h"
55 using app_modal::AppModalDialog
;
56 using app_modal::JavaScriptAppModalDialog
;
57 using app_modal::NativeAppModalDialog
;
58 using content::BrowserThread
;
59 using content::DevToolsAgentHost
;
60 using content::NavigationController
;
61 using content::RenderViewHost
;
62 using content::WebContents
;
63 using content::WorkerService
;
64 using content::WorkerServiceObserver
;
68 const char kDebuggerTestPage
[] = "files/devtools/debugger_test_page.html";
69 const char kPauseWhenLoadingDevTools
[] =
70 "files/devtools/pause_when_loading_devtools.html";
71 const char kPauseWhenScriptIsRunning
[] =
72 "files/devtools/pause_when_script_is_running.html";
73 const char kPageWithContentScript
[] =
74 "files/devtools/page_with_content_script.html";
75 const char kNavigateBackTestPage
[] =
76 "files/devtools/navigate_back.html";
77 const char kChunkedTestPage
[] = "chunked";
78 const char kSlowTestPage
[] =
79 "chunked?waitBeforeHeaders=100&waitBetweenChunks=100&chunksNumber=2";
80 const char kSharedWorkerTestPage
[] =
81 "files/workers/workers_ui_shared_worker.html";
82 const char kSharedWorkerTestWorker
[] =
83 "files/workers/workers_ui_shared_worker.js";
84 const char kReloadSharedWorkerTestPage
[] =
85 "files/workers/debug_shared_worker_initialization.html";
86 const char kReloadSharedWorkerTestWorker
[] =
87 "files/workers/debug_shared_worker_initialization.js";
89 void RunTestFunction(DevToolsWindow
* window
, const char* test_name
) {
92 RenderViewHost
* rvh
= DevToolsWindowTesting::Get(window
)->
93 main_web_contents()->GetRenderViewHost();
94 // At first check that JavaScript part of the front-end is loaded by
95 // checking that global variable uiTests exists(it's created after all js
96 // files have been loaded) and has runTest method.
98 content::ExecuteScriptAndExtractString(
100 "window.domAutomationController.send("
101 " '' + (window.uiTests && (typeof uiTests.runTest)));",
104 ASSERT_EQ("function", result
) << "DevTools front-end is broken.";
105 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
107 base::StringPrintf("uiTests.runTest('%s')", test_name
),
109 EXPECT_EQ("[OK]", result
);
114 class DevToolsSanityTest
: public InProcessBrowserTest
{
116 DevToolsSanityTest() : window_(NULL
) {}
119 void RunTest(const std::string
& test_name
, const std::string
& test_page
) {
120 OpenDevToolsWindow(test_page
, false);
121 RunTestFunction(window_
, test_name
.c_str());
122 CloseDevToolsWindow();
125 void LoadTestPage(const std::string
& test_page
) {
126 GURL url
= test_server()->GetURL(test_page
);
127 ui_test_utils::NavigateToURL(browser(), url
);
130 void OpenDevToolsWindow(const std::string
& test_page
, bool is_docked
) {
131 ASSERT_TRUE(test_server()->Start());
132 LoadTestPage(test_page
);
134 window_
= DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(),
138 WebContents
* GetInspectedTab() {
139 return browser()->tab_strip_model()->GetWebContentsAt(0);
142 void CloseDevToolsWindow() {
143 DevToolsWindowTesting::CloseDevToolsWindowSync(window_
);
146 WebContents
* main_web_contents() {
147 return DevToolsWindowTesting::Get(window_
)->main_web_contents();
150 WebContents
* toolbox_web_contents() {
151 return DevToolsWindowTesting::Get(window_
)->toolbox_web_contents();
154 DevToolsWindow
* window_
;
157 // Used to block until a dev tools window gets beforeunload event.
158 class DevToolsWindowBeforeUnloadObserver
159 : public content::WebContentsObserver
{
161 explicit DevToolsWindowBeforeUnloadObserver(DevToolsWindow
*);
164 // Invoked when the beforeunload handler fires.
165 void BeforeUnloadFired(const base::TimeTicks
& proceed_time
) override
;
168 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
169 DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBeforeUnloadObserver
);
172 DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver(
173 DevToolsWindow
* devtools_window
)
174 : WebContentsObserver(
175 DevToolsWindowTesting::Get(devtools_window
)->main_web_contents()),
179 void DevToolsWindowBeforeUnloadObserver::Wait() {
182 message_loop_runner_
= new content::MessageLoopRunner
;
183 message_loop_runner_
->Run();
186 void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired(
187 const base::TimeTicks
& proceed_time
) {
189 if (message_loop_runner_
.get())
190 message_loop_runner_
->Quit();
193 class DevToolsBeforeUnloadTest
: public DevToolsSanityTest
{
195 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
196 command_line
->AppendSwitch(
197 switches::kDisableHangMonitor
);
200 void CloseInspectedTab() {
201 browser()->tab_strip_model()->CloseWebContentsAt(0,
202 TabStripModel::CLOSE_NONE
);
205 void CloseDevToolsWindowAsync() {
206 DevToolsWindowTesting::CloseDevToolsWindow(window_
);
209 void CloseInspectedBrowser() {
210 chrome::CloseWindow(browser());
214 void InjectBeforeUnloadListener(content::WebContents
* web_contents
) {
215 ASSERT_TRUE(content::ExecuteScript(web_contents
->GetRenderViewHost(),
216 "window.addEventListener('beforeunload',"
217 "function(event) { event.returnValue = 'Foo'; });"));
220 void RunBeforeUnloadSanityTest(bool is_docked
,
221 base::Callback
<void(void)> close_method
,
222 bool wait_for_browser_close
= true) {
223 OpenDevToolsWindow(kDebuggerTestPage
, is_docked
);
224 scoped_refptr
<content::MessageLoopRunner
> runner
=
225 new content::MessageLoopRunner
;
226 DevToolsWindowTesting::Get(window_
)->
227 SetCloseCallback(runner
->QuitClosure());
228 InjectBeforeUnloadListener(main_web_contents());
230 DevToolsWindowBeforeUnloadObserver
before_unload_observer(window_
);
233 before_unload_observer
.Wait();
236 content::WindowedNotificationObserver
close_observer(
237 chrome::NOTIFICATION_BROWSER_CLOSED
,
238 content::Source
<Browser
>(browser()));
241 if (wait_for_browser_close
)
242 close_observer
.Wait();
247 DevToolsWindow
* OpenDevToolWindowOnWebContents(
248 content::WebContents
* contents
, bool is_docked
) {
249 DevToolsWindow
* window
=
250 DevToolsWindowTesting::OpenDevToolsWindowSync(contents
, is_docked
);
254 void OpenDevToolsPopupWindow(DevToolsWindow
* devtools_window
) {
255 content::WindowedNotificationObserver
observer(
256 content::NOTIFICATION_LOAD_STOP
,
257 content::NotificationService::AllSources());
258 ASSERT_TRUE(content::ExecuteScript(
259 DevToolsWindowTesting::Get(devtools_window
)->
260 main_web_contents()->GetRenderViewHost(),
261 "window.open(\"\", \"\", \"location=0\");"));
265 void CloseDevToolsPopupWindow(DevToolsWindow
* devtools_window
) {
266 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window
);
269 void AcceptModalDialog() {
270 NativeAppModalDialog
* native_dialog
= GetDialog();
271 native_dialog
->AcceptAppModalDialog();
274 void CancelModalDialog() {
275 NativeAppModalDialog
* native_dialog
= GetDialog();
276 native_dialog
->CancelAppModalDialog();
279 NativeAppModalDialog
* GetDialog() {
280 AppModalDialog
* dialog
= ui_test_utils::WaitForAppModalDialog();
281 EXPECT_TRUE(dialog
->IsJavaScriptModalDialog());
282 JavaScriptAppModalDialog
* js_dialog
=
283 static_cast<JavaScriptAppModalDialog
*>(dialog
);
284 NativeAppModalDialog
* native_dialog
= js_dialog
->native_dialog();
285 EXPECT_TRUE(native_dialog
);
286 return native_dialog
;
290 class DevToolsUnresponsiveBeforeUnloadTest
: public DevToolsBeforeUnloadTest
{
292 void SetUpCommandLine(base::CommandLine
* command_line
) override
{}
295 void TimeoutCallback(const std::string
& timeout_message
) {
296 ADD_FAILURE() << timeout_message
;
297 base::MessageLoop::current()->Quit();
300 // Base class for DevTools tests that test devtools functionality for
301 // extensions and content scripts.
302 class DevToolsExtensionTest
: public DevToolsSanityTest
,
303 public content::NotificationObserver
{
305 DevToolsExtensionTest() : DevToolsSanityTest() {
306 PathService::Get(chrome::DIR_TEST_DATA
, &test_extensions_dir_
);
307 test_extensions_dir_
= test_extensions_dir_
.AppendASCII("devtools");
308 test_extensions_dir_
= test_extensions_dir_
.AppendASCII("extensions");
312 // Load an extension from test\data\devtools\extensions\<extension_name>
313 void LoadExtension(const char* extension_name
) {
314 base::FilePath path
= test_extensions_dir_
.AppendASCII(extension_name
);
315 ASSERT_TRUE(LoadExtensionFromPath(path
)) << "Failed to load extension.";
319 bool LoadExtensionFromPath(const base::FilePath
& path
) {
320 ExtensionService
* service
= extensions::ExtensionSystem::Get(
321 browser()->profile())->extension_service();
322 extensions::ExtensionRegistry
* registry
=
323 extensions::ExtensionRegistry::Get(browser()->profile());
324 size_t num_before
= registry
->enabled_extensions().size();
326 content::NotificationRegistrar registrar
;
328 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
,
329 content::NotificationService::AllSources());
330 base::CancelableClosure
timeout(
331 base::Bind(&TimeoutCallback
, "Extension load timed out."));
332 base::MessageLoop::current()->PostDelayedTask(
333 FROM_HERE
, timeout
.callback(), TestTimeouts::action_timeout());
334 extensions::UnpackedInstaller::Create(service
)->Load(path
);
335 content::RunMessageLoop();
338 size_t num_after
= registry
->enabled_extensions().size();
339 if (num_after
!= (num_before
+ 1))
342 return WaitForExtensionViewsToLoad();
345 bool WaitForExtensionViewsToLoad() {
346 // Wait for all the extension render views that exist to finish loading.
347 // NOTE: This assumes that the extension views list is not changing while
348 // this method is running.
350 content::NotificationRegistrar registrar
;
352 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING
,
353 content::NotificationService::AllSources());
354 base::CancelableClosure
timeout(
355 base::Bind(&TimeoutCallback
, "Extension host load timed out."));
356 base::MessageLoop::current()->PostDelayedTask(
357 FROM_HERE
, timeout
.callback(), TestTimeouts::action_timeout());
359 extensions::ProcessManager
* manager
=
360 extensions::ProcessManager::Get(browser()->profile());
361 extensions::ProcessManager::ViewSet all_views
= manager
->GetAllViews();
362 for (extensions::ProcessManager::ViewSet::const_iterator iter
=
364 iter
!= all_views
.end();) {
365 if (!(*iter
)->IsLoading())
368 content::RunMessageLoop();
375 void Observe(int type
,
376 const content::NotificationSource
& source
,
377 const content::NotificationDetails
& details
) override
{
379 case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED
:
380 case extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_LOADING
:
381 base::MessageLoopForUI::current()->Quit();
389 base::FilePath test_extensions_dir_
;
392 class DevToolsExperimentalExtensionTest
: public DevToolsExtensionTest
{
394 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
395 command_line
->AppendSwitch(
396 extensions::switches::kEnableExperimentalExtensionApis
);
400 class WorkerDevToolsSanityTest
: public InProcessBrowserTest
{
402 WorkerDevToolsSanityTest() : window_(NULL
) {}
405 class WorkerData
: public base::RefCountedThreadSafe
<WorkerData
> {
407 WorkerData() : worker_process_id(0), worker_route_id(0) {}
408 int worker_process_id
;
412 friend class base::RefCountedThreadSafe
<WorkerData
>;
416 class WorkerCreationObserver
: public WorkerServiceObserver
{
418 explicit WorkerCreationObserver(const std::string
& path
,
419 WorkerData
* worker_data
)
420 : path_(path
), worker_data_(worker_data
) {}
423 ~WorkerCreationObserver() override
{}
425 void WorkerCreated(const GURL
& url
,
426 const base::string16
& name
,
428 int route_id
) override
{
429 if (url
.path().rfind(path_
) == std::string::npos
)
431 worker_data_
->worker_process_id
= process_id
;
432 worker_data_
->worker_route_id
= route_id
;
433 WorkerService::GetInstance()->RemoveObserver(this);
434 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
435 base::MessageLoop::QuitClosure());
439 scoped_refptr
<WorkerData
> worker_data_
;
442 class WorkerTerminationObserver
: public WorkerServiceObserver
{
444 explicit WorkerTerminationObserver(WorkerData
* worker_data
)
445 : worker_data_(worker_data
) {
449 ~WorkerTerminationObserver() override
{}
451 void WorkerDestroyed(int process_id
, int route_id
) override
{
452 ASSERT_EQ(worker_data_
->worker_process_id
, process_id
);
453 ASSERT_EQ(worker_data_
->worker_route_id
, route_id
);
454 WorkerService::GetInstance()->RemoveObserver(this);
455 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
456 base::MessageLoop::QuitClosure());
459 scoped_refptr
<WorkerData
> worker_data_
;
462 void RunTest(const char* test_name
,
463 const char* test_page
,
464 const char* worker_path
) {
465 ASSERT_TRUE(test_server()->Start());
466 GURL url
= test_server()->GetURL(test_page
);
467 ui_test_utils::NavigateToURL(browser(), url
);
469 scoped_refptr
<WorkerData
> worker_data
=
470 WaitForFirstSharedWorker(worker_path
);
471 OpenDevToolsWindowForSharedWorker(worker_data
.get());
472 RunTestFunction(window_
, test_name
);
473 CloseDevToolsWindow();
476 static void TerminateWorkerOnIOThread(scoped_refptr
<WorkerData
> worker_data
) {
477 if (!WorkerService::GetInstance()->TerminateWorker(
478 worker_data
->worker_process_id
, worker_data
->worker_route_id
))
479 FAIL() << "Failed to terminate worker.\n";
480 WorkerService::GetInstance()->AddObserver(
481 new WorkerTerminationObserver(worker_data
.get()));
484 static void TerminateWorker(scoped_refptr
<WorkerData
> worker_data
) {
485 BrowserThread::PostTask(
486 BrowserThread::IO
, FROM_HERE
,
487 base::Bind(&TerminateWorkerOnIOThread
, worker_data
));
488 content::RunMessageLoop();
491 static void WaitForFirstSharedWorkerOnIOThread(
492 const std::string
& path
,
493 scoped_refptr
<WorkerData
> worker_data
) {
494 std::vector
<WorkerService::WorkerInfo
> worker_info
=
495 WorkerService::GetInstance()->GetWorkers();
496 for (size_t i
= 0; i
< worker_info
.size(); i
++) {
497 if (worker_info
[i
].url
.path().rfind(path
) == std::string::npos
)
499 worker_data
->worker_process_id
= worker_info
[0].process_id
;
500 worker_data
->worker_route_id
= worker_info
[0].route_id
;
501 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
502 base::MessageLoop::QuitClosure());
506 WorkerService::GetInstance()->AddObserver(
507 new WorkerCreationObserver(path
, worker_data
.get()));
510 static scoped_refptr
<WorkerData
> WaitForFirstSharedWorker(const char* path
) {
511 scoped_refptr
<WorkerData
> worker_data(new WorkerData());
512 BrowserThread::PostTask(
515 base::Bind(&WaitForFirstSharedWorkerOnIOThread
, path
, worker_data
));
516 content::RunMessageLoop();
520 void OpenDevToolsWindowForSharedWorker(WorkerData
* worker_data
) {
521 Profile
* profile
= browser()->profile();
522 scoped_refptr
<DevToolsAgentHost
> agent_host(
523 DevToolsAgentHost::GetForWorker(
524 worker_data
->worker_process_id
,
525 worker_data
->worker_route_id
));
526 window_
= DevToolsWindowTesting::OpenDevToolsWindowForWorkerSync(
527 profile
, agent_host
.get());
530 void CloseDevToolsWindow() {
531 DevToolsWindowTesting::CloseDevToolsWindowSync(window_
);
534 DevToolsWindow
* window_
;
537 // Tests that BeforeUnload event gets called on docked devtools if
538 // we try to close them.
539 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
, TestDockedDevToolsClose
) {
540 RunBeforeUnloadSanityTest(true, base::Bind(
541 &DevToolsBeforeUnloadTest::CloseDevToolsWindowAsync
, this), false);
544 // Tests that BeforeUnload event gets called on docked devtools if
545 // we try to close the inspected page.
546 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
547 TestDockedDevToolsInspectedTabClose
) {
548 RunBeforeUnloadSanityTest(true, base::Bind(
549 &DevToolsBeforeUnloadTest::CloseInspectedTab
, this));
552 // Tests that BeforeUnload event gets called on docked devtools if
553 // we try to close the inspected browser.
554 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
555 TestDockedDevToolsInspectedBrowserClose
) {
556 RunBeforeUnloadSanityTest(true, base::Bind(
557 &DevToolsBeforeUnloadTest::CloseInspectedBrowser
, this));
560 // Tests that BeforeUnload event gets called on undocked devtools if
561 // we try to close them.
562 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
, TestUndockedDevToolsClose
) {
563 RunBeforeUnloadSanityTest(false, base::Bind(
564 &DevToolsBeforeUnloadTest::CloseDevToolsWindowAsync
, this), false);
567 // Tests that BeforeUnload event gets called on undocked devtools if
568 // we try to close the inspected page.
569 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
570 TestUndockedDevToolsInspectedTabClose
) {
571 RunBeforeUnloadSanityTest(false, base::Bind(
572 &DevToolsBeforeUnloadTest::CloseInspectedTab
, this));
575 // Tests that BeforeUnload event gets called on undocked devtools if
576 // we try to close the inspected browser.
577 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
578 TestUndockedDevToolsInspectedBrowserClose
) {
579 RunBeforeUnloadSanityTest(false, base::Bind(
580 &DevToolsBeforeUnloadTest::CloseInspectedBrowser
, this));
583 // Tests that BeforeUnload event gets called on undocked devtools if
584 // we try to exit application.
585 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
586 TestUndockedDevToolsApplicationClose
) {
587 RunBeforeUnloadSanityTest(false, base::Bind(
588 &chrome::CloseAllBrowsers
));
591 // Times out on Win and Linux
592 // @see http://crbug.com/410327
593 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
594 #define MAYBE_TestUndockedDevToolsUnresponsive DISABLED_TestUndockedDevToolsUnresponsive
596 #define MAYBE_TestUndockedDevToolsUnresponsive TestUndockedDevToolsUnresponsive
599 // Tests that inspected tab gets closed if devtools renderer
600 // becomes unresponsive during beforeunload event interception.
601 // @see http://crbug.com/322380
602 IN_PROC_BROWSER_TEST_F(DevToolsUnresponsiveBeforeUnloadTest
,
603 MAYBE_TestUndockedDevToolsUnresponsive
) {
604 ASSERT_TRUE(test_server()->Start());
605 LoadTestPage(kDebuggerTestPage
);
606 DevToolsWindow
* devtools_window
= OpenDevToolWindowOnWebContents(
607 GetInspectedTab(), false);
609 scoped_refptr
<content::MessageLoopRunner
> runner
=
610 new content::MessageLoopRunner
;
611 DevToolsWindowTesting::Get(devtools_window
)->SetCloseCallback(
612 runner
->QuitClosure());
614 ASSERT_TRUE(content::ExecuteScript(
615 DevToolsWindowTesting::Get(devtools_window
)->main_web_contents()->
617 "window.addEventListener('beforeunload',"
618 "function(event) { while (true); });"));
623 // Tests that closing worker inspector window does not cause browser crash
624 // @see http://crbug.com/323031
625 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
626 TestWorkerWindowClosing
) {
627 ASSERT_TRUE(test_server()->Start());
628 LoadTestPage(kDebuggerTestPage
);
629 DevToolsWindow
* devtools_window
= OpenDevToolWindowOnWebContents(
630 GetInspectedTab(), false);
632 OpenDevToolsPopupWindow(devtools_window
);
633 CloseDevToolsPopupWindow(devtools_window
);
636 // Tests that BeforeUnload event gets called on devtools that are opened
637 // on another devtools.
638 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest
,
639 TestDevToolsOnDevTools
) {
640 ASSERT_TRUE(test_server()->Start());
641 LoadTestPage(kDebuggerTestPage
);
643 std::vector
<DevToolsWindow
*> windows
;
644 std::vector
<content::WindowedNotificationObserver
*> close_observers
;
645 content::WebContents
* inspected_web_contents
= GetInspectedTab();
646 for (int i
= 0; i
< 3; ++i
) {
647 DevToolsWindow
* devtools_window
= OpenDevToolWindowOnWebContents(
648 inspected_web_contents
, i
== 0);
649 windows
.push_back(devtools_window
);
650 content::WindowedNotificationObserver
* close_observer
=
651 new content::WindowedNotificationObserver(
652 content::NOTIFICATION_WEB_CONTENTS_DESTROYED
,
653 content::Source
<content::WebContents
>(
654 DevToolsWindowTesting::Get(devtools_window
)->
655 main_web_contents()));
656 close_observers
.push_back(close_observer
);
657 inspected_web_contents
=
658 DevToolsWindowTesting::Get(devtools_window
)->main_web_contents();
661 InjectBeforeUnloadListener(
662 DevToolsWindowTesting::Get(windows
[0])->main_web_contents());
663 InjectBeforeUnloadListener(
664 DevToolsWindowTesting::Get(windows
[2])->main_web_contents());
665 // Try to close second devtools.
667 content::WindowedNotificationObserver
cancel_browser(
668 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
,
669 content::NotificationService::AllSources());
670 chrome::CloseWindow(DevToolsWindowTesting::Get(windows
[1])->browser());
672 cancel_browser
.Wait();
674 // Try to close browser window.
676 content::WindowedNotificationObserver
cancel_browser(
677 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED
,
678 content::NotificationService::AllSources());
679 chrome::CloseWindow(browser());
682 cancel_browser
.Wait();
684 // Try to exit application.
686 content::WindowedNotificationObserver
close_observer(
687 chrome::NOTIFICATION_BROWSER_CLOSED
,
688 content::Source
<Browser
>(browser()));
689 chrome::IncrementKeepAliveCount();
690 chrome::CloseAllBrowsers();
693 close_observer
.Wait();
695 for (size_t i
= 0; i
< close_observers
.size(); ++i
) {
696 close_observers
[i
]->Wait();
697 delete close_observers
[i
];
701 // Tests scripts panel showing.
702 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestShowScriptsTab
) {
703 RunTest("testShowScriptsTab", kDebuggerTestPage
);
706 // Tests that scripts tab is populated with inspected scripts even if it
707 // hadn't been shown by the moment inspected paged refreshed.
708 // @see http://crbug.com/26312
709 IN_PROC_BROWSER_TEST_F(
711 TestScriptsTabIsPopulatedOnInspectedPageRefresh
) {
712 RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh",
716 // Tests that chrome.devtools extension is correctly exposed.
717 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest
,
718 TestDevToolsExtensionAPI
) {
719 LoadExtension("devtools_extension");
720 RunTest("waitForTestResultsInConsole", std::string());
723 // Disabled on Windows due to flakiness. http://crbug.com/183649
725 #define MAYBE_TestDevToolsExtensionMessaging DISABLED_TestDevToolsExtensionMessaging
727 #define MAYBE_TestDevToolsExtensionMessaging TestDevToolsExtensionMessaging
730 // Tests that chrome.devtools extension can communicate with background page
731 // using extension messaging.
732 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest
,
733 MAYBE_TestDevToolsExtensionMessaging
) {
734 LoadExtension("devtools_messaging");
735 RunTest("waitForTestResultsInConsole", std::string());
738 // Tests that chrome.experimental.devtools extension is correctly exposed
739 // when the extension has experimental permission.
740 IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest
,
741 TestDevToolsExperimentalExtensionAPI
) {
742 LoadExtension("devtools_experimental");
743 RunTest("waitForTestResultsInConsole", std::string());
746 // Tests that a content script is in the scripts list.
747 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest
,
748 TestContentScriptIsPresent
) {
749 LoadExtension("simple_content_script");
750 RunTest("testContentScriptIsPresent", kPageWithContentScript
);
753 // Tests that scripts are not duplicated after Scripts Panel switch.
754 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
,
755 TestNoScriptDuplicatesOnPanelSwitch
) {
756 RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage
);
759 // Tests that debugger works correctly if pause event occurs when DevTools
760 // frontend is being loaded.
761 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
,
762 TestPauseWhenLoadingDevTools
) {
763 RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools
);
766 // Tests that pressing 'Pause' will pause script execution if the script
767 // is already running.
768 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
769 // Timing out on linux ARM bot: https://crbug/238453
770 #define MAYBE_TestPauseWhenScriptIsRunning DISABLED_TestPauseWhenScriptIsRunning
772 #define MAYBE_TestPauseWhenScriptIsRunning TestPauseWhenScriptIsRunning
774 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
,
775 MAYBE_TestPauseWhenScriptIsRunning
) {
776 RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning
);
779 // Tests network timing.
780 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkTiming
) {
781 RunTest("testNetworkTiming", kSlowTestPage
);
784 // Tests network size.
785 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkSize
) {
786 RunTest("testNetworkSize", kChunkedTestPage
);
789 // Tests raw headers text.
790 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkSyncSize
) {
791 RunTest("testNetworkSyncSize", kChunkedTestPage
);
794 // Tests raw headers text.
795 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestNetworkRawHeadersText
) {
796 RunTest("testNetworkRawHeadersText", kChunkedTestPage
);
799 // Tests that console messages are not duplicated on navigation back.
801 // Flaking on windows swarm try runs: crbug.com/409285.
802 #define MAYBE_TestConsoleOnNavigateBack DISABLED_TestConsoleOnNavigateBack
804 #define MAYBE_TestConsoleOnNavigateBack TestConsoleOnNavigateBack
806 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, MAYBE_TestConsoleOnNavigateBack
) {
807 RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage
);
810 // https://crbug.com/397889
811 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, DISABLED_TestDeviceEmulation
) {
812 RunTest("testDeviceMetricsOverrides", "about:blank");
816 // Tests that external navigation from inspector page is always handled by
817 // DevToolsWindow and results in inspected page navigation.
818 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestDevToolsExternalNavigation
) {
819 OpenDevToolsWindow(kDebuggerTestPage
, true);
820 GURL url
= test_server()->GetURL(kNavigateBackTestPage
);
821 ui_test_utils::UrlLoadObserver
observer(url
,
822 content::NotificationService::AllSources());
823 ASSERT_TRUE(content::ExecuteScript(
825 std::string("window.location = \"") + url
.spec() + "\""));
828 ASSERT_TRUE(main_web_contents()->GetURL().
829 SchemeIs(content::kChromeDevToolsScheme
));
830 ASSERT_EQ(url
, GetInspectedTab()->GetURL());
831 CloseDevToolsWindow();
834 // Tests that toolbox window is loaded when DevTools window is undocked.
835 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestToolboxLoadedUndocked
) {
836 OpenDevToolsWindow(kDebuggerTestPage
, false);
837 ASSERT_TRUE(toolbox_web_contents());
838 DevToolsWindow
* on_self
=
839 DevToolsWindowTesting::OpenDevToolsWindowSync(main_web_contents(), false);
840 ASSERT_FALSE(DevToolsWindowTesting::Get(on_self
)->toolbox_web_contents());
841 DevToolsWindowTesting::CloseDevToolsWindowSync(on_self
);
842 CloseDevToolsWindow();
845 // Tests that toolbox window is not loaded when DevTools window is docked.
846 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestToolboxNotLoadedDocked
) {
847 OpenDevToolsWindow(kDebuggerTestPage
, true);
848 ASSERT_FALSE(toolbox_web_contents());
849 DevToolsWindow
* on_self
=
850 DevToolsWindowTesting::OpenDevToolsWindowSync(main_web_contents(), false);
851 ASSERT_FALSE(DevToolsWindowTesting::Get(on_self
)->toolbox_web_contents());
852 DevToolsWindowTesting::CloseDevToolsWindowSync(on_self
);
853 CloseDevToolsWindow();
856 // Tests that inspector will reattach to inspected page when it is reloaded
857 // after a crash. See http://crbug.com/101952
858 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestReattachAfterCrash
) {
859 RunTest("testReattachAfterCrash", std::string());
862 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest
, TestPageWithNoJavaScript
) {
863 OpenDevToolsWindow("about:blank", false);
866 content::ExecuteScriptAndExtractString(
867 main_web_contents()->GetRenderViewHost(),
868 "window.domAutomationController.send("
869 " '' + (window.uiTests && (typeof uiTests.runTest)));",
871 ASSERT_EQ("function", result
) << "DevTools front-end is broken.";
872 CloseDevToolsWindow();
875 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest
, InspectSharedWorker
) {
876 #if defined(OS_WIN) && defined(USE_ASH)
877 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
878 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
879 switches::kAshBrowserTests
))
883 RunTest("testSharedWorker", kSharedWorkerTestPage
, kSharedWorkerTestWorker
);
886 // Disabled, crashes under Dr.Memory and ASan, http://crbug.com/432444.
887 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest
,
888 DISABLED_PauseInSharedWorkerInitialization
) {
889 ASSERT_TRUE(test_server()->Start());
890 GURL url
= test_server()->GetURL(kReloadSharedWorkerTestPage
);
891 ui_test_utils::NavigateToURL(browser(), url
);
893 scoped_refptr
<WorkerData
> worker_data
=
894 WaitForFirstSharedWorker(kReloadSharedWorkerTestWorker
);
895 OpenDevToolsWindowForSharedWorker(worker_data
.get());
897 // We should make sure that the worker inspector has loaded before
898 // terminating worker.
899 RunTestFunction(window_
, "testPauseInSharedWorkerInitialization1");
901 TerminateWorker(worker_data
);
903 // Reload page to restart the worker.
904 ui_test_utils::NavigateToURL(browser(), url
);
906 // Wait until worker script is paused on the debugger statement.
907 RunTestFunction(window_
, "testPauseInSharedWorkerInitialization2");
908 CloseDevToolsWindow();
911 class DevToolsAgentHostTest
: public InProcessBrowserTest
{};
913 // Tests DevToolsAgentHost retention by its target.
914 IN_PROC_BROWSER_TEST_F(DevToolsAgentHostTest
, TestAgentHostReleased
) {
915 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
916 WebContents
* web_contents
= browser()->tab_strip_model()->GetWebContentsAt(0);
917 DevToolsAgentHost
* agent_raw
=
918 DevToolsAgentHost::GetOrCreateFor(web_contents
).get();
919 const std::string agent_id
= agent_raw
->GetId();
920 ASSERT_EQ(agent_raw
, DevToolsAgentHost::GetForId(agent_id
).get())
921 << "DevToolsAgentHost cannot be found by id";
922 browser()->tab_strip_model()->
923 CloseWebContentsAt(0, TabStripModel::CLOSE_NONE
);
924 ASSERT_FALSE(DevToolsAgentHost::GetForId(agent_id
).get())
925 << "DevToolsAgentHost is not released when the tab is closed";
928 class RemoteDebuggingTest
: public ExtensionApiTest
{
929 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
930 ExtensionApiTest::SetUpCommandLine(command_line
);
931 command_line
->AppendSwitchASCII(switches::kRemoteDebuggingPort
, "9222");
933 // Override the extension root path.
934 PathService::Get(chrome::DIR_TEST_DATA
, &test_data_dir_
);
935 test_data_dir_
= test_data_dir_
.AppendASCII("devtools");
939 // Fails on CrOS. crbug.com/431399
940 #if defined(OS_CHROMEOS)
941 #define MAYBE_RemoteDebugger DISABLED_RemoteDebugger
943 #define MAYBE_RemoteDebugger RemoteDebugger
945 IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest
, MAYBE_RemoteDebugger
) {
946 #if defined(OS_WIN) && defined(USE_ASH)
947 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
948 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
949 switches::kAshBrowserTests
))
953 ASSERT_TRUE(RunExtensionTest("target_list")) << message_
;