OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h" | 5 #include "chrome/browser/ui/webui/settings/chromeos/device_power_handler.h" |
6 | 6 |
7 #include <memory> | 7 #include <memory> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/bind_helpers.h" | 11 #include "base/bind_helpers.h" |
| 12 #include "base/memory/ptr_util.h" |
12 #include "base/strings/string_number_conversions.h" | 13 #include "base/strings/string_number_conversions.h" |
13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 15 #include "base/time/time.h" |
14 #include "base/values.h" | 16 #include "base/values.h" |
| 17 #include "chrome/common/pref_names.h" |
15 #include "chrome/grit/generated_resources.h" | 18 #include "chrome/grit/generated_resources.h" |
| 19 #include "chromeos/dbus/dbus_thread_manager.h" |
| 20 #include "components/prefs/pref_change_registrar.h" |
| 21 #include "components/prefs/pref_service.h" |
16 #include "content/public/browser/web_ui.h" | 22 #include "content/public/browser/web_ui.h" |
17 #include "ui/base/l10n/l10n_util.h" | 23 #include "ui/base/l10n/l10n_util.h" |
18 #include "ui/base/l10n/time_format.h" | 24 #include "ui/base/l10n/time_format.h" |
19 #include "ui/base/webui/web_ui_util.h" | 25 #include "ui/base/webui/web_ui_util.h" |
20 | 26 |
21 namespace chromeos { | 27 namespace chromeos { |
22 namespace settings { | 28 namespace settings { |
23 namespace { | 29 namespace { |
24 | 30 |
25 base::string16 GetBatteryTimeText(base::TimeDelta time_left) { | 31 base::string16 GetBatteryTimeText(base::TimeDelta time_left) { |
26 int hour = 0; | 32 int hour = 0; |
27 int min = 0; | 33 int min = 0; |
28 ash::PowerStatus::SplitTimeIntoHoursAndMinutes(time_left, &hour, &min); | 34 ash::PowerStatus::SplitTimeIntoHoursAndMinutes(time_left, &hour, &min); |
29 | 35 |
30 base::string16 time_text; | 36 base::string16 time_text; |
31 if (hour == 0 || min == 0) { | 37 if (hour == 0 || min == 0) { |
32 // Display only one unit ("2 hours" or "10 minutes"). | 38 // Display only one unit ("2 hours" or "10 minutes"). |
33 return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, | 39 return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_DURATION, |
34 ui::TimeFormat::LENGTH_LONG, time_left); | 40 ui::TimeFormat::LENGTH_LONG, time_left); |
35 } | 41 } |
36 | 42 |
37 return ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION, | 43 return ui::TimeFormat::Detailed(ui::TimeFormat::FORMAT_DURATION, |
38 ui::TimeFormat::LENGTH_LONG, | 44 ui::TimeFormat::LENGTH_LONG, |
39 -1, // force hour and minute output | 45 -1, // force hour and minute output |
40 time_left); | 46 time_left); |
41 } | 47 } |
42 | 48 |
43 } // namespace | 49 } // namespace |
44 | 50 |
45 PowerHandler::PowerHandler() | 51 const char PowerHandler::kPowerManagementSettingsChangedName[] = |
46 : power_observer_(this) { | 52 "power-management-settings-changed"; |
| 53 const char PowerHandler::kIdleBehaviorKey[] = "idleBehavior"; |
| 54 const char PowerHandler::kIdleControlledKey[] = "idleControlled"; |
| 55 const char PowerHandler::kLidClosedBehaviorKey[] = "lidClosedBehavior"; |
| 56 const char PowerHandler::kLidClosedControlledKey[] = "lidClosedControlled"; |
| 57 const char PowerHandler::kHasLidKey[] = "hasLid"; |
| 58 |
| 59 PowerHandler::TestAPI::TestAPI(PowerHandler* handler) : handler_(handler) {} |
| 60 |
| 61 PowerHandler::TestAPI::~TestAPI() = default; |
| 62 |
| 63 void PowerHandler::TestAPI::RequestPowerManagementSettings() { |
| 64 base::ListValue args; |
| 65 handler_->HandleRequestPowerManagementSettings(&args); |
| 66 } |
| 67 |
| 68 void PowerHandler::TestAPI::SetIdleBehavior(IdleBehavior behavior) { |
| 69 base::ListValue args; |
| 70 args.AppendInteger(static_cast<int>(behavior)); |
| 71 handler_->HandleSetIdleBehavior(&args); |
| 72 } |
| 73 |
| 74 void PowerHandler::TestAPI::SetLidClosedBehavior( |
| 75 PowerPolicyController::Action behavior) { |
| 76 base::ListValue args; |
| 77 args.AppendInteger(behavior); |
| 78 handler_->HandleSetLidClosedBehavior(&args); |
| 79 } |
| 80 |
| 81 PowerHandler::PowerHandler(PrefService* prefs) |
| 82 : prefs_(prefs), |
| 83 power_status_observer_(this), |
| 84 power_manager_client_observer_(this), |
| 85 weak_ptr_factory_(this) { |
47 power_status_ = ash::PowerStatus::Get(); | 86 power_status_ = ash::PowerStatus::Get(); |
48 } | 87 } |
49 | 88 |
50 PowerHandler::~PowerHandler() {} | 89 PowerHandler::~PowerHandler() {} |
51 | 90 |
52 void PowerHandler::RegisterMessages() { | 91 void PowerHandler::RegisterMessages() { |
53 web_ui()->RegisterMessageCallback( | 92 web_ui()->RegisterMessageCallback( |
54 "updatePowerStatus", base::Bind(&PowerHandler::HandleUpdatePowerStatus, | 93 "updatePowerStatus", base::Bind(&PowerHandler::HandleUpdatePowerStatus, |
55 base::Unretained(this))); | 94 base::Unretained(this))); |
56 web_ui()->RegisterMessageCallback( | 95 web_ui()->RegisterMessageCallback( |
57 "setPowerSource", | 96 "setPowerSource", |
58 base::Bind(&PowerHandler::HandleSetPowerSource, base::Unretained(this))); | 97 base::Bind(&PowerHandler::HandleSetPowerSource, base::Unretained(this))); |
| 98 web_ui()->RegisterMessageCallback( |
| 99 "requestPowerManagementSettings", |
| 100 base::Bind(&PowerHandler::HandleRequestPowerManagementSettings, |
| 101 base::Unretained(this))); |
| 102 web_ui()->RegisterMessageCallback( |
| 103 "setLidClosedBehavior", |
| 104 base::Bind(&PowerHandler::HandleSetLidClosedBehavior, |
| 105 base::Unretained(this))); |
| 106 web_ui()->RegisterMessageCallback( |
| 107 "setIdleBehavior", |
| 108 base::Bind(&PowerHandler::HandleSetIdleBehavior, base::Unretained(this))); |
59 } | 109 } |
60 | 110 |
61 void PowerHandler::OnJavascriptAllowed() { | 111 void PowerHandler::OnJavascriptAllowed() { |
62 power_observer_.Add(power_status_); | 112 power_status_observer_.Add(power_status_); |
| 113 |
| 114 PowerManagerClient* power_manager_client = |
| 115 DBusThreadManager::Get()->GetPowerManagerClient(); |
| 116 power_manager_client_observer_.Add(power_manager_client); |
| 117 power_manager_client->GetSwitchStates(base::Bind( |
| 118 &PowerHandler::OnGotSwitchStates, weak_ptr_factory_.GetWeakPtr())); |
| 119 |
| 120 // Observe power management prefs used in the UI. |
| 121 base::Closure callback(base::Bind(&PowerHandler::SendPowerManagementSettings, |
| 122 base::Unretained(this), false /* force */)); |
| 123 pref_change_registrar_ = base::MakeUnique<PrefChangeRegistrar>(); |
| 124 pref_change_registrar_->Init(prefs_); |
| 125 pref_change_registrar_->Add(prefs::kPowerAcIdleAction, callback); |
| 126 pref_change_registrar_->Add(prefs::kPowerAcScreenDimDelayMs, callback); |
| 127 pref_change_registrar_->Add(prefs::kPowerAcScreenOffDelayMs, callback); |
| 128 pref_change_registrar_->Add(prefs::kPowerAcScreenLockDelayMs, callback); |
| 129 pref_change_registrar_->Add(prefs::kPowerBatteryIdleAction, callback); |
| 130 pref_change_registrar_->Add(prefs::kPowerBatteryScreenDimDelayMs, callback); |
| 131 pref_change_registrar_->Add(prefs::kPowerBatteryScreenOffDelayMs, callback); |
| 132 pref_change_registrar_->Add(prefs::kPowerBatteryScreenLockDelayMs, callback); |
| 133 pref_change_registrar_->Add(prefs::kPowerLidClosedAction, callback); |
63 } | 134 } |
64 | 135 |
65 void PowerHandler::OnJavascriptDisallowed() { | 136 void PowerHandler::OnJavascriptDisallowed() { |
66 power_observer_.RemoveAll(); | 137 power_status_observer_.RemoveAll(); |
| 138 power_manager_client_observer_.RemoveAll(); |
| 139 pref_change_registrar_.reset(); |
67 } | 140 } |
68 | 141 |
69 void PowerHandler::OnPowerStatusChanged() { | 142 void PowerHandler::OnPowerStatusChanged() { |
70 SendBatteryStatus(); | 143 SendBatteryStatus(); |
71 SendPowerSources(); | 144 SendPowerSources(); |
72 } | 145 } |
73 | 146 |
| 147 void PowerHandler::PowerManagerRestarted() { |
| 148 DBusThreadManager::Get()->GetPowerManagerClient()->GetSwitchStates(base::Bind( |
| 149 &PowerHandler::OnGotSwitchStates, weak_ptr_factory_.GetWeakPtr())); |
| 150 } |
| 151 |
| 152 void PowerHandler::LidEventReceived(PowerManagerClient::LidState state, |
| 153 const base::TimeTicks& timestamp) { |
| 154 lid_state_ = state; |
| 155 SendPowerManagementSettings(false /* force */); |
| 156 } |
| 157 |
74 void PowerHandler::HandleUpdatePowerStatus(const base::ListValue* args) { | 158 void PowerHandler::HandleUpdatePowerStatus(const base::ListValue* args) { |
75 AllowJavascript(); | 159 AllowJavascript(); |
76 power_status_->RequestStatusUpdate(); | 160 power_status_->RequestStatusUpdate(); |
77 } | 161 } |
78 | 162 |
79 void PowerHandler::HandleSetPowerSource(const base::ListValue* args) { | 163 void PowerHandler::HandleSetPowerSource(const base::ListValue* args) { |
80 AllowJavascript(); | 164 AllowJavascript(); |
81 | 165 |
82 std::string id; | 166 std::string id; |
83 CHECK(args->GetString(0, &id)); | 167 CHECK(args->GetString(0, &id)); |
84 power_status_->SetPowerSource(id); | 168 power_status_->SetPowerSource(id); |
85 } | 169 } |
86 | 170 |
| 171 void PowerHandler::HandleRequestPowerManagementSettings( |
| 172 const base::ListValue* args) { |
| 173 AllowJavascript(); |
| 174 SendPowerManagementSettings(true /* force */); |
| 175 } |
| 176 |
| 177 void PowerHandler::HandleSetIdleBehavior(const base::ListValue* args) { |
| 178 AllowJavascript(); |
| 179 |
| 180 int value = 0; |
| 181 CHECK(args->GetInteger(0, &value)); |
| 182 switch (static_cast<IdleBehavior>(value)) { |
| 183 case IdleBehavior::DISPLAY_OFF_SLEEP: |
| 184 // The default behavior is to turn the display off and sleep. Clear the |
| 185 // prefs so we use the default delays. |
| 186 prefs_->ClearPref(prefs::kPowerAcIdleAction); |
| 187 prefs_->ClearPref(prefs::kPowerAcScreenDimDelayMs); |
| 188 prefs_->ClearPref(prefs::kPowerAcScreenOffDelayMs); |
| 189 prefs_->ClearPref(prefs::kPowerAcScreenLockDelayMs); |
| 190 prefs_->ClearPref(prefs::kPowerBatteryIdleAction); |
| 191 prefs_->ClearPref(prefs::kPowerBatteryScreenDimDelayMs); |
| 192 prefs_->ClearPref(prefs::kPowerBatteryScreenOffDelayMs); |
| 193 prefs_->ClearPref(prefs::kPowerBatteryScreenLockDelayMs); |
| 194 break; |
| 195 case IdleBehavior::DISPLAY_OFF_STAY_AWAKE: |
| 196 // Override idle actions to keep the system awake, but use the default |
| 197 // screen delays. |
| 198 prefs_->SetInteger(prefs::kPowerAcIdleAction, |
| 199 PowerPolicyController::ACTION_DO_NOTHING); |
| 200 prefs_->ClearPref(prefs::kPowerAcScreenDimDelayMs); |
| 201 prefs_->ClearPref(prefs::kPowerAcScreenOffDelayMs); |
| 202 prefs_->ClearPref(prefs::kPowerAcScreenLockDelayMs); |
| 203 prefs_->SetInteger(prefs::kPowerBatteryIdleAction, |
| 204 PowerPolicyController::ACTION_DO_NOTHING); |
| 205 prefs_->ClearPref(prefs::kPowerBatteryScreenDimDelayMs); |
| 206 prefs_->ClearPref(prefs::kPowerBatteryScreenOffDelayMs); |
| 207 prefs_->ClearPref(prefs::kPowerBatteryScreenLockDelayMs); |
| 208 break; |
| 209 case IdleBehavior::DISPLAY_ON: |
| 210 // Override idle actions and set screen delays to 0 in order to disable |
| 211 // them (i.e. keep the screen on). |
| 212 prefs_->SetInteger(prefs::kPowerAcIdleAction, |
| 213 PowerPolicyController::ACTION_DO_NOTHING); |
| 214 prefs_->SetInteger(prefs::kPowerAcScreenDimDelayMs, 0); |
| 215 prefs_->SetInteger(prefs::kPowerAcScreenOffDelayMs, 0); |
| 216 prefs_->SetInteger(prefs::kPowerAcScreenLockDelayMs, 0); |
| 217 prefs_->SetInteger(prefs::kPowerBatteryIdleAction, |
| 218 PowerPolicyController::ACTION_DO_NOTHING); |
| 219 prefs_->SetInteger(prefs::kPowerBatteryScreenDimDelayMs, 0); |
| 220 prefs_->SetInteger(prefs::kPowerBatteryScreenOffDelayMs, 0); |
| 221 prefs_->SetInteger(prefs::kPowerBatteryScreenLockDelayMs, 0); |
| 222 break; |
| 223 default: |
| 224 NOTREACHED() << "Invalid idle behavior " << value; |
| 225 } |
| 226 } |
| 227 |
| 228 void PowerHandler::HandleSetLidClosedBehavior(const base::ListValue* args) { |
| 229 AllowJavascript(); |
| 230 |
| 231 int value = 0; |
| 232 CHECK(args->GetInteger(0, &value)); |
| 233 switch (static_cast<PowerPolicyController::Action>(value)) { |
| 234 case PowerPolicyController::ACTION_SUSPEND: |
| 235 prefs_->ClearPref(prefs::kPowerLidClosedAction); |
| 236 break; |
| 237 case PowerPolicyController::ACTION_DO_NOTHING: |
| 238 prefs_->SetInteger(prefs::kPowerLidClosedAction, |
| 239 PowerPolicyController::ACTION_DO_NOTHING); |
| 240 break; |
| 241 default: |
| 242 NOTREACHED() << "Unsupported lid-closed behavior " << value; |
| 243 } |
| 244 } |
| 245 |
87 void PowerHandler::SendBatteryStatus() { | 246 void PowerHandler::SendBatteryStatus() { |
88 bool charging = power_status_->IsBatteryCharging(); | 247 bool charging = power_status_->IsBatteryCharging(); |
89 bool calculating = power_status_->IsBatteryTimeBeingCalculated(); | 248 bool calculating = power_status_->IsBatteryTimeBeingCalculated(); |
90 int percent = power_status_->GetRoundedBatteryPercent(); | 249 int percent = power_status_->GetRoundedBatteryPercent(); |
91 base::TimeDelta time_left; | 250 base::TimeDelta time_left; |
92 bool show_time = false; | 251 bool show_time = false; |
93 | 252 |
94 if (!calculating) { | 253 if (!calculating) { |
95 time_left = charging ? power_status_->GetBatteryTimeToFull() | 254 time_left = charging ? power_status_->GetBatteryTimeToFull() |
96 : power_status_->GetBatteryTimeToEmpty(); | 255 : power_status_->GetBatteryTimeToEmpty(); |
(...skipping 29 matching lines...) Expand all Loading... |
126 dict->SetString("description", | 285 dict->SetString("description", |
127 l10n_util::GetStringUTF16(source.description_id)); | 286 l10n_util::GetStringUTF16(source.description_id)); |
128 sources_list.Append(std::move(dict)); | 287 sources_list.Append(std::move(dict)); |
129 } | 288 } |
130 | 289 |
131 FireWebUIListener("power-sources-changed", sources_list, | 290 FireWebUIListener("power-sources-changed", sources_list, |
132 base::Value(power_status_->GetCurrentPowerSourceID()), | 291 base::Value(power_status_->GetCurrentPowerSourceID()), |
133 base::Value(power_status_->IsUsbChargerConnected())); | 292 base::Value(power_status_->IsUsbChargerConnected())); |
134 } | 293 } |
135 | 294 |
| 295 void PowerHandler::SendPowerManagementSettings(bool force) { |
| 296 // Infer the idle behavior based on the idle action (determining whether we'll |
| 297 // sleep eventually or not) and the AC screen-off delay. Policy can request |
| 298 // more-nuanced combinations of AC/battery actions and delays, but we wouldn't |
| 299 // be able to display something meaningful in the UI in those cases anyway. |
| 300 const PowerPolicyController::Action idle_action = |
| 301 static_cast<PowerPolicyController::Action>( |
| 302 prefs_->GetInteger(prefs::kPowerAcIdleAction)); |
| 303 IdleBehavior idle_behavior = IdleBehavior::OTHER; |
| 304 if (idle_action == PowerPolicyController::ACTION_SUSPEND) { |
| 305 idle_behavior = IdleBehavior::DISPLAY_OFF_SLEEP; |
| 306 } else if (idle_action == PowerPolicyController::ACTION_DO_NOTHING) { |
| 307 idle_behavior = (prefs_->GetInteger(prefs::kPowerAcScreenOffDelayMs) > 0 |
| 308 ? IdleBehavior::DISPLAY_OFF_STAY_AWAKE |
| 309 : IdleBehavior::DISPLAY_ON); |
| 310 } |
| 311 |
| 312 const bool idle_controlled = |
| 313 prefs_->IsManagedPreference(prefs::kPowerAcIdleAction) || |
| 314 prefs_->IsManagedPreference(prefs::kPowerAcScreenDimDelayMs) || |
| 315 prefs_->IsManagedPreference(prefs::kPowerAcScreenOffDelayMs) || |
| 316 prefs_->IsManagedPreference(prefs::kPowerAcScreenLockDelayMs) || |
| 317 prefs_->IsManagedPreference(prefs::kPowerBatteryIdleAction) || |
| 318 prefs_->IsManagedPreference(prefs::kPowerBatteryScreenDimDelayMs) || |
| 319 prefs_->IsManagedPreference(prefs::kPowerBatteryScreenOffDelayMs) || |
| 320 prefs_->IsManagedPreference(prefs::kPowerBatteryScreenLockDelayMs); |
| 321 |
| 322 const PowerPolicyController::Action lid_closed_behavior = |
| 323 static_cast<PowerPolicyController::Action>( |
| 324 prefs_->GetInteger(prefs::kPowerLidClosedAction)); |
| 325 const bool lid_closed_controlled = |
| 326 prefs_->IsManagedPreference(prefs::kPowerLidClosedAction); |
| 327 const bool has_lid = lid_state_ != PowerManagerClient::LidState::NOT_PRESENT; |
| 328 |
| 329 // Don't notify the UI if nothing changed. |
| 330 if (!force && idle_behavior == last_idle_behavior_ && |
| 331 idle_controlled == last_idle_controlled_ && |
| 332 lid_closed_behavior == last_lid_closed_behavior_ && |
| 333 lid_closed_controlled == last_lid_closed_controlled_ && |
| 334 has_lid == last_has_lid_) |
| 335 return; |
| 336 |
| 337 base::DictionaryValue dict; |
| 338 dict.SetInteger(kIdleBehaviorKey, static_cast<int>(idle_behavior)); |
| 339 dict.SetBoolean(kIdleControlledKey, idle_controlled); |
| 340 dict.SetInteger(kLidClosedBehaviorKey, lid_closed_behavior); |
| 341 dict.SetBoolean(kLidClosedControlledKey, lid_closed_controlled); |
| 342 dict.SetBoolean(kHasLidKey, has_lid); |
| 343 CallJavascriptFunction("cr.webUIListenerCallback", |
| 344 base::Value(kPowerManagementSettingsChangedName), |
| 345 dict); |
| 346 |
| 347 last_idle_behavior_ = idle_behavior; |
| 348 last_idle_controlled_ = idle_controlled; |
| 349 last_lid_closed_behavior_ = lid_closed_behavior; |
| 350 last_lid_closed_controlled_ = lid_closed_controlled; |
| 351 last_has_lid_ = has_lid; |
| 352 } |
| 353 |
| 354 void PowerHandler::OnGotSwitchStates( |
| 355 PowerManagerClient::LidState lid_state, |
| 356 PowerManagerClient::TabletMode tablet_mode) { |
| 357 lid_state_ = lid_state; |
| 358 SendPowerManagementSettings(false /* force */); |
| 359 } |
| 360 |
136 } // namespace settings | 361 } // namespace settings |
137 } // namespace chromeos | 362 } // namespace chromeos |
OLD | NEW |