Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(80)

Side by Side Diff: chrome/browser/extensions/api/power/power_api_unittest.cc

Issue 12576018: Add chrome.power extension API. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: update PermissionsTest.PermissionMessages Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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/extensions/api/power/power_api.h"
6
7 #include <deque>
8 #include <string>
9
10 #include "base/basictypes.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/memory/weak_ptr.h"
13 #include "chrome/browser/extensions/api/power/power_api_constants.h"
14 #include "chrome/browser/extensions/api/power/power_api_manager.h"
15 #include "chrome/browser/extensions/extension_function_test_utils.h"
16 #include "chrome/common/chrome_notification_types.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "chrome/test/base/browser_with_test_window_test.h"
19 #include "content/public/browser/power_save_blocker.h"
20
21 namespace utils = extension_function_test_utils;
22 namespace constants = extensions::power_api_constants;
23
24 namespace extensions {
25
26 namespace {
27
28 // Different actions that can be performed as a result of a
29 // PowerSaveBlocker being created or destroyed.
30 enum Request {
31 BLOCK_APP_SUSPENSION,
32 UNBLOCK_APP_SUSPENSION,
33 BLOCK_DISPLAY_SLEEP,
34 UNBLOCK_DISPLAY_SLEEP,
35 // Returned by PowerSaveBlockerStubManager::PopFirstRequest() when no
36 // requests are present.
37 NONE,
38 };
39
40 // Stub implementation of content::PowerSaveBlocker that just runs a
41 // callback on destruction.
42 class PowerSaveBlockerStub : public content::PowerSaveBlocker {
43 public:
44 explicit PowerSaveBlockerStub(base::Closure unblock_callback)
45 : unblock_callback_(unblock_callback) {
46 }
47
48 virtual ~PowerSaveBlockerStub() {
49 unblock_callback_.Run();
50 }
51
52 private:
53 base::Closure unblock_callback_;
54
55 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub);
56 };
57
58 // Manages PowerSaveBlockerStub objects. Tests can instantiate this class
59 // to make PowerApiManager's calls to create PowerSaveBlockers record the
60 // actions that would've been performed instead of actually blocking and
61 // unblocking power management.
62 class PowerSaveBlockerStubManager {
63 public:
64 PowerSaveBlockerStubManager() : weak_ptr_factory_(this) {
65 // Use base::Unretained since callbacks with return values can't use
66 // weak pointers.
67 PowerApiManager::GetInstance()->set_create_blocker_function_for_testing(
68 scoped_ptr<PowerApiManager::CreateBlockerFunction>(
69 new PowerApiManager::CreateBlockerFunction(
70 base::Bind(&PowerSaveBlockerStubManager::CreateStub,
71 base::Unretained(this)))));
72 }
73
74 ~PowerSaveBlockerStubManager() {
75 PowerApiManager::GetInstance()->set_create_blocker_function_for_testing(
76 scoped_ptr<PowerApiManager::CreateBlockerFunction>());
77 }
78
79 // Removes and returns the first item from |requests_|. Returns NONE if
80 // |requests_| is empty.
81 Request PopFirstRequest() {
82 if (requests_.empty())
83 return NONE;
84
85 Request request = requests_.front();
86 requests_.pop_front();
87 return request;
88 }
89
90 private:
91 // Creates a new PowerSaveBlockerStub of type |type|.
92 scoped_ptr<content::PowerSaveBlocker> CreateStub(
93 content::PowerSaveBlocker::PowerSaveBlockerType type,
94 const std::string& reason) {
95 Request unblock_request = NONE;
96 switch (type) {
97 case content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension:
98 requests_.push_back(BLOCK_APP_SUSPENSION);
99 unblock_request = UNBLOCK_APP_SUSPENSION;
100 break;
101 case content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep:
102 requests_.push_back(BLOCK_DISPLAY_SLEEP);
103 unblock_request = UNBLOCK_DISPLAY_SLEEP;
104 break;
105 }
106 return scoped_ptr<content::PowerSaveBlocker>(
107 new PowerSaveBlockerStub(
108 base::Bind(&PowerSaveBlockerStubManager::AppendRequest,
109 weak_ptr_factory_.GetWeakPtr(),
110 unblock_request)));
111 }
112
113 void AppendRequest(Request request) {
114 requests_.push_back(request);
115 }
116
117 // Requests in chronological order.
118 std::deque<Request> requests_;
119
120 base::WeakPtrFactory<PowerSaveBlockerStubManager> weak_ptr_factory_;
121
122 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStubManager);
123 };
124
125 } // namespace
126
127 class PowerApiTest : public BrowserWithTestWindowTest {
128 public:
129 virtual void SetUp() OVERRIDE {
130 BrowserWithTestWindowTest::SetUp();
131 manager_.reset(new PowerSaveBlockerStubManager);
132 extension_ = utils::CreateEmptyExtensionWithLocation(
133 extensions::Manifest::UNPACKED);
134 }
135
136 protected:
137 // Shorthand for PowerRequestKeepAwakeFunction and
138 // PowerReleaseKeepAwakeFunction.
139 enum FunctionType {
140 REQUEST,
141 RELEASE,
142 };
143
144 // Args commonly passed to PowerSaveBlockerStubManager::CallFunction().
145 static const std::string kDisplayArgs;
146 static const std::string kSystemArgs;
147 static const std::string kEmptyArgs;
148
149 // Calls the function described by |type| with |args|, a JSON list of
150 // arguments, on behalf of |extension|.
151 bool CallFunction(FunctionType type,
152 const std::string& args,
153 extensions::Extension* extension) {
154 UIThreadExtensionFunction* function =
155 type == REQUEST ?
156 static_cast<UIThreadExtensionFunction*>(
157 new PowerRequestKeepAwakeFunction) :
158 static_cast<UIThreadExtensionFunction*>(
159 new PowerReleaseKeepAwakeFunction);
160 function->set_extension(extension);
161 return utils::RunFunction(function, args, browser(), utils::NONE);
162 }
163
164 // Send a notification to PowerApiManager saying that |extension| has
165 // been unloaded.
166 void UnloadExtension(extensions::Extension* extension) {
167 UnloadedExtensionInfo details(
168 extension, extension_misc::UNLOAD_REASON_UNINSTALL);
169 PowerApiManager::GetInstance()->Observe(
170 chrome::NOTIFICATION_EXTENSION_UNLOADED,
171 content::Source<Profile>(browser()->profile()),
172 content::Details<UnloadedExtensionInfo>(&details));
173 }
174
175 scoped_ptr<PowerSaveBlockerStubManager> manager_;
176 scoped_refptr<extensions::Extension> extension_;
177 };
178
179 const std::string PowerApiTest::kDisplayArgs =
180 std::string("[\"") + constants::kDisplayLevelValue + "\"]";
181 const std::string PowerApiTest::kSystemArgs =
182 std::string("[\"") + constants::kSystemLevelValue + "\"]";
183 const std::string PowerApiTest::kEmptyArgs = "[]";
184
185 TEST_F(PowerApiTest, RequestAndRelease) {
186 // Simulate an extension making and releasing a "display" request, a
187 // "system" request, a request without any arguments (which should be
188 // treated as "display"), and a request with an invalid argument (which
189 // should also be treated as "display").
190 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
191 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
192 EXPECT_EQ(NONE, manager_->PopFirstRequest());
193 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
194 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
195 EXPECT_EQ(NONE, manager_->PopFirstRequest());
196
197 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension_.get()));
198 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
199 EXPECT_EQ(NONE, manager_->PopFirstRequest());
200 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
201 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
202 EXPECT_EQ(NONE, manager_->PopFirstRequest());
203
204 ASSERT_TRUE(CallFunction(REQUEST, kEmptyArgs, extension_.get()));
205 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
206 EXPECT_EQ(NONE, manager_->PopFirstRequest());
207 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
208 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
209 EXPECT_EQ(NONE, manager_->PopFirstRequest());
210
211 ASSERT_TRUE(CallFunction(REQUEST, "[\"foo\"]", extension_.get()));
212 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
213 EXPECT_EQ(NONE, manager_->PopFirstRequest());
214 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
215 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
216 EXPECT_EQ(NONE, manager_->PopFirstRequest());
217 }
218
219 TEST_F(PowerApiTest, RequestWithoutRelease) {
220 // Simulate an extension calling requestKeepAwake() without calling
221 // releaseKeepAwake(). The override should be automatically removed when
222 // the extension is unloaded.
223 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
224 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
225 EXPECT_EQ(NONE, manager_->PopFirstRequest());
226
227 UnloadExtension(extension_.get());
228 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
229 EXPECT_EQ(NONE, manager_->PopFirstRequest());
230 }
231
232 TEST_F(PowerApiTest, ReleaseWithoutRequest) {
233 // Simulate an extension calling releaseKeepAwake() without having
234 // calling requestKeepAwake() earlier. The call should be ignored.
235 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
236 EXPECT_EQ(NONE, manager_->PopFirstRequest());
237 }
238
239 TEST_F(PowerApiTest, UpgradeRequest) {
240 // Simulate an extension calling requestKeepAwake("system") and then
241 // requestKeepAwake("display"). When the second call is made, a
242 // display-sleep-blocking request should be made before the initial
243 // app-suspension-blocking request is released.
244 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension_.get()));
245 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
246 EXPECT_EQ(NONE, manager_->PopFirstRequest());
247
248 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
249 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
250 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
251 EXPECT_EQ(NONE, manager_->PopFirstRequest());
252
253 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
254 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
255 EXPECT_EQ(NONE, manager_->PopFirstRequest());
256 }
257
258 TEST_F(PowerApiTest, DowngradeRequest) {
259 // Simulate an extension calling requestKeepAwake("display") and then
260 // requestKeepAwake("system"). When the second call is made, an
261 // app-suspension-blocking request should be made before the initial
262 // display-sleep-blocking request is released.
263 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
264 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
265 EXPECT_EQ(NONE, manager_->PopFirstRequest());
266
267 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension_.get()));
268 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
269 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
270 EXPECT_EQ(NONE, manager_->PopFirstRequest());
271
272 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
273 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
274 EXPECT_EQ(NONE, manager_->PopFirstRequest());
275 }
276
277 TEST_F(PowerApiTest, MultipleExtensions) {
278 // Simulate an extension blocking the display from sleeping.
279 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
280 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
281 EXPECT_EQ(NONE, manager_->PopFirstRequest());
282
283 // Create a second extension that blocks system suspend. No additional
284 // PowerSaveBlocker is needed; the blocker from the first extension
285 // already covers the behavior requested by the second extension.
286 scoped_ptr<base::DictionaryValue> extension_value(
287 utils::ParseDictionary("{\"name\": \"Test\", \"version\": \"1.0\"}"));
288 scoped_refptr<extensions::Extension> extension2(
289 utils::CreateExtension(extensions::Manifest::UNPACKED,
290 extension_value.get(), "second_extension"));
291 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension2.get()));
292 EXPECT_EQ(NONE, manager_->PopFirstRequest());
293
294 // When the first extension is unloaded, a new app-suspension blocker
295 // should be created before the display-sleep blocker is destroyed.
296 UnloadExtension(extension_.get());
297 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
298 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
299 EXPECT_EQ(NONE, manager_->PopFirstRequest());
300
301 // Make the first extension block display-sleep again.
302 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
303 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
304 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
305 EXPECT_EQ(NONE, manager_->PopFirstRequest());
306 }
307
308 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698