1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/memory/ref_counted.h" 6 #include "base/stringprintf.h" 7 #include "chrome/browser/debugger/devtools_client_host.h" 8 #include "chrome/browser/debugger/devtools_manager.h" 9 #include "chrome/browser/extensions/extension_devtools_browsertest.h" 10 #include "chrome/browser/extensions/extension_error_reporter.h" 11 #include "chrome/browser/extensions/extension_host.h" 12 #include "chrome/browser/extensions/extension_process_manager.h" 13 #include "chrome/browser/extensions/extension_service.h" 14 #include "chrome/browser/extensions/extension_tabs_module.h" 15 #include "chrome/browser/profiles/profile.h" 16 #include "chrome/browser/tabs/tab_strip_model.h" 17 #include "chrome/browser/ui/browser_list.h" 18 #include "chrome/common/chrome_paths.h" 19 #include "chrome/common/devtools_messages.h" 20 #include "chrome/common/url_constants.h" 21 #include "chrome/test/ui_test_utils.h" 22 #include "content/browser/renderer_host/render_view_host.h" 23 #include "content/browser/site_instance.h" 24 #include "content/browser/tab_contents/tab_contents.h" 25 #include "net/base/net_util.h" 26 27 // Looks for an ExtensionHost whose URL has the given path component (including 28 // leading slash). Also verifies that the expected number of hosts are loaded. 29 static ExtensionHost* FindHostWithPath(ExtensionProcessManager* manager, 30 const std::string& path, 31 int expected_hosts) { 32 ExtensionHost* host = NULL; 33 int num_hosts = 0; 34 for (ExtensionProcessManager::const_iterator iter = manager->begin(); 35 iter != manager->end(); ++iter) { 36 if ((*iter)->GetURL().path() == path) { 37 EXPECT_FALSE(host); 38 host = *iter; 39 } 40 num_hosts++; 41 } 42 EXPECT_EQ(expected_hosts, num_hosts); 43 EXPECT_TRUE(host); 44 return host; 45 } 46 47 // Tests for the experimental timeline extensions API. 48 // TODO(johnnyg): crbug.com/52544 Test was broken by webkit r65510. 49 IN_PROC_BROWSER_TEST_F(ExtensionDevToolsBrowserTest, FLAKY_TimelineApi) { 50 ASSERT_TRUE(LoadExtension( 51 test_data_dir_.AppendASCII("devtools").AppendASCII("timeline_api"))); 52 53 // Get the ExtensionHost that is hosting our background page. 54 ExtensionProcessManager* manager = 55 browser()->profile()->GetExtensionProcessManager(); 56 ExtensionHost* host = FindHostWithPath(manager, "/background.html", 1); 57 58 // Grab a handle to the DevToolsManager so we can forward messages to it. 59 DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); 60 61 // Grab the tab_id of whatever tab happens to be first. 62 TabContents* tab_contents = browser()->GetTabContentsAt(0); 63 ASSERT_TRUE(tab_contents); 64 int tab_id = ExtensionTabUtil::GetTabId(tab_contents); 65 66 // Test setup. 67 bool result = false; 68 std::wstring register_listeners_js = base::StringPrintf( 69 L"setListenersOnTab(%d)", tab_id); 70 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 71 host->render_view_host(), L"", register_listeners_js, &result)); 72 EXPECT_TRUE(result); 73 74 // Setting the events should have caused an ExtensionDevToolsBridge to be 75 // registered for the tab's RenderViewHost. 76 DevToolsClientHost* devtools_client_host = 77 devtools_manager->GetDevToolsClientHostFor( 78 tab_contents->render_view_host()); 79 ASSERT_TRUE(devtools_client_host); 80 81 // Test onPageEvent event. 82 result = false; 83 84 DevToolsClientMsg_DispatchOnInspectorFrontend pageEventMessage(""); 85 devtools_client_host->SendMessageToClient(pageEventMessage); 86 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 87 host->render_view_host(), L"", L"testReceivePageEvent()", &result)); 88 EXPECT_TRUE(result); 89 90 // Test onTabClose event. 91 result = false; 92 devtools_manager->UnregisterDevToolsClientHostFor( 93 tab_contents->render_view_host()); 94 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 95 host->render_view_host(), L"", L"testReceiveTabCloseEvent()", &result)); 96 EXPECT_TRUE(result); 97 } 98 99 100 // Tests that ref counting of listeners from multiple processes works. 101 IN_PROC_BROWSER_TEST_F(ExtensionDevToolsBrowserTest, ProcessRefCounting) { 102 ASSERT_TRUE(LoadExtension( 103 test_data_dir_.AppendASCII("devtools").AppendASCII("timeline_api"))); 104 105 // Get the ExtensionHost that is hosting our background page. 106 ExtensionProcessManager* manager = 107 browser()->profile()->GetExtensionProcessManager(); 108 ExtensionHost* host_one = FindHostWithPath(manager, "/background.html", 1); 109 110 ASSERT_TRUE(LoadExtension( 111 test_data_dir_.AppendASCII("devtools").AppendASCII("timeline_api_two"))); 112 ExtensionHost* host_two = FindHostWithPath(manager, 113 "/background_two.html", 2); 114 115 DevToolsManager* devtools_manager = DevToolsManager::GetInstance(); 116 117 // Grab the tab_id of whatever tab happens to be first. 118 TabContents* tab_contents = browser()->GetTabContentsAt(0); 119 ASSERT_TRUE(tab_contents); 120 int tab_id = ExtensionTabUtil::GetTabId(tab_contents); 121 122 // Test setup. 123 bool result = false; 124 std::wstring register_listeners_js = base::StringPrintf( 125 L"setListenersOnTab(%d)", tab_id); 126 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 127 host_one->render_view_host(), L"", register_listeners_js, &result)); 128 EXPECT_TRUE(result); 129 130 // Setting the event listeners should have caused an ExtensionDevToolsBridge 131 // to be registered for the tab's RenderViewHost. 132 ASSERT_TRUE(devtools_manager->GetDevToolsClientHostFor( 133 tab_contents->render_view_host())); 134 135 // Register listeners from the second extension as well. 136 std::wstring script = base::StringPrintf(L"registerListenersForTab(%d)", 137 tab_id); 138 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 139 host_two->render_view_host(), L"", script, &result)); 140 EXPECT_TRUE(result); 141 142 // Removing the listeners from the first extension should leave the bridge 143 // alive. 144 result = false; 145 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 146 host_one->render_view_host(), L"", L"unregisterListeners()", &result)); 147 EXPECT_TRUE(result); 148 ASSERT_TRUE(devtools_manager->GetDevToolsClientHostFor( 149 tab_contents->render_view_host())); 150 151 // Removing the listeners from the second extension should tear the bridge 152 // down. 153 result = false; 154 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 155 host_two->render_view_host(), L"", L"unregisterListeners()", &result)); 156 EXPECT_TRUE(result); 157 ASSERT_FALSE(devtools_manager->GetDevToolsClientHostFor( 158 tab_contents->render_view_host())); 159 } 160