blob: 9206cad017333d4a8f0de7c2802e0199c3a9d219 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h"
#include <memory>
#include <utility>
#include "ash/public/cpp/ash_pref_names.h"
#include "base/json/json_writer.h"
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/values.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chromeos/dbus/fake_power_manager_client.h"
#include "chromeos/dbus/power_policy_controller.h"
#include "components/policy/core/browser/browser_policy_connector.h"
#include "components/policy/core/common/mock_configuration_policy_provider.h"
#include "components/policy/policy_constants.h"
#include "components/prefs/pref_service.h"
#include "content/public/test/test_web_ui.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::Return;
using testing::_;
namespace chromeos {
namespace settings {
namespace {
PrefService* GetPrefs() {
return ProfileManager::GetActiveUserProfile()->GetPrefs();
}
} // namespace
class TestPowerHandler : public PowerHandler {
public:
explicit TestPowerHandler(PrefService* prefs) : PowerHandler(prefs) {}
// Pull WebUIMessageHandler::set_web_ui() into public so tests can call it.
using PowerHandler::set_web_ui;
};
class PowerHandlerTest : public InProcessBrowserTest {
protected:
PowerHandlerTest() = default;
~PowerHandlerTest() override = default;
// InProcessBrowserTest:
void SetUpInProcessBrowserTestFixture() override {
// Initialize user policy.
ON_CALL(provider_, IsInitializationComplete(_)).WillByDefault(Return(true));
policy::BrowserPolicyConnector::SetPolicyProviderForTesting(&provider_);
}
void SetUpOnMainThread() override {
handler_ = std::make_unique<TestPowerHandler>(GetPrefs());
test_api_ = std::make_unique<PowerHandler::TestAPI>(handler_.get());
handler_->set_web_ui(&web_ui_);
handler_->RegisterMessages();
handler_->AllowJavascriptForTesting();
base::RunLoop().RunUntilIdle();
}
void TearDownOnMainThread() override {
test_api_.reset();
handler_.reset();
}
// Returns a JSON representation of the contents of the last message sent to
// WebUI about settings being changed.
std::string GetLastSettingsChangedMessage() WARN_UNUSED_RESULT {
for (auto it = web_ui_.call_data().rbegin();
it != web_ui_.call_data().rend(); ++it) {
const content::TestWebUI::CallData* data = it->get();
std::string name;
const base::DictionaryValue* dict = nullptr;
if (data->function_name() != "cr.webUIListenerCallback" ||
!data->arg1()->GetAsString(&name) ||
name != PowerHandler::kPowerManagementSettingsChangedName) {
continue;
}
if (!data->arg2()->GetAsDictionary(&dict)) {
ADD_FAILURE() << "Failed to get dict from " << name << " message";
continue;
}
std::string out;
EXPECT_TRUE(base::JSONWriter::Write(*dict, &out));
return out;
}
ADD_FAILURE() << PowerHandler::kPowerManagementSettingsChangedName
<< " message was not sent";
return std::string();
}
// Returns a string for the given settings that can be compared against the
// output of GetLastSettingsChangedMessage().
std::string CreateSettingsChangedString(
PowerHandler::IdleBehavior idle_behavior,
bool idle_controlled,
PowerPolicyController::Action lid_closed_behavior,
bool lid_closed_controlled,
bool has_lid) {
base::DictionaryValue dict;
dict.SetInteger(PowerHandler::kIdleBehaviorKey,
static_cast<int>(idle_behavior));
dict.SetBoolean(PowerHandler::kIdleControlledKey, idle_controlled);
dict.SetInteger(PowerHandler::kLidClosedBehaviorKey, lid_closed_behavior);
dict.SetBoolean(PowerHandler::kLidClosedControlledKey,
lid_closed_controlled);
dict.SetBoolean(PowerHandler::kHasLidKey, has_lid);
std::string out;
EXPECT_TRUE(base::JSONWriter::Write(dict, &out));
return out;
}
// Returns the user-set value of the integer pref identified by |name| or -1
// if the pref is unset.
int GetIntPref(const std::string& name) {
if (!GetPrefs()->HasPrefPath(name))
return -1;
return GetPrefs()->GetInteger(name);
}
// Sets a policy update which will cause power pref managed change.
void SetPolicyForPolicyKey(policy::PolicyMap* policy_map,
const std::string& policy_key,
std::unique_ptr<base::Value> value) {
policy_map->Set(policy_key, policy::POLICY_LEVEL_MANDATORY,
policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD,
std::move(value), nullptr);
provider_.UpdateChromePolicy(*policy_map);
base::RunLoop().RunUntilIdle();
}
std::unique_ptr<TestPowerHandler> handler_;
std::unique_ptr<TestPowerHandler::TestAPI> test_api_;
content::TestWebUI web_ui_;
policy::MockConfigurationPolicyProvider provider_;
private:
DISALLOW_COPY_AND_ASSIGN(PowerHandlerTest);
};
// Verifies that settings are sent to WebUI when requested.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendInitialSettings) {
test_api_->RequestPowerManagementSettings();
EXPECT_EQ(
CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
}
// Verifies that WebUI receives updated settings when the lid state changes.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendSettingsForLidStateChanges) {
chromeos::FakePowerManagerClient::Get()->SetLidState(
PowerManagerClient::LidState::NOT_PRESENT, base::TimeTicks());
EXPECT_EQ(
CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */, false /* has_lid */),
GetLastSettingsChangedMessage());
chromeos::FakePowerManagerClient::Get()->SetLidState(
PowerManagerClient::LidState::OPEN, base::TimeTicks());
EXPECT_EQ(
CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
false /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
}
// Verifies that when various prefs are controlled, the corresponding settings
// are reported as controlled to WebUI.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendSettingsForControlledPrefs) {
policy::PolicyMap policy_map;
// Making an arbitrary delay pref managed should result in the idle setting
// being reported as controlled.
SetPolicyForPolicyKey(&policy_map, policy::key::kScreenDimDelayAC,
std::make_unique<base::Value>(10000));
EXPECT_EQ(
CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
true /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
// Ditto for making the lid action pref managed.
SetPolicyForPolicyKey(
&policy_map, policy::key::kLidCloseAction,
std::make_unique<base::Value>(PowerPolicyController::ACTION_SUSPEND));
EXPECT_EQ(
CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
true /* idle_controlled */, PowerPolicyController::ACTION_SUSPEND,
true /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
}
// Verifies that idle-related prefs are distilled into the proper WebUI
// settings.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendIdleSettingForPrefChanges) {
// Set a do-nothing idle action and a nonzero screen-off delay.
GetPrefs()->Set(ash::prefs::kPowerAcIdleAction,
base::Value(PowerPolicyController::ACTION_DO_NOTHING));
GetPrefs()->Set(ash::prefs::kPowerAcScreenOffDelayMs, base::Value(10000));
EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_OFF,
false /* idle_controlled */,
PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */,
true /* has_lid */),
GetLastSettingsChangedMessage());
// Now set the delay to zero and check that the setting goes to "display on".
GetPrefs()->Set(ash::prefs::kPowerAcScreenOffDelayMs, base::Value(0));
EXPECT_EQ(CreateSettingsChangedString(PowerHandler::IdleBehavior::DISPLAY_ON,
false /* idle_controlled */,
PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */,
true /* has_lid */),
GetLastSettingsChangedMessage());
// Other idle actions should result in an "other" setting.
GetPrefs()->Set(ash::prefs::kPowerAcIdleAction,
base::Value(PowerPolicyController::ACTION_STOP_SESSION));
EXPECT_EQ(CreateSettingsChangedString(
PowerHandler::IdleBehavior::OTHER, false /* idle_controlled */,
PowerPolicyController::ACTION_SUSPEND,
false /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
}
// Verifies that the lid-closed pref's value is sent directly to WebUI.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SendLidSettingForPrefChanges) {
GetPrefs()->Set(ash::prefs::kPowerLidClosedAction,
base::Value(PowerPolicyController::ACTION_SHUT_DOWN));
EXPECT_EQ(
CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
false /* idle_controlled */, PowerPolicyController::ACTION_SHUT_DOWN,
false /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
GetPrefs()->Set(ash::prefs::kPowerLidClosedAction,
base::Value(PowerPolicyController::ACTION_STOP_SESSION));
EXPECT_EQ(CreateSettingsChangedString(
PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP,
false /* idle_controlled */,
PowerPolicyController::ACTION_STOP_SESSION,
false /* lid_closed_controlled */, true /* has_lid */),
GetLastSettingsChangedMessage());
}
// Verifies that requests from WebUI to update the idle behavior update prefs
// appropriately.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SetIdleBehavior) {
// Request the "Keep display on" setting and check that prefs are set
// appropriately.
test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON);
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerAcIdleAction));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerBatteryIdleAction));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
EXPECT_EQ(0, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
// "Turn off display" should set the idle prefs but clear the screen
// delays.
test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF);
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerAcIdleAction));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerBatteryIdleAction));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
// Now switch to the "Keep display on" setting (to set the prefs again) and
// check that the "Turn off display and sleep" setting clears all the prefs.
test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_ON);
test_api_->SetIdleBehavior(PowerHandler::IdleBehavior::DISPLAY_OFF_SLEEP);
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcIdleAction));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenDimDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenOffDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerAcScreenLockDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryIdleAction));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenDimDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenOffDelayMs));
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerBatteryScreenLockDelayMs));
}
// Verifies that requests from WebUI to change the lid behavior update the pref.
IN_PROC_BROWSER_TEST_F(PowerHandlerTest, SetLidBehavior) {
// The "do nothing" setting should update the pref.
test_api_->SetLidClosedBehavior(PowerPolicyController::ACTION_DO_NOTHING);
EXPECT_EQ(PowerPolicyController::ACTION_DO_NOTHING,
GetIntPref(ash::prefs::kPowerLidClosedAction));
// Selecting the "suspend" setting should just clear the pref.
test_api_->SetLidClosedBehavior(PowerPolicyController::ACTION_SUSPEND);
EXPECT_EQ(-1, GetIntPref(ash::prefs::kPowerLidClosedAction));
}
} // namespace settings
} // namespace chromeos