OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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 "chrome/browser/power/process_power_collector.h" | |
6 | |
7 #include "apps/app_window_contents.h" | |
8 #include "apps/app_window_registry.h" | |
9 #include "chrome/browser/profiles/profile_manager.h" | |
10 #include "chrome/browser/ui/apps/chrome_app_delegate.h" | |
11 #include "chrome/browser/ui/browser_commands.h" | |
12 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
13 #include "chrome/test/base/browser_with_test_window_test.h" | |
14 #include "chrome/test/base/testing_browser_process.h" | |
15 #include "chrome/test/base/testing_profile_manager.h" | |
16 #include "components/power/origin_power_map.h" | |
17 #include "components/power/origin_power_map_factory.h" | |
18 #include "content/public/browser/site_instance.h" | |
19 #include "content/public/test/browser_test_utils.h" | |
20 #include "content/public/test/mock_render_process_host.h" | |
21 #include "extensions/browser/app_window/native_app_window.h" | |
22 #include "extensions/common/extension.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 #include "url/gurl.h" | |
25 | |
26 #if defined(OS_CHROMEOS) | |
27 #include "chrome/browser/chromeos/power/power_data_collector.h" | |
28 #include "chromeos/dbus/dbus_thread_manager.h" | |
29 #include "chromeos/dbus/fake_dbus_thread_manager.h" | |
30 #include "chromeos/dbus/power_manager/power_supply_properties.pb.h" | |
31 #endif | |
32 | |
33 using power::OriginPowerMap; | |
34 using power::OriginPowerMapFactory; | |
35 | |
36 class BrowserProcessPowerTest : public BrowserWithTestWindowTest { | |
37 public: | |
38 BrowserProcessPowerTest() {} | |
39 virtual ~BrowserProcessPowerTest() {} | |
40 | |
41 virtual void SetUp() OVERRIDE { | |
42 BrowserWithTestWindowTest::SetUp(); | |
43 #if defined(OS_CHROMEOS) | |
44 chromeos::DBusThreadManager::Shutdown(); | |
Daniel Erat
2014/08/20 19:55:08
this is weird; adding stevenjb@ for advice. should
| |
45 chromeos::FakeDBusThreadManager* fake_dbus_thread_manager = | |
46 new chromeos::FakeDBusThreadManager; | |
47 fake_dbus_thread_manager->SetFakeClients(); | |
48 chromeos::DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager); | |
49 chromeos::PowerDataCollector::InitializeForTesting(); | |
50 | |
51 power_manager::PowerSupplyProperties prop1; | |
52 prop1.set_external_power( | |
53 power_manager::PowerSupplyProperties::DISCONNECTED); | |
54 prop1.set_battery_percent(20.00); | |
55 prop1.set_battery_discharge_rate(1); | |
56 chromeos::PowerDataCollector::Get()->PowerChanged(prop1); | |
57 #endif | |
58 | |
59 profile_manager_.reset( | |
60 new TestingProfileManager(TestingBrowserProcess::GetGlobal())); | |
61 ASSERT_TRUE(profile_manager_->SetUp()); | |
62 } | |
63 | |
64 virtual void TearDown() OVERRIDE { | |
65 #if defined(OS_CHROMEOS) | |
66 chromeos::PowerDataCollector::Shutdown(); | |
67 #endif | |
68 BrowserWithTestWindowTest::TearDown(); | |
69 } | |
70 | |
71 protected: | |
72 scoped_ptr<TestingProfileManager> profile_manager_; | |
73 | |
74 content::MockRenderProcessHost* process(Browser* browser) { | |
75 return static_cast<content::MockRenderProcessHost*>( | |
76 browser->tab_strip_model() | |
77 ->GetActiveWebContents() | |
78 ->GetRenderViewHost() | |
79 ->GetProcess()); | |
80 } | |
81 | |
82 scoped_ptr<base::ProcessHandle> MakeProcessHandle(int process_id) { | |
83 scoped_ptr<base::ProcessHandle> proc_handle(new base::ProcessHandle( | |
84 #if defined(OS_WIN) | |
85 reinterpret_cast<HANDLE>(process_id)) | |
86 #else | |
87 process_id) | |
88 #endif | |
89 ); | |
90 return proc_handle.Pass(); | |
91 } | |
92 }; | |
93 | |
94 class TestAppWindowContents : public apps::AppWindowContents { | |
95 public: | |
96 explicit TestAppWindowContents(content::WebContents* web_contents) { | |
97 web_contents_.reset(web_contents); | |
98 } | |
99 // apps:AppWindowContents | |
100 virtual void Initialize(content::BrowserContext* context, | |
101 const GURL& url) OVERRIDE{}; | |
102 virtual void LoadContents(int32 creator_process_id) OVERRIDE{}; | |
103 virtual void NativeWindowChanged( | |
104 extensions::NativeAppWindow* native_app_window) OVERRIDE{}; | |
105 virtual void NativeWindowClosed() OVERRIDE{}; | |
106 virtual void DispatchWindowShownForTests() const OVERRIDE{}; | |
107 virtual content::WebContents* GetWebContents() const OVERRIDE { | |
108 return web_contents_.get(); | |
109 } | |
110 | |
111 private: | |
112 scoped_ptr<content::WebContents> web_contents_; | |
113 }; | |
114 | |
115 TEST_F(BrowserProcessPowerTest, NoSite) { | |
116 ProcessPowerCollector collector; | |
117 collector.SynchronizeProcesses(); | |
118 EXPECT_EQ(size_t(0), collector.metrics_map_for_testing()->size()); | |
119 } | |
120 | |
121 TEST_F(BrowserProcessPowerTest, OneSite) { | |
122 GURL url("http://www.google.com"); | |
123 AddTab(browser(), url); | |
124 ProcessPowerCollector collector; | |
125 collector.SynchronizeProcesses(); | |
126 ProcessPowerCollector::ProcessMetricsMap* metrics_map = | |
127 collector.metrics_map_for_testing(); | |
128 EXPECT_EQ(size_t(1), metrics_map->size()); | |
129 collector.RecordCpuUsageByOrigin(0); | |
130 | |
131 // Create fake process numbers. | |
132 content::MockRenderProcessHost* rph = process(browser()); | |
133 rph->SetProcessHandle(MakeProcessHandle(1).Pass()); | |
134 | |
135 OriginPowerMap* origin_power_map = | |
136 OriginPowerMapFactory::GetForBrowserContext(profile()); | |
137 EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url)); | |
138 | |
139 collector.SynchronizeProcesses(); | |
140 // Manually update the map to make the CPU usage work. | |
Daniel Erat
2014/08/20 19:55:08
please add a way to fake the cpu usage so that the
Daniel Nishi
2014/08/20 20:56:35
Added a way to set a cpu usage getting callback fo
| |
141 for (ProcessPowerCollector::ProcessMetricsMap::iterator it = | |
142 metrics_map->begin(); | |
143 it != metrics_map->end(); | |
144 ++it) { | |
145 it->second->set_last_cpu_percent(5); | |
146 } | |
147 collector.RecordCpuUsageByOrigin(5); | |
148 EXPECT_EQ(100, origin_power_map->GetPowerForOrigin(url)); | |
149 } | |
150 | |
151 TEST_F(BrowserProcessPowerTest, MultipleSites) { | |
152 Browser::CreateParams native_params(profile(), | |
153 chrome::HOST_DESKTOP_TYPE_NATIVE); | |
154 GURL url1("http://www.google.com"); | |
155 GURL url2("http://www.example.com"); | |
156 GURL url3("https://www.google.com"); | |
157 scoped_ptr<Browser> browser2( | |
158 chrome::CreateBrowserWithTestWindowForParams(&native_params)); | |
159 scoped_ptr<Browser> browser3( | |
160 chrome::CreateBrowserWithTestWindowForParams(&native_params)); | |
161 AddTab(browser(), url1); | |
162 AddTab(browser2.get(), url2); | |
163 AddTab(browser3.get(), url3); | |
164 | |
165 // Create fake process numbers. | |
166 content::MockRenderProcessHost* rph = process(browser()); | |
167 rph->SetProcessHandle(MakeProcessHandle(1).Pass()); | |
Daniel Erat
2014/08/20 19:55:08
nit: condense these to e.g.
process(browser())-
Daniel Nishi
2014/08/20 20:56:35
Done.
| |
168 rph = process(browser2.get()); | |
169 rph->SetProcessHandle(MakeProcessHandle(2).Pass()); | |
170 rph = process(browser3.get()); | |
171 rph->SetProcessHandle(MakeProcessHandle(3).Pass()); | |
172 | |
173 ProcessPowerCollector collector; | |
174 collector.SynchronizeProcesses(); | |
175 ProcessPowerCollector::ProcessMetricsMap* metrics_map = | |
176 collector.metrics_map_for_testing(); | |
177 EXPECT_EQ(size_t(3), metrics_map->size()); | |
Daniel Erat
2014/08/20 19:55:08
nit: static_cast<size_t>(3) or just do 3U
Daniel Nishi
2014/08/20 20:56:34
Done.
| |
178 | |
179 // Since all handlers are uninitialized, this should be 0. | |
180 EXPECT_EQ(0, collector.SynchronizeProcesses()); | |
181 collector.RecordCpuUsageByOrigin(0); | |
182 OriginPowerMap* origin_power_map = | |
183 OriginPowerMapFactory::GetForBrowserContext(profile()); | |
184 EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url1)); | |
185 EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url2)); | |
186 EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url3)); | |
187 | |
188 collector.SynchronizeProcesses(); | |
189 // Manually update the map to make the CPU usage work. | |
190 for (ProcessPowerCollector::ProcessMetricsMap::iterator it = | |
191 metrics_map->begin(); | |
192 it != metrics_map->end(); | |
193 ++it) { | |
194 it->second->set_last_cpu_percent(5); | |
195 } | |
196 collector.RecordCpuUsageByOrigin(15); | |
197 EXPECT_EQ(33, origin_power_map->GetPowerForOrigin(url1)); | |
198 EXPECT_EQ(33, origin_power_map->GetPowerForOrigin(url2)); | |
199 EXPECT_EQ(33, origin_power_map->GetPowerForOrigin(url3)); | |
200 | |
201 // Close some tabs and verify that they are removed from the metrics map. | |
202 chrome::CloseTab(browser2.get()); | |
203 chrome::CloseTab(browser3.get()); | |
204 | |
205 collector.SynchronizeProcesses(); | |
206 collector.RecordCpuUsageByOrigin(0); | |
207 EXPECT_EQ(size_t(1), metrics_map->size()); | |
208 } | |
209 | |
210 TEST_F(BrowserProcessPowerTest, IncognitoDoesntRecordPowerUsage) { | |
211 Browser::CreateParams native_params(profile()->GetOffTheRecordProfile(), | |
212 chrome::HOST_DESKTOP_TYPE_NATIVE); | |
213 scoped_ptr<Browser> incognito_browser( | |
214 chrome::CreateBrowserWithTestWindowForParams(&native_params)); | |
215 GURL url("http://www.google.com"); | |
216 AddTab(browser(), url); | |
217 | |
218 GURL hidden_url("http://foo.com"); | |
219 AddTab(incognito_browser.get(), hidden_url); | |
220 | |
221 // Create fake process numbers. | |
222 content::MockRenderProcessHost* rph = process(browser()); | |
223 rph->SetProcessHandle(MakeProcessHandle(1).Pass()); | |
224 rph = process(incognito_browser.get()); | |
225 rph->SetProcessHandle(MakeProcessHandle(2).Pass()); | |
226 | |
227 ProcessPowerCollector collector; | |
228 collector.SynchronizeProcesses(); | |
229 ProcessPowerCollector::ProcessMetricsMap* metrics_map = | |
230 collector.metrics_map_for_testing(); | |
231 EXPECT_EQ(size_t(1), metrics_map->size()); | |
232 collector.RecordCpuUsageByOrigin(0); | |
233 | |
234 OriginPowerMap* origin_power_map = | |
235 OriginPowerMapFactory::GetForBrowserContext(profile()); | |
236 EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(url)); | |
237 | |
238 collector.SynchronizeProcesses(); | |
239 // Manually update the map to make the CPU usage work. | |
240 for (ProcessPowerCollector::ProcessMetricsMap::iterator it = | |
241 metrics_map->begin(); | |
242 it != metrics_map->end(); | |
243 ++it) { | |
244 it->second->set_last_cpu_percent(5); | |
245 } | |
246 collector.RecordCpuUsageByOrigin(5); | |
247 | |
248 // Verify that the incognito data was not stored. | |
249 EXPECT_EQ(100, origin_power_map->GetPowerForOrigin(url)); | |
250 EXPECT_EQ(0, origin_power_map->GetPowerForOrigin(hidden_url)); | |
251 | |
252 chrome::CloseTab(incognito_browser.get()); | |
253 } | |
254 | |
255 TEST_F(BrowserProcessPowerTest, MultipleProfilesRecordSeparately) { | |
256 scoped_ptr<Profile> other_profile(CreateProfile()); | |
257 Browser::CreateParams native_params(other_profile.get(), | |
258 chrome::HOST_DESKTOP_TYPE_NATIVE); | |
259 scoped_ptr<Browser> other_user( | |
260 chrome::CreateBrowserWithTestWindowForParams(&native_params)); | |
261 | |
262 GURL url("http://www.google.com"); | |
263 AddTab(browser(), url); | |
264 | |
265 GURL hidden_url("http://foo.com"); | |
266 AddTab(other_user.get(), hidden_url); | |
267 | |
268 // Create fake process numbers. | |
269 content::MockRenderProcessHost* rph = process(browser()); | |
270 rph->SetProcessHandle(MakeProcessHandle(1).Pass()); | |
271 rph = process(other_user.get()); | |
272 rph->SetProcessHandle(MakeProcessHandle(2).Pass()); | |
273 | |
274 ProcessPowerCollector collector; | |
275 collector.SynchronizeProcesses(); | |
276 | |
277 EXPECT_EQ(size_t(2), collector.metrics_map_for_testing()->size()); | |
278 collector.RecordCpuUsageByOrigin(0); | |
279 | |
280 // Manually update the map to make the CPU usage work. | |
281 ProcessPowerCollector::ProcessMetricsMap* metrics_map = | |
282 collector.metrics_map_for_testing(); | |
283 for (ProcessPowerCollector::ProcessMetricsMap::iterator it = | |
284 metrics_map->begin(); | |
285 it != metrics_map->end(); | |
286 ++it) { | |
287 it->second->set_last_cpu_percent(5); | |
288 } | |
289 collector.RecordCpuUsageByOrigin(5); | |
290 | |
291 // profile() should have an entry for |url| but not |hidden_url|. | |
292 OriginPowerMap* origin_power_map_first = | |
293 OriginPowerMapFactory::GetForBrowserContext(profile()); | |
294 EXPECT_EQ(100, origin_power_map_first->GetPowerForOrigin(url)); | |
295 EXPECT_EQ(0, origin_power_map_first->GetPowerForOrigin(hidden_url)); | |
296 | |
297 // |other_profile| should have an entry for |hidden_url| but not |url|. | |
298 OriginPowerMap* origin_power_map_second = | |
299 OriginPowerMapFactory::GetForBrowserContext(other_profile.get()); | |
300 EXPECT_EQ(0, origin_power_map_second->GetPowerForOrigin(url)); | |
301 EXPECT_EQ(100, origin_power_map_second->GetPowerForOrigin(hidden_url)); | |
302 | |
303 // Clean up | |
304 chrome::CloseTab(other_user.get()); | |
305 } | |
306 | |
307 const char kTestAppId[] = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; | |
Daniel Erat
2014/08/20 19:55:08
nit: move this inside of the test that uses it
Daniel Nishi
2014/08/20 20:56:35
Done.
| |
308 | |
309 TEST_F(BrowserProcessPowerTest, AppsRecordPowerUsage) { | |
310 Profile* current_profile = | |
311 profile_manager_->CreateTestingProfile("Test user"); | |
312 | |
313 // Install an app (an extension*). | |
Daniel Erat
2014/08/20 19:55:08
this should be indented two spaces
Daniel Nishi
2014/08/20 20:56:35
Done.
| |
314 #if defined(OS_WIN) | |
315 base::FilePath extension_path(FILE_PATH_LITERAL("c:\\foo")); | |
Daniel Erat
2014/08/20 19:55:08
probably there's some other way of creating a fake
| |
316 #elif defined(OS_POSIX) | |
317 base::FilePath extension_path(FILE_PATH_LITERAL("/foo")); | |
318 #endif | |
319 base::DictionaryValue manifest; | |
320 manifest.SetString("name", "Fake Name"); | |
321 manifest.SetString("version", "1"); | |
322 std::string error; | |
323 scoped_refptr<extensions::Extension> extension( | |
324 extensions::Extension::Create(extension_path, | |
325 extensions::Manifest::INTERNAL, | |
326 manifest, | |
327 extensions::Extension::NO_FLAGS, | |
328 kTestAppId, | |
329 &error)); | |
330 EXPECT_TRUE(extension.get()) << error; | |
331 | |
332 GURL url("chrome-extension://aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); | |
Daniel Erat
2014/08/20 19:55:08
use the above constant here
Daniel Nishi
2014/08/20 20:56:35
I think the standard way to do this is with hardco
| |
333 // Use that to create a new AppWindow -- hopefully that can avoid | |
334 // dependencies. | |
Daniel Erat
2014/08/20 19:55:08
i don't fully understand this comment (partially t
Daniel Nishi
2014/08/20 20:56:35
Oh, whoops. That comment was one I left as a note
Daniel Nishi
2014/08/20 20:57:40
FWIW, it was a comment left from when this was ori
| |
335 apps::AppWindow* window = | |
336 new apps::AppWindow(current_profile, new ChromeAppDelegate(), extension); | |
337 scoped_ptr<content::WebContents> web_contents( | |
338 content::WebContents::Create(content::WebContents::CreateParams( | |
339 current_profile, | |
340 content::SiteInstance::CreateForURL(current_profile, url)))); | |
341 window->SetAppWindowContentsForTesting(scoped_ptr<apps::AppWindowContents>( | |
342 new TestAppWindowContents(web_contents.get()))); | |
343 apps::AppWindowRegistry* app_registry = | |
344 apps::AppWindowRegistry::Get(current_profile); | |
345 app_registry->AddAppWindow(window); | |
346 | |
347 ProcessPowerCollector collector; | |
348 collector.SynchronizeProcesses(); | |
349 EXPECT_EQ(size_t(1), collector.metrics_map_for_testing()->size()); | |
350 collector.RecordCpuUsageByOrigin(0); | |
351 | |
352 app_registry->RemoveAppWindow(window); | |
353 collector.SynchronizeProcesses(); | |
354 EXPECT_EQ(size_t(0), collector.metrics_map_for_testing()->size()); | |
355 collector.RecordCpuUsageByOrigin(0); | |
356 } | |
OLD | NEW |