Add testing/scripts/OWNERS
[chromium-blink-merge.git] / extensions / browser / api / power / power_api_unittest.cc
blob3e7d8d4f3369aef4cf26ee15f93a23586cd81444
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.
5 #include "extensions/browser/api/power/power_api.h"
7 #include <deque>
8 #include <string>
10 #include "base/basictypes.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/memory/weak_ptr.h"
14 #include "content/public/browser/power_save_blocker.h"
15 #include "extensions/browser/api/power/power_api_manager.h"
16 #include "extensions/browser/api_test_utils.h"
17 #include "extensions/browser/api_unittest.h"
18 #include "extensions/common/extension.h"
19 #include "extensions/common/test_util.h"
21 namespace extensions {
23 namespace {
25 // Args commonly passed to PowerSaveBlockerStubManager::CallFunction().
26 const char kDisplayArgs[] = "[\"display\"]";
27 const char kSystemArgs[] = "[\"system\"]";
28 const char kEmptyArgs[] = "[]";
30 // Different actions that can be performed as a result of a
31 // PowerSaveBlocker being created or destroyed.
32 enum Request {
33 BLOCK_APP_SUSPENSION,
34 UNBLOCK_APP_SUSPENSION,
35 BLOCK_DISPLAY_SLEEP,
36 UNBLOCK_DISPLAY_SLEEP,
37 // Returned by PowerSaveBlockerStubManager::PopFirstRequest() when no
38 // requests are present.
39 NONE,
42 // Stub implementation of content::PowerSaveBlocker that just runs a
43 // callback on destruction.
44 class PowerSaveBlockerStub : public content::PowerSaveBlocker {
45 public:
46 explicit PowerSaveBlockerStub(base::Closure unblock_callback)
47 : unblock_callback_(unblock_callback) {
50 ~PowerSaveBlockerStub() override { unblock_callback_.Run(); }
52 private:
53 base::Closure unblock_callback_;
55 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub);
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 explicit PowerSaveBlockerStubManager(content::BrowserContext* context)
65 : browser_context_(context),
66 weak_ptr_factory_(this) {
67 // Use base::Unretained since callbacks with return values can't use
68 // weak pointers.
69 PowerApiManager::Get(browser_context_)->SetCreateBlockerFunctionForTesting(
70 base::Bind(&PowerSaveBlockerStubManager::CreateStub,
71 base::Unretained(this)));
74 ~PowerSaveBlockerStubManager() {
75 PowerApiManager::Get(browser_context_)->SetCreateBlockerFunctionForTesting(
76 PowerApiManager::CreateBlockerFunction());
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;
85 Request request = requests_.front();
86 requests_.pop_front();
87 return request;
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;
106 return scoped_ptr<content::PowerSaveBlocker>(
107 new PowerSaveBlockerStub(
108 base::Bind(&PowerSaveBlockerStubManager::AppendRequest,
109 weak_ptr_factory_.GetWeakPtr(),
110 unblock_request)));
113 void AppendRequest(Request request) {
114 requests_.push_back(request);
117 content::BrowserContext* browser_context_;
119 // Requests in chronological order.
120 std::deque<Request> requests_;
122 base::WeakPtrFactory<PowerSaveBlockerStubManager> weak_ptr_factory_;
124 DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStubManager);
127 } // namespace
129 class PowerApiTest : public ApiUnitTest {
130 public:
131 void SetUp() override {
132 ApiUnitTest::SetUp();
133 manager_.reset(new PowerSaveBlockerStubManager(browser_context()));
136 void TearDown() override {
137 manager_.reset();
138 ApiUnitTest::TearDown();
141 protected:
142 // Shorthand for PowerRequestKeepAwakeFunction and
143 // PowerReleaseKeepAwakeFunction.
144 enum FunctionType {
145 REQUEST,
146 RELEASE,
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 const extensions::Extension* extension) {
154 scoped_refptr<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 api_test_utils::RunFunction(function.get(), args, browser_context());
164 // Send a notification to PowerApiManager saying that |extension| has
165 // been unloaded.
166 void UnloadExtension(const extensions::Extension* extension) {
167 PowerApiManager::Get(browser_context())->OnExtensionUnloaded(
168 browser_context(), extension, UnloadedExtensionInfo::REASON_UNINSTALL);
171 scoped_ptr<PowerSaveBlockerStubManager> manager_;
174 TEST_F(PowerApiTest, RequestAndRelease) {
175 // Simulate an extension making and releasing a "display" request and a
176 // "system" request.
177 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension()));
178 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
179 EXPECT_EQ(NONE, manager_->PopFirstRequest());
180 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension()));
181 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
182 EXPECT_EQ(NONE, manager_->PopFirstRequest());
184 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension()));
185 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
186 EXPECT_EQ(NONE, manager_->PopFirstRequest());
187 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension()));
188 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
189 EXPECT_EQ(NONE, manager_->PopFirstRequest());
192 TEST_F(PowerApiTest, RequestWithoutRelease) {
193 // Simulate an extension calling requestKeepAwake() without calling
194 // releaseKeepAwake(). The override should be automatically removed when
195 // the extension is unloaded.
196 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension()));
197 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
198 EXPECT_EQ(NONE, manager_->PopFirstRequest());
200 UnloadExtension(extension());
201 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
202 EXPECT_EQ(NONE, manager_->PopFirstRequest());
205 TEST_F(PowerApiTest, ReleaseWithoutRequest) {
206 // Simulate an extension calling releaseKeepAwake() without having
207 // calling requestKeepAwake() earlier. The call should be ignored.
208 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension()));
209 EXPECT_EQ(NONE, manager_->PopFirstRequest());
212 TEST_F(PowerApiTest, UpgradeRequest) {
213 // Simulate an extension calling requestKeepAwake("system") and then
214 // requestKeepAwake("display"). When the second call is made, a
215 // display-sleep-blocking request should be made before the initial
216 // app-suspension-blocking request is released.
217 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension()));
218 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
219 EXPECT_EQ(NONE, manager_->PopFirstRequest());
221 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension()));
222 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
223 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
224 EXPECT_EQ(NONE, manager_->PopFirstRequest());
226 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension()));
227 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
228 EXPECT_EQ(NONE, manager_->PopFirstRequest());
231 TEST_F(PowerApiTest, DowngradeRequest) {
232 // Simulate an extension calling requestKeepAwake("display") and then
233 // requestKeepAwake("system"). When the second call is made, an
234 // app-suspension-blocking request should be made before the initial
235 // display-sleep-blocking request is released.
236 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension()));
237 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
238 EXPECT_EQ(NONE, manager_->PopFirstRequest());
240 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension()));
241 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
242 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
243 EXPECT_EQ(NONE, manager_->PopFirstRequest());
245 ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension()));
246 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
247 EXPECT_EQ(NONE, manager_->PopFirstRequest());
250 TEST_F(PowerApiTest, MultipleExtensions) {
251 // Simulate an extension blocking the display from sleeping.
252 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension()));
253 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
254 EXPECT_EQ(NONE, manager_->PopFirstRequest());
256 // Create a second extension that blocks system suspend. No additional
257 // PowerSaveBlocker is needed; the blocker from the first extension
258 // already covers the behavior requested by the second extension.
259 scoped_refptr<Extension> extension2(test_util::CreateEmptyExtension("id2"));
260 ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension2.get()));
261 EXPECT_EQ(NONE, manager_->PopFirstRequest());
263 // When the first extension is unloaded, a new app-suspension blocker
264 // should be created before the display-sleep blocker is destroyed.
265 UnloadExtension(extension());
266 EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
267 EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
268 EXPECT_EQ(NONE, manager_->PopFirstRequest());
270 // Make the first extension block display-sleep again.
271 ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension()));
272 EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
273 EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
274 EXPECT_EQ(NONE, manager_->PopFirstRequest());
277 } // namespace extensions