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.
FindHostWithPath(ExtensionProcessManager * manager,const std::string & path,int expected_hosts)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.
IN_PROC_BROWSER_TEST_F(ExtensionDevToolsBrowserTest,FLAKY_TimelineApi)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.
IN_PROC_BROWSER_TEST_F(ExtensionDevToolsBrowserTest,ProcessRefCounting)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