Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/cancelable_callback.h" | 6 #include "base/cancelable_callback.h" |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/compiler_specific.h" | 8 #include "base/compiler_specific.h" |
| 9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| 11 #include "base/prefs/pref_service.h" | 11 #include "base/prefs/pref_service.h" |
| 12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/test/test_timeouts.h" | 14 #include "base/test/test_timeouts.h" |
| 15 #include "chrome/browser/chrome_notification_types.h" | 15 #include "chrome/browser/chrome_notification_types.h" |
| 16 #include "chrome/browser/devtools/browser_list_tabcontents_provider.h" | 16 #include "chrome/browser/devtools/browser_list_tabcontents_provider.h" |
| 17 #include "chrome/browser/devtools/devtools_window.h" | 17 #include "chrome/browser/devtools/devtools_window.h" |
| 18 #include "chrome/browser/extensions/extension_apitest.h" | 18 #include "chrome/browser/extensions/extension_apitest.h" |
| 19 #include "chrome/browser/extensions/extension_browsertest.h" | 19 #include "chrome/browser/extensions/extension_browsertest.h" |
| 20 #include "chrome/browser/extensions/extension_service.h" | 20 #include "chrome/browser/extensions/extension_service.h" |
| 21 #include "chrome/browser/extensions/extension_system.h" | 21 #include "chrome/browser/extensions/extension_system.h" |
| 22 #include "chrome/browser/extensions/unpacked_installer.h" | 22 #include "chrome/browser/extensions/unpacked_installer.h" |
| 23 #include "chrome/browser/lifetime/application_lifetime.h" | |
| 23 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
| 25 #include "chrome/browser/ui/app_modal_dialogs/javascript_app_modal_dialog.h" | |
| 26 #include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h" | |
| 24 #include "chrome/browser/ui/browser.h" | 27 #include "chrome/browser/ui/browser.h" |
| 25 #include "chrome/browser/ui/browser_commands.h" | 28 #include "chrome/browser/ui/browser_commands.h" |
| 26 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 29 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 27 #include "chrome/common/chrome_paths.h" | 30 #include "chrome/common/chrome_paths.h" |
| 28 #include "chrome/common/chrome_switches.h" | 31 #include "chrome/common/chrome_switches.h" |
| 29 #include "chrome/common/pref_names.h" | 32 #include "chrome/common/pref_names.h" |
| 30 #include "chrome/common/url_constants.h" | 33 #include "chrome/common/url_constants.h" |
| 31 #include "chrome/test/base/in_process_browser_test.h" | 34 #include "chrome/test/base/in_process_browser_test.h" |
| 32 #include "chrome/test/base/test_switches.h" | 35 #include "chrome/test/base/test_switches.h" |
| 33 #include "chrome/test/base/ui_test_utils.h" | 36 #include "chrome/test/base/ui_test_utils.h" |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 151 } | 154 } |
| 152 | 155 |
| 153 DevToolsWindow* window_; | 156 DevToolsWindow* window_; |
| 154 RenderViewHost* inspected_rvh_; | 157 RenderViewHost* inspected_rvh_; |
| 155 }; | 158 }; |
| 156 | 159 |
| 157 // Used to block until a dev tools window gets beforeunload event. | 160 // Used to block until a dev tools window gets beforeunload event. |
| 158 class DevToolsWindowBeforeUnloadObserver | 161 class DevToolsWindowBeforeUnloadObserver |
| 159 : public content::WebContentsObserver { | 162 : public content::WebContentsObserver { |
| 160 public: | 163 public: |
| 161 explicit DevToolsWindowBeforeUnloadObserver( | 164 explicit DevToolsWindowBeforeUnloadObserver(DevToolsWindow*); |
| 162 content::WebContents* web_contents); | 165 void Wait(); |
| 163 bool Fired(); | |
| 164 private: | 166 private: |
| 165 // Invoked when the beforeunload handler fires. | 167 // Invoked when the beforeunload handler fires. |
| 166 virtual void BeforeUnloadFired(const base::TimeTicks& proceed_time) OVERRIDE; | 168 virtual void BeforeUnloadFired(const base::TimeTicks& proceed_time) OVERRIDE; |
| 167 | 169 |
| 168 bool m_fired; | 170 bool m_fired; |
| 169 | 171 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| 170 DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBeforeUnloadObserver); | 172 DISALLOW_COPY_AND_ASSIGN(DevToolsWindowBeforeUnloadObserver); |
| 171 }; | 173 }; |
| 172 | 174 |
| 173 DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver( | 175 DevToolsWindowBeforeUnloadObserver::DevToolsWindowBeforeUnloadObserver( |
| 174 content::WebContents* web_contents) | 176 DevToolsWindow* devtools_window) |
| 175 : WebContentsObserver(web_contents), | 177 : WebContentsObserver(devtools_window->web_contents()), |
| 176 m_fired(false) { | 178 m_fired(false) { |
| 177 } | 179 } |
| 178 | 180 |
| 179 bool DevToolsWindowBeforeUnloadObserver::Fired() { | 181 void DevToolsWindowBeforeUnloadObserver::Wait() { |
| 180 return m_fired; | 182 if (m_fired) |
| 183 return; | |
| 184 message_loop_runner_ = new content::MessageLoopRunner; | |
| 185 message_loop_runner_->Run(); | |
| 181 } | 186 } |
| 182 | 187 |
| 183 void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired( | 188 void DevToolsWindowBeforeUnloadObserver::BeforeUnloadFired( |
| 184 const base::TimeTicks& proceed_time) { | 189 const base::TimeTicks& proceed_time) { |
| 185 m_fired = true; | 190 m_fired = true; |
| 191 if (message_loop_runner_.get()) | |
| 192 message_loop_runner_->Quit(); | |
| 186 } | 193 } |
| 187 | 194 |
| 195 class DevToolsBeforeUnloadTest: public DevToolsSanityTest { | |
| 196 public: | |
| 197 void CloseInspectedTab() { | |
| 198 browser()->tab_strip_model()->CloseWebContentsAt(0, | |
| 199 TabStripModel::CLOSE_NONE); | |
| 200 } | |
| 201 | |
| 202 void CloseDockedDevTools() { | |
| 203 DevToolsWindow::ToggleDevToolsWindow(inspected_rvh_, false, | |
| 204 DevToolsToggleAction::Toggle()); | |
| 205 } | |
| 206 | |
| 207 void CloseUndockedDevTools() { | |
| 208 chrome::CloseWindow(window_->browser()); | |
| 209 } | |
| 210 | |
| 211 void CloseInspectedBrowser() { | |
| 212 chrome::CloseWindow(browser()); | |
| 213 } | |
| 214 protected: | |
| 215 void InjectBeforeUnloadListener(content::WebContents* web_contents) { | |
| 216 ASSERT_TRUE(content::ExecuteScript(web_contents->GetRenderViewHost(), | |
| 217 "window.addEventListener('beforeunload'," | |
| 218 "function(event) { event.returnValue = 'Foo'; });")); | |
| 219 } | |
| 220 | |
| 221 void RunBeforeUnloadSanityTest(DevToolsDockSide dock_side, | |
| 222 base::Callback<void(void)> close_method, | |
| 223 bool wait_for_browser_close = true) { | |
| 224 OpenDevToolsWindow(kDebuggerTestPage); | |
| 225 window_->SetDockSideForTest(dock_side); | |
| 226 content::WindowedNotificationObserver devtools_close_observer( | |
| 227 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
| 228 content::Source<content::WebContents>(window_->web_contents())); | |
| 229 InjectBeforeUnloadListener(window_->web_contents()); | |
| 230 { | |
| 231 DevToolsWindowBeforeUnloadObserver before_unload_observer(window_); | |
| 232 close_method.Run(); | |
| 233 CancelModalDialog(); | |
| 234 before_unload_observer.Wait(); | |
| 235 } | |
| 236 { | |
| 237 content::WindowedNotificationObserver close_observer( | |
| 238 chrome::NOTIFICATION_BROWSER_CLOSED, | |
| 239 content::Source<Browser>(browser())); | |
| 240 close_method.Run(); | |
| 241 AcceptModalDialog(); | |
| 242 if (wait_for_browser_close) | |
| 243 close_observer.Wait(); | |
| 244 } | |
| 245 devtools_close_observer.Wait(); | |
| 246 } | |
| 247 | |
| 248 DevToolsWindow* OpenDevToolWindowOnWebContents( | |
| 249 content::WebContents* contents) { | |
| 250 content::WindowedNotificationObserver observer( | |
| 251 content::NOTIFICATION_LOAD_STOP, | |
| 252 content::NotificationService::AllSources()); | |
| 253 DevToolsWindow* window = DevToolsWindow::OpenDevToolsWindow( | |
| 254 contents->GetRenderViewHost()); | |
| 255 observer.Wait(); | |
| 256 return window; | |
| 257 } | |
| 258 | |
| 259 void AcceptModalDialog() { | |
| 260 NativeAppModalDialog* native_dialog = GetDialog(); | |
| 261 native_dialog->AcceptAppModalDialog(); | |
| 262 } | |
| 263 | |
| 264 void CancelModalDialog() { | |
| 265 NativeAppModalDialog* native_dialog = GetDialog(); | |
| 266 native_dialog->CancelAppModalDialog(); | |
| 267 } | |
| 268 | |
| 269 NativeAppModalDialog* GetDialog() { | |
| 270 AppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog(); | |
| 271 EXPECT_TRUE(dialog->IsJavaScriptModalDialog()); | |
| 272 JavaScriptAppModalDialog* js_dialog = | |
| 273 static_cast<JavaScriptAppModalDialog*>(dialog); | |
| 274 NativeAppModalDialog* native_dialog = js_dialog->native_dialog(); | |
| 275 EXPECT_TRUE(native_dialog); | |
| 276 return native_dialog; | |
| 277 } | |
| 278 }; | |
| 279 | |
| 188 void TimeoutCallback(const std::string& timeout_message) { | 280 void TimeoutCallback(const std::string& timeout_message) { |
| 189 FAIL() << timeout_message; | 281 FAIL() << timeout_message; |
| 190 base::MessageLoop::current()->Quit(); | 282 base::MessageLoop::current()->Quit(); |
| 191 } | 283 } |
| 192 | 284 |
| 193 // Base class for DevTools tests that test devtools functionality for | 285 // Base class for DevTools tests that test devtools functionality for |
| 194 // extensions and content scripts. | 286 // extensions and content scripts. |
| 195 class DevToolsExtensionTest : public DevToolsSanityTest, | 287 class DevToolsExtensionTest : public DevToolsSanityTest, |
| 196 public content::NotificationObserver { | 288 public content::NotificationObserver { |
| 197 public: | 289 public: |
| (...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 426 content::WindowedNotificationObserver close_observer( | 518 content::WindowedNotificationObserver close_observer( |
| 427 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | 519 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 428 content::Source<content::WebContents>(window_->web_contents())); | 520 content::Source<content::WebContents>(window_->web_contents())); |
| 429 browser->tab_strip_model()->CloseAllTabs(); | 521 browser->tab_strip_model()->CloseAllTabs(); |
| 430 close_observer.Wait(); | 522 close_observer.Wait(); |
| 431 } | 523 } |
| 432 | 524 |
| 433 DevToolsWindow* window_; | 525 DevToolsWindow* window_; |
| 434 }; | 526 }; |
| 435 | 527 |
| 436 // Test beforeunload event delivery. | 528 // Tests that BeforeUnload event gets called on docked DevTools if |
| 437 // Crashes on Win only. http://crbug.com/313658 | 529 // we try to close them. |
| 438 #if defined(OS_WIN) | 530 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestDockedDevToolsClose) { |
| 439 #define MAYBE_TestBeforeUnloadEvents DISABLED_TestBeforeUnloadEvents | 531 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_BOTTOM, base::Bind( |
| 440 #else | 532 &DevToolsBeforeUnloadTest::CloseDockedDevTools, this), false); |
| 441 #define MAYBE_TestBeforeUnloadEvents TestBeforeUnloadEvents | 533 } |
| 442 #endif | 534 |
| 443 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, MAYBE_TestBeforeUnloadEvents) { | 535 // Tests that BeforeUnload event gets called on docked DevTools if |
| 444 OpenDevToolsWindow(kDebuggerTestPage); | 536 // we try to close inspected page. |
|
jeremy
2013/11/10 12:50:30
nit: "the inspected page", and the same fix on oth
lushnikov
2013/11/11 15:22:54
Done.
| |
| 445 scoped_ptr<DevToolsWindowBeforeUnloadObserver> contents_observer; | 537 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, |
| 446 contents_observer.reset( | 538 TestDockedDevToolsInspectedTabClose) { |
| 447 new DevToolsWindowBeforeUnloadObserver(window_->web_contents())); | 539 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_BOTTOM, base::Bind( |
| 448 ToggleDevToolsWindow(); | 540 &DevToolsBeforeUnloadTest::CloseInspectedTab, this)); |
| 449 ASSERT_TRUE(contents_observer->Fired()); | 541 } |
| 542 | |
| 543 // Tests that BeforeUnload event gets called on docked DevTools if | |
| 544 // we try to close inspected browser. | |
| 545 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, | |
| 546 TestDockedDevToolsInspectedBrowserClose) { | |
| 547 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_BOTTOM, base::Bind( | |
| 548 &DevToolsBeforeUnloadTest::CloseInspectedBrowser, this)); | |
| 549 } | |
| 550 | |
| 551 // Tests that BeforeUnload event gets called on undocked DevTools if | |
| 552 // we try to close them. | |
| 553 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestUndockedDevToolsClose) { | |
| 554 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_UNDOCKED, base::Bind( | |
| 555 &DevToolsBeforeUnloadTest::CloseUndockedDevTools, this), false); | |
| 556 } | |
| 557 | |
| 558 // Tests that BeforeUnload event gets called on undocked DevTools if | |
| 559 // we try to close inspected page. | |
| 560 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, | |
| 561 TestUndockedDevToolsInspectedTabClose) { | |
| 562 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_UNDOCKED, base::Bind( | |
| 563 &DevToolsBeforeUnloadTest::CloseInspectedTab, this)); | |
| 564 } | |
| 565 | |
| 566 // Tests that BeforeUnload event gets called on undocked DevTools if | |
| 567 // we try to close inspected browser. | |
| 568 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, | |
| 569 TestUndockedDevToolsInspectedBrowserClose) { | |
| 570 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_UNDOCKED, base::Bind( | |
| 571 &DevToolsBeforeUnloadTest::CloseInspectedBrowser, this)); | |
| 572 } | |
| 573 | |
| 574 // Tests that BeforeUnload event gets called on undocked DevTools if | |
| 575 // we try to exit application. | |
| 576 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, | |
| 577 TestUndockedDevToolsApplicationClose) { | |
| 578 RunBeforeUnloadSanityTest(DEVTOOLS_DOCK_SIDE_UNDOCKED, base::Bind( | |
| 579 &chrome::CloseAllBrowsers)); | |
| 580 } | |
| 581 | |
| 582 // Tests that BeforeUnload event gets called on DevTools that are opened | |
| 583 // on another DevTools. | |
| 584 IN_PROC_BROWSER_TEST_F(DevToolsBeforeUnloadTest, TestDevToolsOnDevTools) { | |
| 585 ASSERT_TRUE(test_server()->Start()); | |
| 586 GURL url = test_server()->GetURL(kDebuggerTestPage); | |
| 587 ui_test_utils::NavigateToURL(browser(), url); | |
| 588 | |
| 589 std::vector<DevToolsWindow*> windows; | |
| 590 std::vector<content::WindowedNotificationObserver*> close_observers; | |
| 591 content::WebContents* inspected_web_contents = GetInspectedTab(); | |
| 592 for (int i = 0; i < 3; ++i) { | |
| 593 DevToolsWindow* devtools_window = OpenDevToolWindowOnWebContents( | |
| 594 inspected_web_contents); | |
| 595 windows.push_back(devtools_window); | |
| 596 content::WindowedNotificationObserver* close_observer = | |
| 597 new content::WindowedNotificationObserver( | |
| 598 content::NOTIFICATION_WEB_CONTENTS_DESTROYED, | |
| 599 content::Source<content::WebContents>( | |
| 600 devtools_window->web_contents())); | |
| 601 close_observers.push_back(close_observer); | |
| 602 inspected_web_contents = devtools_window->web_contents(); | |
| 603 } | |
| 604 | |
| 605 InjectBeforeUnloadListener(windows[0]->web_contents()); | |
| 606 InjectBeforeUnloadListener(windows[2]->web_contents()); | |
| 607 // Try to close second DevTools. | |
| 608 { | |
| 609 content::WindowedNotificationObserver cancel_browser( | |
| 610 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, | |
| 611 content::NotificationService::AllSources()); | |
| 612 chrome::CloseWindow(windows[1]->browser()); | |
| 613 CancelModalDialog(); | |
| 614 cancel_browser.Wait(); | |
| 615 } | |
| 616 // Try to close browser window. | |
| 617 { | |
| 618 content::WindowedNotificationObserver cancel_browser( | |
| 619 chrome::NOTIFICATION_BROWSER_CLOSE_CANCELLED, | |
| 620 content::NotificationService::AllSources()); | |
| 621 chrome::CloseWindow(browser()); | |
| 622 AcceptModalDialog(); | |
| 623 CancelModalDialog(); | |
| 624 cancel_browser.Wait(); | |
| 625 } | |
| 626 // Try to exit application. | |
| 627 { | |
| 628 content::WindowedNotificationObserver close_observer( | |
| 629 chrome::NOTIFICATION_BROWSER_CLOSED, | |
| 630 content::Source<Browser>(browser())); | |
| 631 chrome::CloseAllBrowsers(); | |
| 632 AcceptModalDialog(); | |
| 633 AcceptModalDialog(); | |
| 634 close_observer.Wait(); | |
| 635 } | |
| 636 for (size_t i = 0; i < close_observers.size(); ++i) { | |
| 637 close_observers[i]->Wait(); | |
| 638 delete close_observers[i]; | |
| 639 } | |
| 450 } | 640 } |
| 451 | 641 |
| 452 // Tests scripts panel showing. | 642 // Tests scripts panel showing. |
| 453 // TODO(pfeldman): figure out flake. | 643 // TODO(pfeldman): figure out flake. |
| 454 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DISABLED_TestShowScriptsTab) { | 644 IN_PROC_BROWSER_TEST_F(DevToolsSanityTest, DISABLED_TestShowScriptsTab) { |
| 455 RunTest("testShowScriptsTab", kDebuggerTestPage); | 645 RunTest("testShowScriptsTab", kDebuggerTestPage); |
| 456 } | 646 } |
| 457 | 647 |
| 458 // Tests that scripts tab is populated with inspected scripts even if it | 648 // Tests that scripts tab is populated with inspected scripts even if it |
| 459 // hadn't been shown by the moment inspected paged refreshed. | 649 // hadn't been shown by the moment inspected paged refreshed. |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 #if defined(OS_WIN) && defined(USE_ASH) | 889 #if defined(OS_WIN) && defined(USE_ASH) |
| 700 // Disable this test in Metro+Ash for now (http://crbug.com/262796). | 890 // Disable this test in Metro+Ash for now (http://crbug.com/262796). |
| 701 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) | 891 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kAshBrowserTests)) |
| 702 return; | 892 return; |
| 703 #endif | 893 #endif |
| 704 | 894 |
| 705 ASSERT_TRUE(RunExtensionTest("target_list")) << message_; | 895 ASSERT_TRUE(RunExtensionTest("target_list")) << message_; |
| 706 } | 896 } |
| 707 | 897 |
| 708 } // namespace | 898 } // namespace |
| OLD | NEW |