12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/power/power_api.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <deque>
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <string>
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/basictypes.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/ref_counted.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/weak_ptr.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/api/power/power_api_manager.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/extension_function_test_utils.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/extensions/extension.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/test/base/browser_with_test_window_test.h"
19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/notification_details.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "content/public/browser/notification_source.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/power_save_blocker.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace utils = extension_function_test_utils;
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace extensions {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Args commonly passed to PowerSaveBlockerStubManager::CallFunction().
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kDisplayArgs[] = "[\"display\"]";
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kSystemArgs[] = "[\"system\"]";
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kEmptyArgs[] = "[]";
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Different actions that can be performed as a result of a
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// PowerSaveBlocker being created or destroyed.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)enum Request {
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BLOCK_APP_SUSPENSION,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UNBLOCK_APP_SUSPENSION,
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BLOCK_DISPLAY_SLEEP,
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UNBLOCK_DISPLAY_SLEEP,
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Returned by PowerSaveBlockerStubManager::PopFirstRequest() when no
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requests are present.
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NONE,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Stub implementation of content::PowerSaveBlocker that just runs a
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// callback on destruction.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PowerSaveBlockerStub : public content::PowerSaveBlocker {
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit PowerSaveBlockerStub(base::Closure unblock_callback)
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : unblock_callback_(unblock_callback) {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~PowerSaveBlockerStub() {
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unblock_callback_.Run();
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure unblock_callback_;
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStub);
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Manages PowerSaveBlockerStub objects.  Tests can instantiate this class
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to make PowerApiManager's calls to create PowerSaveBlockers record the
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// actions that would've been performed instead of actually blocking and
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// unblocking power management.
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PowerSaveBlockerStubManager {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PowerSaveBlockerStubManager() : weak_ptr_factory_(this) {
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Use base::Unretained since callbacks with return values can't use
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // weak pointers.
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PowerApiManager::GetInstance()->SetCreateBlockerFunctionForTesting(
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&PowerSaveBlockerStubManager::CreateStub,
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)));
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~PowerSaveBlockerStubManager() {
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PowerApiManager::GetInstance()->SetCreateBlockerFunctionForTesting(
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        PowerApiManager::CreateBlockerFunction());
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Removes and returns the first item from |requests_|.  Returns NONE if
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |requests_| is empty.
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Request PopFirstRequest() {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (requests_.empty())
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NONE;
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Request request = requests_.front();
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    requests_.pop_front();
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return request;
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates a new PowerSaveBlockerStub of type |type|.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<content::PowerSaveBlocker> CreateStub(
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      content::PowerSaveBlocker::PowerSaveBlockerType type,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const std::string& reason) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Request unblock_request = NONE;
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (type) {
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case content::PowerSaveBlocker::kPowerSaveBlockPreventAppSuspension:
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        requests_.push_back(BLOCK_APP_SUSPENSION);
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        unblock_request = UNBLOCK_APP_SUSPENSION;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case content::PowerSaveBlocker::kPowerSaveBlockPreventDisplaySleep:
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        requests_.push_back(BLOCK_DISPLAY_SLEEP);
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        unblock_request = UNBLOCK_DISPLAY_SLEEP;
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return scoped_ptr<content::PowerSaveBlocker>(
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        new PowerSaveBlockerStub(
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Bind(&PowerSaveBlockerStubManager::AppendRequest,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       weak_ptr_factory_.GetWeakPtr(),
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       unblock_request)));
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void AppendRequest(Request request) {
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    requests_.push_back(request);
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Requests in chronological order.
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::deque<Request> requests_;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WeakPtrFactory<PowerSaveBlockerStubManager> weak_ptr_factory_;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PowerSaveBlockerStubManager);
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class PowerApiTest : public BrowserWithTestWindowTest {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void SetUp() OVERRIDE {
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserWithTestWindowTest::SetUp();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    manager_.reset(new PowerSaveBlockerStubManager);
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    extension_ = utils::CreateEmptyExtensionWithLocation(
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extensions::Manifest::UNPACKED);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shorthand for PowerRequestKeepAwakeFunction and
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // PowerReleaseKeepAwakeFunction.
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum FunctionType {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    REQUEST,
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RELEASE,
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Calls the function described by |type| with |args|, a JSON list of
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // arguments, on behalf of |extension|.
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool CallFunction(FunctionType type,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& args,
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    extensions::Extension* extension) {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_refptr<UIThreadExtensionFunction> function(
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        type == REQUEST ?
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<UIThreadExtensionFunction*>(
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new PowerRequestKeepAwakeFunction) :
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        static_cast<UIThreadExtensionFunction*>(
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            new PowerReleaseKeepAwakeFunction));
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    function->set_extension(extension);
160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return utils::RunFunction(function.get(), args, browser(), utils::NONE);
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Send a notification to PowerApiManager saying that |extension| has
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // been unloaded.
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void UnloadExtension(extensions::Extension* extension) {
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    UnloadedExtensionInfo details(
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        extension, extension_misc::UNLOAD_REASON_UNINSTALL);
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PowerApiManager::GetInstance()->Observe(
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        chrome::NOTIFICATION_EXTENSION_UNLOADED,
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Source<Profile>(browser()->profile()),
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        content::Details<UnloadedExtensionInfo>(&details));
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<PowerSaveBlockerStubManager> manager_;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<extensions::Extension> extension_;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(PowerApiTest, RequestAndRelease) {
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simulate an extension making and releasing a "display" request and a
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // "system" request.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension_.get()));
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(PowerApiTest, RequestWithoutRelease) {
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simulate an extension calling requestKeepAwake() without calling
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // releaseKeepAwake().  The override should be automatically removed when
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the extension is unloaded.
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnloadExtension(extension_.get());
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(PowerApiTest, ReleaseWithoutRequest) {
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simulate an extension calling releaseKeepAwake() without having
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // calling requestKeepAwake() earlier.  The call should be ignored.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(PowerApiTest, UpgradeRequest) {
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simulate an extension calling requestKeepAwake("system") and then
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requestKeepAwake("display").  When the second call is made, a
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // display-sleep-blocking request should be made before the initial
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // app-suspension-blocking request is released.
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension_.get()));
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(PowerApiTest, DowngradeRequest) {
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simulate an extension calling requestKeepAwake("display") and then
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // requestKeepAwake("system").  When the second call is made, an
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // app-suspension-blocking request should be made before the initial
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // display-sleep-blocking request is released.
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension_.get()));
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(RELEASE, kEmptyArgs, extension_.get()));
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(PowerApiTest, MultipleExtensions) {
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Simulate an extension blocking the display from sleeping.
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Create a second extension that blocks system suspend.  No additional
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // PowerSaveBlocker is needed; the blocker from the first extension
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // already covers the behavior requested by the second extension.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<base::DictionaryValue> extension_value(
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      utils::ParseDictionary("{\"name\": \"Test\", \"version\": \"1.0\"}"));
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<extensions::Extension> extension2(
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      utils::CreateExtension(extensions::Manifest::UNPACKED,
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             extension_value.get(), "second_extension"));
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kSystemArgs, extension2.get()));
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When the first extension is unloaded, a new app-suspension blocker
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // should be created before the display-sleep blocker is destroyed.
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UnloadExtension(extension_.get());
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make the first extension block display-sleep again.
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_TRUE(CallFunction(REQUEST, kDisplayArgs, extension_.get()));
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(BLOCK_DISPLAY_SLEEP, manager_->PopFirstRequest());
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(UNBLOCK_APP_SUSPENSION, manager_->PopFirstRequest());
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(NONE, manager_->PopFirstRequest());
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace extensions
286