Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / devtools / devtools_sanity_browsertest.cc
blobdb825a30462d8fdb30ba8a0e44790a3467c0c62a
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.
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/location.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/path_service.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/test/test_timeouts.h"
18 #include "base/thread_task_runner_handle.h"
19 #include "chrome/browser/chrome_notification_types.h"
20 #include "chrome/browser/devtools/device/tcp_device_provider.h"
21 #include "chrome/browser/devtools/devtools_window_testing.h"
22 #include "chrome/browser/extensions/extension_apitest.h"
23 #include "chrome/browser/extensions/extension_browsertest.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/unpacked_installer.h"
26 #include "chrome/browser/lifetime/application_lifetime.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/ui/browser.h"
29 #include "chrome/browser/ui/browser_commands.h"
30 #include "chrome/browser/ui/browser_iterator.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/common/chrome_paths.h"
33 #include "chrome/common/chrome_switches.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/common/url_constants.h"
36 #include "chrome/test/base/in_process_browser_test.h"
37 #include "chrome/test/base/test_switches.h"
38 #include "chrome/test/base/ui_test_utils.h"
39 #include "components/app_modal/javascript_app_modal_dialog.h"
40 #include "components/app_modal/native_app_modal_dialog.h"
41 #include "content/public/browser/child_process_data.h"
42 #include "content/public/browser/content_browser_client.h"
43 #include "content/public/browser/devtools_agent_host.h"
44 #include "content/public/browser/notification_registrar.h"
45 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/render_view_host.h"
47 #include "content/public/browser/web_contents.h"
48 #include "content/public/browser/worker_service.h"
49 #include "content/public/browser/worker_service_observer.h"
50 #include "content/public/common/content_switches.h"
51 #include "content/public/test/browser_test_utils.h"
52 #include "extensions/browser/extension_registry.h"
53 #include "extensions/browser/extension_system.h"
54 #include "extensions/browser/notification_types.h"
55 #include "extensions/common/switches.h"
56 #include "net/test/spawned_test_server/spawned_test_server.h"
57 #include "ui/compositor/compositor_switches.h"
58 #include "ui/gl/gl_switches.h"
60 using app_modal::AppModalDialog;
61 using app_modal::JavaScriptAppModalDialog;
62 using app_modal::NativeAppModalDialog;
63 using content::BrowserThread;
64 using content::DevToolsAgentHost;
65 using content::NavigationController;
66 using content::RenderViewHost;
67 using content::WebContents;
68 using content::WorkerService;
69 using content::WorkerServiceObserver;
71 namespace {
73 const char kDebuggerTestPage[] = "files/devtools/debugger_test_page.html";
74 const char kPauseWhenLoadingDevTools[] =
75 "files/devtools/pause_when_loading_devtools.html";
76 const char kPauseWhenScriptIsRunning[] =
77 "files/devtools/pause_when_script_is_running.html";
78 const char kPageWithContentScript[] =
79 "files/devtools/page_with_content_script.html";
80 const char kNavigateBackTestPage[] =
81 "files/devtools/navigate_back.html";
82 const char kChunkedTestPage[] = "chunked";
83 const char kSlowTestPage[] =
84 "chunked?waitBeforeHeaders=100&waitBetweenChunks=100&chunksNumber=2";
85 const char kSharedWorkerTestPage[] =
86 "files/workers/workers_ui_shared_worker.html";
87 const char kSharedWorkerTestWorker[] =
88 "files/workers/workers_ui_shared_worker.js";
89 const char kReloadSharedWorkerTestPage[] =
90 "files/workers/debug_shared_worker_initialization.html";
91 const char kReloadSharedWorkerTestWorker[] =
92 "files/workers/debug_shared_worker_initialization.js";
94 void RunTestFunction(DevToolsWindow* window, const char* test_name) {
95 std::string result;
97 RenderViewHost* rvh = DevToolsWindowTesting::Get(window)->
98 main_web_contents()->GetRenderViewHost();
99 // At first check that JavaScript part of the front-end is loaded by
100 // checking that global variable uiTests exists(it's created after all js
101 // files have been loaded) and has runTest method.
102 ASSERT_TRUE(
103 content::ExecuteScriptAndExtractString(
104 rvh,
105 "window.domAutomationController.send("
106 " '' + (window.uiTests && (typeof uiTests.runTest)));",
107 &result));
109 ASSERT_EQ("function", result) << "DevTools front-end is broken.";
110 ASSERT_TRUE(content::ExecuteScriptAndExtractString(
111 rvh,
112 base::StringPrintf("uiTests.runTest('%s')", test_name),
113 &result));
114 EXPECT_EQ("[OK]", result);
117 } // namespace
119 class DevToolsSanityTest : public InProcessBrowserTest {
120 public:
121 DevToolsSanityTest() : window_(NULL) {}
123 protected:
124 void RunTest(const std::string& test_name, const std::string& test_page) {
125 OpenDevToolsWindow(test_page, false);
126 RunTestFunction(window_, test_name.c_str());
127 CloseDevToolsWindow();
130 void LoadTestPage(const std::string& test_page) {
131 GURL url = test_server()->GetURL(test_page);
132 ui_test_utils::NavigateToURL(browser(), url);
135 void OpenDevToolsWindow(const std::string& test_page, bool is_docked) {
136 ASSERT_TRUE(test_server()->Start());
137 LoadTestPage(test_page);
139 window_ = DevToolsWindowTesting::OpenDevToolsWindowSync(GetInspectedTab(),
140 is_docked);
143 WebContents* GetInspectedTab() {
144 return browser()->tab_strip_model()->GetWebContentsAt(0);
147 void CloseDevToolsWindow() {
148 DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
151 WebContents* main_web_contents() {
152 return DevToolsWindowTesting::Get(window_)->main_web_contents();
155 WebContents* toolbox_web_contents() {
156 return DevToolsWindowTesting::Get(window_)->toolbox_web_contents();
159 DevToolsWindow* window_;
162 // Used to block until a dev tools window gets beforeunload event.
163 class DevToolsWindowBeforeUnloadObserver
164 : public content::WebContentsObserver {
165 public:
166 explicit DevToolsWindowBeforeUnloadObserver(DevToolsWindow*);
167 void Wait();
168 private:
169 // Invoked when the beforeunload handler fires.
170 void BeforeUnloadFired(const base::TimeTicks& proceed_time) override;
172 bool m_fired;
173 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
174 DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBeforeUnloadObserver);
177 DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver(
178 DevToolsWindow* devtools_window)
179 : WebContentsObserver(
180 DevToolsWindowTesting::Get(devtools_window)->main_web_contents()),
181 m_fired(false) {
184 void DevToolsWindowBeforeUnloadObserver::Wait() {
185 if (m_fired)
186 return;
187 message_loop_runner_ = new content::MessageLoopRunner;
188 message_loop_runner_->Run();
191 void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired(
192 const base::TimeTicks& proceed_time) {
193 m_fired = true;
194 if (message_loop_runner_.get())
195 message_loop_runner_->Quit();
198 class DevToolsBeforeUnloadTest: public DevToolsSanityTest {
199 public:
200 void SetUpCommandLine(base::CommandLine* command_line) override {
201 command_line->AppendSwitch(
202 switches::kDisableHangMonitor);
205 void CloseInspectedTab() {
206 browser()->tab_strip_model()->CloseWebContentsAt(0,
207 TabStripModel::CLOSE_NONE);
210 void CloseDevToolsWindowAsync() {
211 DevToolsWindowTesting::CloseDevToolsWindow(window_);
214 void CloseInspectedBrowser() {
215 chrome::CloseWindow(browser());
218 protected:
219 void InjectBeforeUnloadListener(content::WebContents* web_contents) {
220 ASSERT_TRUE(content::ExecuteScript(web_contents->GetRenderViewHost(),
221 "window.addEventListener('beforeunload',"
222 "function(event) { event.returnValue = 'Foo'; });"));
225 void RunBeforeUnloadSanityTest(bool is_docked,
226 base::Callback<void(void)> close_method,
227 bool wait_for_browser_close = true) {
228 OpenDevToolsWindow(kDebuggerTestPage, is_docked);
229 scoped_refptr<content::MessageLoopRunner> runner =
230 new content::MessageLoopRunner;
231 DevToolsWindowTesting::Get(window_)->
232 SetCloseCallback(runner->QuitClosure());
233 InjectBeforeUnloadListener(main_web_contents());
235 DevToolsWindowBeforeUnloadObserver before_unload_observer(window_);
236 close_method.Run();
237 CancelModalDialog();
238 before_unload_observer.Wait();
241 content::WindowedNotificationObserver close_observer(
242 chrome::NOTIFICATION_BROWSER_CLOSED,
243 content::Source<Browser>(browser()));
244 close_method.Run();
245 AcceptModalDialog();
246 if (wait_for_browser_close)
247 close_observer.Wait();
249 runner->Run();
252 DevToolsWindow* OpenDevToolWindowOnWebContents(
253 content::WebContents* contents, bool is_docked) {
254 DevToolsWindow* window =
255 DevToolsWindowTesting::OpenDevToolsWindowSync(contents, is_docked);
256 return window;
259 void OpenDevToolsPopupWindow(DevToolsWindow* devtools_window) {
260 content::WindowedNotificationObserver observer(
261 content::NOTIFICATION_LOAD_STOP,
262 content::NotificationService::AllSources());
263 ASSERT_TRUE(content::ExecuteScript(
264 DevToolsWindowTesting::Get(devtools_window)->
265 main_web_contents()->GetRenderViewHost(),
266 "window.open(\"\", \"\", \"location=0\");"));
267 observer.Wait();
270 void CloseDevToolsPopupWindow(DevToolsWindow* devtools_window) {
271 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window);
274 void AcceptModalDialog() {
275 NativeAppModalDialog* native_dialog = GetDialog();
276 native_dialog->AcceptAppModalDialog();
279 void CancelModalDialog() {
280 NativeAppModalDialog* native_dialog = GetDialog();
281 native_dialog->CancelAppModalDialog();
284 NativeAppModalDialog* GetDialog() {
285 AppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog();
286 EXPECT_TRUE(dialog->IsJavaScriptModalDialog());
287 JavaScriptAppModalDialog* js_dialog =
288 static_cast<JavaScriptAppModalDialog*>(dialog);
289 NativeAppModalDialog* native_dialog = js_dialog->native_dialog();
290 EXPECT_TRUE(native_dialog);
291 return native_dialog;
295 class DevToolsUnresponsiveBeforeUnloadTest: public DevToolsBeforeUnloadTest {
296 public:
297 void SetUpCommandLine(base::CommandLine* command_line) override {}
300 void TimeoutCallback(const std::string& timeout_message) {
301 ADD_FAILURE() << timeout_message;
302 base::MessageLoop::current()->Quit();
305 // Base class for DevTools tests that test devtools functionality for
306 // extensions and content scripts.
307 class DevToolsExtensionTest : public DevToolsSanityTest,
308 public content::NotificationObserver {
309 public:
310 DevToolsExtensionTest() : DevToolsSanityTest() {
311 PathService::Get(chrome::DIR_TEST_DATA, &test_extensions_dir_);
312 test_extensions_dir_ = test_extensions_dir_.AppendASCII("devtools");
313 test_extensions_dir_ = test_extensions_dir_.AppendASCII("extensions");
316 protected:
317 // Load an extension from test\data\devtools\extensions\<extension_name>
318 void LoadExtension(const char* extension_name) {
319 base::FilePath path = test_extensions_dir_.AppendASCII(extension_name);
320 ASSERT_TRUE(LoadExtensionFromPath(path)) << "Failed to load extension.";
323 private:
324 bool LoadExtensionFromPath(const base::FilePath& path) {
325 ExtensionService* service = extensions::ExtensionSystem::Get(
326 browser()->profile())->extension_service();
327 extensions::ExtensionRegistry* registry =
328 extensions::ExtensionRegistry::Get(browser()->profile());
329 size_t num_before = registry->enabled_extensions().size();
331 content::NotificationRegistrar registrar;
332 registrar.Add(this,
333 extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED,
334 content::NotificationService::AllSources());
335 base::CancelableClosure timeout(
336 base::Bind(&TimeoutCallback, "Extension load timed out."));
337 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
338 FROM_HERE, timeout.callback(), TestTimeouts::action_timeout());
339 extensions::UnpackedInstaller::Create(service)->Load(path);
340 content::RunMessageLoop();
341 timeout.Cancel();
343 size_t num_after = registry->enabled_extensions().size();
344 if (num_after != (num_before + 1))
345 return false;
347 return WaitForExtensionViewsToLoad();
350 bool WaitForExtensionViewsToLoad() {
351 // Wait for all the extension render views that exist to finish loading.
352 // NOTE: This assumes that the extension views list is not changing while
353 // this method is running.
355 content::NotificationRegistrar registrar;
356 registrar.Add(this,
357 extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD,
358 content::NotificationService::AllSources());
359 base::CancelableClosure timeout(
360 base::Bind(&TimeoutCallback, "Extension host load timed out."));
361 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
362 FROM_HERE, timeout.callback(), TestTimeouts::action_timeout());
364 extensions::ProcessManager* manager =
365 extensions::ProcessManager::Get(browser()->profile());
366 extensions::ProcessManager::FrameSet all_frames = manager->GetAllFrames();
367 for (extensions::ProcessManager::FrameSet::const_iterator iter =
368 all_frames.begin();
369 iter != all_frames.end();) {
370 if (!content::WebContents::FromRenderFrameHost(*iter)->IsLoading())
371 ++iter;
372 else
373 content::RunMessageLoop();
376 timeout.Cancel();
377 return true;
380 void Observe(int type,
381 const content::NotificationSource& source,
382 const content::NotificationDetails& details) override {
383 switch (type) {
384 case extensions::NOTIFICATION_EXTENSION_LOADED_DEPRECATED:
385 case extensions::NOTIFICATION_EXTENSION_HOST_DID_STOP_FIRST_LOAD:
386 base::MessageLoopForUI::current()->Quit();
387 break;
388 default:
389 NOTREACHED();
390 break;
394 base::FilePath test_extensions_dir_;
397 class DevToolsExperimentalExtensionTest : public DevToolsExtensionTest {
398 public:
399 void SetUpCommandLine(base::CommandLine* command_line) override {
400 command_line->AppendSwitch(
401 extensions::switches::kEnableExperimentalExtensionApis);
405 class WorkerDevToolsSanityTest : public InProcessBrowserTest {
406 public:
407 WorkerDevToolsSanityTest() : window_(NULL) {}
409 protected:
410 class WorkerData : public base::RefCountedThreadSafe<WorkerData> {
411 public:
412 WorkerData() : worker_process_id(0), worker_route_id(0) {}
413 int worker_process_id;
414 int worker_route_id;
416 private:
417 friend class base::RefCountedThreadSafe<WorkerData>;
418 ~WorkerData() {}
421 class WorkerCreationObserver : public WorkerServiceObserver {
422 public:
423 explicit WorkerCreationObserver(const std::string& path,
424 WorkerData* worker_data)
425 : path_(path), worker_data_(worker_data) {}
427 private:
428 ~WorkerCreationObserver() override {}
430 void WorkerCreated(const GURL& url,
431 const base::string16& name,
432 int process_id,
433 int route_id) override {
434 if (url.path().rfind(path_) == std::string::npos)
435 return;
436 worker_data_->worker_process_id = process_id;
437 worker_data_->worker_route_id = route_id;
438 WorkerService::GetInstance()->RemoveObserver(this);
439 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
440 base::MessageLoop::QuitClosure());
441 delete this;
443 std::string path_;
444 scoped_refptr<WorkerData> worker_data_;
447 class WorkerTerminationObserver : public WorkerServiceObserver {
448 public:
449 explicit WorkerTerminationObserver(WorkerData* worker_data)
450 : worker_data_(worker_data) {
453 private:
454 ~WorkerTerminationObserver() override {}
456 void WorkerDestroyed(int process_id, int route_id) override {
457 ASSERT_EQ(worker_data_->worker_process_id, process_id);
458 ASSERT_EQ(worker_data_->worker_route_id, route_id);
459 WorkerService::GetInstance()->RemoveObserver(this);
460 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
461 base::MessageLoop::QuitClosure());
462 delete this;
464 scoped_refptr<WorkerData> worker_data_;
467 void RunTest(const char* test_name,
468 const char* test_page,
469 const char* worker_path) {
470 ASSERT_TRUE(test_server()->Start());
471 GURL url = test_server()->GetURL(test_page);
472 ui_test_utils::NavigateToURL(browser(), url);
474 scoped_refptr<WorkerData> worker_data =
475 WaitForFirstSharedWorker(worker_path);
476 OpenDevToolsWindowForSharedWorker(worker_data.get());
477 RunTestFunction(window_, test_name);
478 CloseDevToolsWindow();
481 static void TerminateWorkerOnIOThread(scoped_refptr<WorkerData> worker_data) {
482 if (!WorkerService::GetInstance()->TerminateWorker(
483 worker_data->worker_process_id, worker_data->worker_route_id))
484 FAIL() << "Failed to terminate worker.\n";
485 WorkerService::GetInstance()->AddObserver(
486 new WorkerTerminationObserver(worker_data.get()));
489 static void TerminateWorker(scoped_refptr<WorkerData> worker_data) {
490 BrowserThread::PostTask(
491 BrowserThread::IO, FROM_HERE,
492 base::Bind(&TerminateWorkerOnIOThread, worker_data));
493 content::RunMessageLoop();
496 static void WaitForFirstSharedWorkerOnIOThread(
497 const std::string& path,
498 scoped_refptr<WorkerData> worker_data) {
499 std::vector<WorkerService::WorkerInfo> worker_info =
500 WorkerService::GetInstance()->GetWorkers();
501 for (size_t i = 0; i < worker_info.size(); i++) {
502 if (worker_info[i].url.path().rfind(path) == std::string::npos)
503 continue;
504 worker_data->worker_process_id = worker_info[0].process_id;
505 worker_data->worker_route_id = worker_info[0].route_id;
506 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
507 base::MessageLoop::QuitClosure());
508 return;
511 WorkerService::GetInstance()->AddObserver(
512 new WorkerCreationObserver(path, worker_data.get()));
515 static scoped_refptr<WorkerData> WaitForFirstSharedWorker(const char* path) {
516 scoped_refptr<WorkerData> worker_data(new WorkerData());
517 BrowserThread::PostTask(
518 BrowserThread::IO,
519 FROM_HERE,
520 base::Bind(&WaitForFirstSharedWorkerOnIOThread, path, worker_data));
521 content::RunMessageLoop();
522 return worker_data;
525 void OpenDevToolsWindowForSharedWorker(WorkerData* worker_data) {
526 Profile* profile = browser()->profile();
527 scoped_refptr<DevToolsAgentHost> agent_host(
528 DevToolsAgentHost::GetForWorker(
529 worker_data->worker_process_id,
530 worker_data->worker_route_id));
531 window_ = DevToolsWindowTesting::OpenDevToolsWindowForWorkerSync(
532 profile, agent_host.get());
535 void CloseDevToolsWindow() {
536 DevToolsWindowTesting::CloseDevToolsWindowSync(window_);
539 DevToolsWindow* window_;
542 // Tests that BeforeUnload event gets called on docked devtools if
543 // we try to close them.
544 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestDockedDevToolsClose) {
545 RunBeforeUnloadSanityTest(true, base::Bind(
546 &DevToolsBeforeUnloadTest::CloseDevToolsWindowAsync, this), false);
549 // Tests that BeforeUnload event gets called on docked devtools if
550 // we try to close the inspected page.
551 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
552 TestDockedDevToolsInspectedTabClose) {
553 RunBeforeUnloadSanityTest(true, base::Bind(
554 &DevToolsBeforeUnloadTest::CloseInspectedTab, this));
557 // Tests that BeforeUnload event gets called on docked devtools if
558 // we try to close the inspected browser.
559 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
560 TestDockedDevToolsInspectedBrowserClose) {
561 RunBeforeUnloadSanityTest(true, base::Bind(
562 &DevToolsBeforeUnloadTest::CloseInspectedBrowser, this));
565 // Tests that BeforeUnload event gets called on undocked devtools if
566 // we try to close them.
567 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestUndockedDevToolsClose) {
568 RunBeforeUnloadSanityTest(false, base::Bind(
569 &DevToolsBeforeUnloadTest::CloseDevToolsWindowAsync, this), false);
572 // Tests that BeforeUnload event gets called on undocked devtools if
573 // we try to close the inspected page.
574 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
575 TestUndockedDevToolsInspectedTabClose) {
576 RunBeforeUnloadSanityTest(false, base::Bind(
577 &DevToolsBeforeUnloadTest::CloseInspectedTab, this));
580 // Tests that BeforeUnload event gets called on undocked devtools if
581 // we try to close the inspected browser.
582 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
583 TestUndockedDevToolsInspectedBrowserClose) {
584 RunBeforeUnloadSanityTest(false, base::Bind(
585 &DevToolsBeforeUnloadTest::CloseInspectedBrowser, this));
588 // Tests that BeforeUnload event gets called on undocked devtools if
589 // we try to exit application.
590 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
591 TestUndockedDevToolsApplicationClose) {
592 RunBeforeUnloadSanityTest(false, base::Bind(
593 &chrome::CloseAllBrowsers));
596 // Times out on Win and Linux
597 // @see http://crbug.com/410327
598 #if defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS))
599 #define MAYBE_TestUndockedDevToolsUnresponsive DISABLED_TestUndockedDevToolsUnresponsive
600 #else
601 #define MAYBE_TestUndockedDevToolsUnresponsive TestUndockedDevToolsUnresponsive
602 #endif
604 // Tests that inspected tab gets closed if devtools renderer
605 // becomes unresponsive during beforeunload event interception.
606 // @see http://crbug.com/322380
607 IN_PROC_BROWSER_TEST_F(DevToolsUnresponsiveBeforeUnloadTest,
608 MAYBE_TestUndockedDevToolsUnresponsive) {
609 ASSERT_TRUE(test_server()->Start());
610 LoadTestPage(kDebuggerTestPage);
611 DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
612 GetInspectedTab(), false);
614 scoped_refptr<content::MessageLoopRunner> runner =
615 new content::MessageLoopRunner;
616 DevToolsWindowTesting::Get(devtools_window)->SetCloseCallback(
617 runner->QuitClosure());
619 ASSERT_TRUE(content::ExecuteScript(
620 DevToolsWindowTesting::Get(devtools_window)->main_web_contents()->
621 GetRenderViewHost(),
622 "window.addEventListener('beforeunload',"
623 "function(event) { while (true); });"));
624 CloseInspectedTab();
625 runner->Run();
628 // Tests that closing worker inspector window does not cause browser crash
629 // @see http://crbug.com/323031
630 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
631 TestWorkerWindowClosing) {
632 ASSERT_TRUE(test_server()->Start());
633 LoadTestPage(kDebuggerTestPage);
634 DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
635 GetInspectedTab(), false);
637 OpenDevToolsPopupWindow(devtools_window);
638 CloseDevToolsPopupWindow(devtools_window);
641 // Tests that BeforeUnload event gets called on devtools that are opened
642 // on another devtools.
643 // Disabled because of http://crbug.com/497857
644 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest,
645 DISABLED_TestDevToolsOnDevTools) {
646 ASSERT_TRUE(test_server()->Start());
647 LoadTestPage(kDebuggerTestPage);
649 std::vector<DevToolsWindow*> windows;
650 std::vector<content::WindowedNotificationObserver*> close_observers;
651 content::WebContents* inspected_web_contents = GetInspectedTab();
652 for (int i = 0; i < 3; ++i) {
653 DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents(
654 inspected_web_contents, i == 0);
655 windows.push_back(devtools_window);
656 content::WindowedNotificationObserver* close_observer =
657 new content::WindowedNotificationObserver(
658 content::NOTIFICATION_WEB_CONTENTS_DESTROYED,
659 content::Source<content::WebContents>(
660 DevToolsWindowTesting::Get(devtools_window)->
661 main_web_contents()));
662 close_observers.push_back(close_observer);
663 inspected_web_contents =
664 DevToolsWindowTesting::Get(devtools_window)->main_web_contents();
667 InjectBeforeUnloadListener(
668 DevToolsWindowTesting::Get(windows[0])->main_web_contents());
669 InjectBeforeUnloadListener(
670 DevToolsWindowTesting::Get(windows[2])->main_web_contents());
671 // Try to close second devtools.
673 content::WindowedNotificationObserver cancel_browser(
674 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
675 content::NotificationService::AllSources());
676 chrome::CloseWindow(DevToolsWindowTesting::Get(windows[1])->browser());
677 CancelModalDialog();
678 cancel_browser.Wait();
680 // Try to close browser window.
682 content::WindowedNotificationObserver cancel_browser(
683 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED,
684 content::NotificationService::AllSources());
685 chrome::CloseWindow(browser());
686 AcceptModalDialog();
687 CancelModalDialog();
688 cancel_browser.Wait();
690 // Try to exit application.
692 content::WindowedNotificationObserver close_observer(
693 chrome::NOTIFICATION_BROWSER_CLOSED,
694 content::Source<Browser>(browser()));
695 chrome::IncrementKeepAliveCount();
696 chrome::CloseAllBrowsers();
697 AcceptModalDialog();
698 AcceptModalDialog();
699 close_observer.Wait();
701 for (size_t i = 0; i < close_observers.size(); ++i) {
702 close_observers[i]->Wait();
703 delete close_observers[i];
707 // Tests scripts panel showing.
708 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestShowScriptsTab) {
709 RunTest("testShowScriptsTab", kDebuggerTestPage);
712 // Tests that scripts tab is populated with inspected scripts even if it
713 // hadn't been shown by the moment inspected paged refreshed.
714 // @see http://crbug.com/26312
715 IN_PROC_BROWSER_TEST_F(
716 DevToolsSanityTest,
717 TestScriptsTabIsPopulatedOnInspectedPageRefresh) {
718 RunTest("testScriptsTabIsPopulatedOnInspectedPageRefresh",
719 kDebuggerTestPage);
722 // Tests that chrome.devtools extension is correctly exposed.
723 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
724 TestDevToolsExtensionAPI) {
725 LoadExtension("devtools_extension");
726 RunTest("waitForTestResultsInConsole", std::string());
729 // Disabled on Windows due to flakiness. http://crbug.com/183649
730 #if defined(OS_WIN)
731 #define MAYBE_TestDevToolsExtensionMessaging DISABLED_TestDevToolsExtensionMessaging
732 #else
733 #define MAYBE_TestDevToolsExtensionMessaging TestDevToolsExtensionMessaging
734 #endif
736 // Tests that chrome.devtools extension can communicate with background page
737 // using extension messaging.
738 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
739 MAYBE_TestDevToolsExtensionMessaging) {
740 LoadExtension("devtools_messaging");
741 RunTest("waitForTestResultsInConsole", std::string());
744 // Tests that chrome.experimental.devtools extension is correctly exposed
745 // when the extension has experimental permission.
746 IN_PROC_BROWSER_TEST_F(DevToolsExperimentalExtensionTest,
747 TestDevToolsExperimentalExtensionAPI) {
748 LoadExtension("devtools_experimental");
749 RunTest("waitForTestResultsInConsole", std::string());
752 // Tests that a content script is in the scripts list.
753 IN_PROC_BROWSER_TEST_F(DevToolsExtensionTest,
754 TestContentScriptIsPresent) {
755 LoadExtension("simple_content_script");
756 RunTest("testContentScriptIsPresent", kPageWithContentScript);
759 // Tests that scripts are not duplicated after Scripts Panel switch.
760 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
761 TestNoScriptDuplicatesOnPanelSwitch) {
762 RunTest("testNoScriptDuplicatesOnPanelSwitch", kDebuggerTestPage);
765 // Tests that debugger works correctly if pause event occurs when DevTools
766 // frontend is being loaded.
767 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
768 TestPauseWhenLoadingDevTools) {
769 RunTest("testPauseWhenLoadingDevTools", kPauseWhenLoadingDevTools);
772 // Tests that pressing 'Pause' will pause script execution if the script
773 // is already running.
774 #if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(ARCH_CPU_ARM_FAMILY)
775 // Timing out on linux ARM bot: https://crbug/238453
776 #define MAYBE_TestPauseWhenScriptIsRunning DISABLED_TestPauseWhenScriptIsRunning
777 #else
778 #define MAYBE_TestPauseWhenScriptIsRunning TestPauseWhenScriptIsRunning
779 #endif
780 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest,
781 MAYBE_TestPauseWhenScriptIsRunning) {
782 RunTest("testPauseWhenScriptIsRunning", kPauseWhenScriptIsRunning);
785 // Tests network timing.
786 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkTiming) {
787 RunTest("testNetworkTiming", kSlowTestPage);
790 // Tests network size.
791 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSize) {
792 RunTest("testNetworkSize", kChunkedTestPage);
795 // Tests raw headers text.
796 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkSyncSize) {
797 RunTest("testNetworkSyncSize", kChunkedTestPage);
800 // Tests raw headers text.
801 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestNetworkRawHeadersText) {
802 RunTest("testNetworkRawHeadersText", kChunkedTestPage);
805 // Tests that console messages are not duplicated on navigation back.
806 #if defined(OS_WIN)
807 // Flaking on windows swarm try runs: crbug.com/409285.
808 #define MAYBE_TestConsoleOnNavigateBack DISABLED_TestConsoleOnNavigateBack
809 #else
810 #define MAYBE_TestConsoleOnNavigateBack TestConsoleOnNavigateBack
811 #endif
812 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, MAYBE_TestConsoleOnNavigateBack) {
813 RunTest("testConsoleOnNavigateBack", kNavigateBackTestPage);
816 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestDeviceEmulation) {
817 RunTest("testDeviceMetricsOverrides", "about:blank");
820 // Tests that settings are stored in profile correctly.
821 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestSettings) {
822 OpenDevToolsWindow("about:blank", true);
823 RunTestFunction(window_, "testSettings");
824 CloseDevToolsWindow();
827 // Tests that external navigation from inspector page is always handled by
828 // DevToolsWindow and results in inspected page navigation.
829 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestDevToolsExternalNavigation) {
830 OpenDevToolsWindow(kDebuggerTestPage, true);
831 GURL url = test_server()->GetURL(kNavigateBackTestPage);
832 ui_test_utils::UrlLoadObserver observer(url,
833 content::NotificationService::AllSources());
834 ASSERT_TRUE(content::ExecuteScript(
835 main_web_contents(),
836 std::string("window.location = \"") + url.spec() + "\""));
837 observer.Wait();
839 ASSERT_TRUE(main_web_contents()->GetURL().
840 SchemeIs(content::kChromeDevToolsScheme));
841 ASSERT_EQ(url, GetInspectedTab()->GetURL());
842 CloseDevToolsWindow();
845 // Tests that toolbox window is loaded when DevTools window is undocked.
846 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestToolboxLoadedUndocked) {
847 OpenDevToolsWindow(kDebuggerTestPage, false);
848 ASSERT_TRUE(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 toolbox window is not loaded when DevTools window is docked.
857 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestToolboxNotLoadedDocked) {
858 OpenDevToolsWindow(kDebuggerTestPage, true);
859 ASSERT_FALSE(toolbox_web_contents());
860 DevToolsWindow* on_self =
861 DevToolsWindowTesting::OpenDevToolsWindowSync(main_web_contents(), false);
862 ASSERT_FALSE(DevToolsWindowTesting::Get(on_self)->toolbox_web_contents());
863 DevToolsWindowTesting::CloseDevToolsWindowSync(on_self);
864 CloseDevToolsWindow();
867 // Tests that inspector will reattach to inspected page when it is reloaded
868 // after a crash. See http://crbug.com/101952
869 // Disabled. it doesn't check anything right now: http://crbug.com/461790
870 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DISABLED_TestReattachAfterCrash) {
871 RunTest("testReattachAfterCrash", std::string());
874 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, TestPageWithNoJavaScript) {
875 OpenDevToolsWindow("about:blank", false);
876 std::string result;
877 ASSERT_TRUE(
878 content::ExecuteScriptAndExtractString(
879 main_web_contents()->GetRenderViewHost(),
880 "window.domAutomationController.send("
881 " '' + (window.uiTests && (typeof uiTests.runTest)));",
882 &result));
883 ASSERT_EQ("function", result) << "DevTools front-end is broken.";
884 CloseDevToolsWindow();
887 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest, InspectSharedWorker) {
888 #if defined(OS_WIN) && defined(USE_ASH)
889 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
890 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
891 switches::kAshBrowserTests))
892 return;
893 #endif
895 RunTest("testSharedWorker", kSharedWorkerTestPage, kSharedWorkerTestWorker);
898 // Disabled, crashes under Dr.Memory and ASan, http://crbug.com/432444.
899 IN_PROC_BROWSER_TEST_F(WorkerDevToolsSanityTest,
900 DISABLED_PauseInSharedWorkerInitialization) {
901 ASSERT_TRUE(test_server()->Start());
902 GURL url = test_server()->GetURL(kReloadSharedWorkerTestPage);
903 ui_test_utils::NavigateToURL(browser(), url);
905 scoped_refptr<WorkerData> worker_data =
906 WaitForFirstSharedWorker(kReloadSharedWorkerTestWorker);
907 OpenDevToolsWindowForSharedWorker(worker_data.get());
909 // We should make sure that the worker inspector has loaded before
910 // terminating worker.
911 RunTestFunction(window_, "testPauseInSharedWorkerInitialization1");
913 TerminateWorker(worker_data);
915 // Reload page to restart the worker.
916 ui_test_utils::NavigateToURL(browser(), url);
918 // Wait until worker script is paused on the debugger statement.
919 RunTestFunction(window_, "testPauseInSharedWorkerInitialization2");
920 CloseDevToolsWindow();
923 class DevToolsAgentHostTest : public InProcessBrowserTest {};
925 // Tests DevToolsAgentHost retention by its target.
926 IN_PROC_BROWSER_TEST_F(DevToolsAgentHostTest, TestAgentHostReleased) {
927 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
928 WebContents* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
929 DevToolsAgentHost* agent_raw =
930 DevToolsAgentHost::GetOrCreateFor(web_contents).get();
931 const std::string agent_id = agent_raw->GetId();
932 ASSERT_EQ(agent_raw, DevToolsAgentHost::GetForId(agent_id).get())
933 << "DevToolsAgentHost cannot be found by id";
934 browser()->tab_strip_model()->
935 CloseWebContentsAt(0, TabStripModel::CLOSE_NONE);
936 ASSERT_FALSE(DevToolsAgentHost::GetForId(agent_id).get())
937 << "DevToolsAgentHost is not released when the tab is closed";
940 class RemoteDebuggingTest : public ExtensionApiTest {
941 void SetUpCommandLine(base::CommandLine* command_line) override {
942 ExtensionApiTest::SetUpCommandLine(command_line);
943 command_line->AppendSwitchASCII(switches::kRemoteDebuggingPort, "9222");
945 // Override the extension root path.
946 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir_);
947 test_data_dir_ = test_data_dir_.AppendASCII("devtools");
951 // Fails on CrOS. crbug.com/431399
952 #if defined(OS_CHROMEOS)
953 #define MAYBE_RemoteDebugger DISABLED_RemoteDebugger
954 #else
955 #define MAYBE_RemoteDebugger RemoteDebugger
956 #endif
957 IN_PROC_BROWSER_TEST_F(RemoteDebuggingTest, MAYBE_RemoteDebugger) {
958 #if defined(OS_WIN) && defined(USE_ASH)
959 // Disable this test in Metro+Ash for now (http://crbug.com/262796).
960 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
961 switches::kAshBrowserTests))
962 return;
963 #endif
965 ASSERT_TRUE(RunExtensionTest("target_list")) << message_;
968 using DevToolsPolicyTest = InProcessBrowserTest;
969 IN_PROC_BROWSER_TEST_F(DevToolsPolicyTest, PolicyTrue) {
970 browser()->profile()->GetPrefs()->SetBoolean(prefs::kDevToolsDisabled, true);
971 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
972 content::WebContents* web_contents =
973 browser()->tab_strip_model()->GetWebContentsAt(0);
974 scoped_refptr<content::DevToolsAgentHost> agent(
975 content::DevToolsAgentHost::GetOrCreateFor(web_contents));
976 DevToolsWindow::OpenDevToolsWindow(web_contents);
977 DevToolsWindow* window = DevToolsWindow::FindDevToolsWindow(agent.get());
978 ASSERT_FALSE(window);
981 class DevToolsPixelOutputTests : public DevToolsSanityTest {
982 public:
983 void SetUpCommandLine(base::CommandLine* command_line) override {
984 command_line->AppendSwitch(switches::kEnablePixelOutputInTests);
985 command_line->AppendSwitch(switches::kUseGpuInTests);
989 // This test enables switches::kUseGpuInTests which causes false positives
990 // with MemorySanitizer.
991 #if defined(MEMORY_SANITIZER) || \
992 (defined(OS_CHROMEOS) && defined(OFFICIAL_BUILD))
993 #define MAYBE_TestScreenshotRecording DISABLED_TestScreenshotRecording
994 #else
995 #define MAYBE_TestScreenshotRecording TestScreenshotRecording
996 #endif
997 // Tests raw headers text.
998 IN_PROC_BROWSER_TEST_F(DevToolsPixelOutputTests,
999 MAYBE_TestScreenshotRecording) {
1000 RunTest("testScreenshotRecording", std::string());