Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / ui / webui / options / chromeos / display_options_handler.cc
blob22b3eb650b1bfec7e23f7c863c0462836bc7cf75
1 // Copyright (c) 2012 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 "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
7 #include <string>
9 #include "ash/ash_switches.h"
10 #include "ash/display/display_configurator_animation.h"
11 #include "ash/display/display_controller.h"
12 #include "ash/display/display_manager.h"
13 #include "ash/display/resolution_notification_controller.h"
14 #include "ash/rotator/screen_rotation_animator.h"
15 #include "ash/shell.h"
16 #include "base/bind.h"
17 #include "base/logging.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/values.h"
21 #include "chrome/browser/chromeos/display/display_preferences.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "content/public/browser/user_metrics.h"
24 #include "content/public/browser/web_ui.h"
25 #include "grit/ash_strings.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/gfx/display.h"
28 #include "ui/gfx/geometry/rect.h"
29 #include "ui/gfx/geometry/size_conversions.h"
30 #include "ui/gfx/screen.h"
32 using ash::DisplayManager;
34 namespace chromeos {
35 namespace options {
36 namespace {
38 DisplayManager* GetDisplayManager() {
39 return ash::Shell::GetInstance()->display_manager();
42 int64 GetDisplayId(const base::ListValue* args) {
43 // Assumes the display ID is specified as the first argument.
44 std::string id_value;
45 if (!args->GetString(0, &id_value)) {
46 LOG(ERROR) << "Can't find ID";
47 return gfx::Display::kInvalidDisplayID;
50 int64 display_id = gfx::Display::kInvalidDisplayID;
51 if (!base::StringToInt64(id_value, &display_id)) {
52 LOG(ERROR) << "Invalid display id: " << id_value;
53 return gfx::Display::kInvalidDisplayID;
56 return display_id;
59 base::string16 GetColorProfileName(ui::ColorCalibrationProfile profile) {
60 switch (profile) {
61 case ui::COLOR_PROFILE_STANDARD:
62 return l10n_util::GetStringUTF16(
63 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_STANDARD);
64 case ui::COLOR_PROFILE_DYNAMIC:
65 return l10n_util::GetStringUTF16(
66 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_DYNAMIC);
67 case ui::COLOR_PROFILE_MOVIE:
68 return l10n_util::GetStringUTF16(
69 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_MOVIE);
70 case ui::COLOR_PROFILE_READING:
71 return l10n_util::GetStringUTF16(
72 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_READING);
73 case ui::NUM_COLOR_PROFILES:
74 break;
77 NOTREACHED();
78 return base::string16();
81 int GetIntOrDouble(const base::DictionaryValue* dict,
82 const std::string& field) {
83 double double_result = 0;
84 if (dict->GetDouble(field, &double_result))
85 return static_cast<int>(double_result);
87 int result = 0;
88 dict->GetInteger(field, &result);
89 return result;
92 bool GetFloat(const base::DictionaryValue* dict,
93 const std::string& field,
94 float* result) {
95 double double_result = 0;
96 if (dict->GetDouble(field, &double_result)) {
97 *result = static_cast<float>(double_result);
98 return true;
100 return false;
103 bool ConvertValueToDisplayMode(const base::DictionaryValue* dict,
104 ash::DisplayMode* mode) {
105 mode->size.set_width(GetIntOrDouble(dict, "originalWidth"));
106 mode->size.set_height(GetIntOrDouble(dict, "originalHeight"));
107 if (mode->size.IsEmpty()) {
108 LOG(ERROR) << "missing width or height.";
109 return false;
111 if (!GetFloat(dict, "refreshRate", &mode->refresh_rate)) {
112 LOG(ERROR) << "missing refreshRate.";
113 return false;
115 if (!GetFloat(dict, "scale", &mode->ui_scale)) {
116 LOG(ERROR) << "missing ui-scale.";
117 return false;
119 if (!GetFloat(dict, "deviceScaleFactor", &mode->device_scale_factor)) {
120 LOG(ERROR) << "missing deviceScaleFactor.";
121 return false;
123 return true;
126 base::DictionaryValue* ConvertDisplayModeToValue(int64 display_id,
127 const ash::DisplayMode& mode) {
128 bool is_internal = gfx::Display::InternalDisplayId() == display_id;
129 base::DictionaryValue* result = new base::DictionaryValue();
130 gfx::Size size_dip = mode.GetSizeInDIP(is_internal);
131 result->SetInteger("width", size_dip.width());
132 result->SetInteger("height", size_dip.height());
133 result->SetInteger("originalWidth", mode.size.width());
134 result->SetInteger("originalHeight", mode.size.height());
135 result->SetDouble("deviceScaleFactor", mode.device_scale_factor);
136 result->SetDouble("scale", mode.ui_scale);
137 result->SetDouble("refreshRate", mode.refresh_rate);
138 result->SetBoolean(
139 "isBest", is_internal ? (mode.ui_scale == 1.0f) : mode.native);
140 result->SetBoolean("isNative", mode.native);
141 result->SetBoolean(
142 "selected", mode.IsEquivalent(
143 GetDisplayManager()->GetActiveModeForDisplayId(display_id)));
144 return result;
147 } // namespace
149 DisplayOptionsHandler::DisplayOptionsHandler() {
150 // ash::Shell doesn't exist in Athena.
151 // See: http://crbug.com/416961
152 ash::Shell::GetInstance()->display_controller()->AddObserver(this);
155 DisplayOptionsHandler::~DisplayOptionsHandler() {
156 // ash::Shell doesn't exist in Athena.
157 ash::Shell::GetInstance()->display_controller()->RemoveObserver(this);
160 void DisplayOptionsHandler::GetLocalizedValues(
161 base::DictionaryValue* localized_strings) {
162 DCHECK(localized_strings);
163 RegisterTitle(localized_strings, "displayOptionsPage",
164 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_TAB_TITLE);
166 localized_strings->SetString(
167 "selectedDisplayTitleOptions", l10n_util::GetStringUTF16(
168 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OPTIONS));
169 localized_strings->SetString(
170 "selectedDisplayTitleResolution", l10n_util::GetStringUTF16(
171 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION));
172 localized_strings->SetString(
173 "selectedDisplayTitleOrientation", l10n_util::GetStringUTF16(
174 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION));
175 localized_strings->SetString(
176 "selectedDisplayTitleOverscan", l10n_util::GetStringUTF16(
177 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OVERSCAN));
179 localized_strings->SetString("startMirroring", l10n_util::GetStringUTF16(
180 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING));
181 localized_strings->SetString("stopMirroring", l10n_util::GetStringUTF16(
182 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STOP_MIRRORING));
183 localized_strings->SetString("mirroringDisplay", l10n_util::GetStringUTF16(
184 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_MIRRORING_DISPLAY_NAME));
185 localized_strings->SetString("setPrimary", l10n_util::GetStringUTF16(
186 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_SET_PRIMARY));
187 localized_strings->SetString("annotateBest", l10n_util::GetStringUTF16(
188 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION_ANNOTATION_BEST));
189 localized_strings->SetString("annotateNative", l10n_util::GetStringUTF16(
190 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION_ANNOTATION_NATIVE));
191 localized_strings->SetString("orientation0", l10n_util::GetStringUTF16(
192 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION));
193 localized_strings->SetString("orientation90", l10n_util::GetStringUTF16(
194 IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90));
195 localized_strings->SetString("orientation180", l10n_util::GetStringUTF16(
196 IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180));
197 localized_strings->SetString("orientation270", l10n_util::GetStringUTF16(
198 IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270));
199 localized_strings->SetString(
200 "startCalibratingOverscan", l10n_util::GetStringUTF16(
201 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
202 localized_strings->SetString(
203 "selectedDisplayColorProfile", l10n_util::GetStringUTF16(
204 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE));
205 localized_strings->SetString(
206 "enableUnifiedDesktop",
207 l10n_util::GetStringUTF16(
208 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ENABLE_UNIFIED_DESKTOP));
211 void DisplayOptionsHandler::InitializePage() {
212 DCHECK(web_ui());
213 UpdateDisplaySettingsEnabled();
216 void DisplayOptionsHandler::RegisterMessages() {
217 web_ui()->RegisterMessageCallback(
218 "getDisplayInfo",
219 base::Bind(&DisplayOptionsHandler::HandleDisplayInfo,
220 base::Unretained(this)));
221 web_ui()->RegisterMessageCallback(
222 "setMirroring",
223 base::Bind(&DisplayOptionsHandler::HandleMirroring,
224 base::Unretained(this)));
225 web_ui()->RegisterMessageCallback(
226 "setPrimary",
227 base::Bind(&DisplayOptionsHandler::HandleSetPrimary,
228 base::Unretained(this)));
229 web_ui()->RegisterMessageCallback(
230 "setDisplayLayout",
231 base::Bind(&DisplayOptionsHandler::HandleDisplayLayout,
232 base::Unretained(this)));
233 web_ui()->RegisterMessageCallback(
234 "setDisplayMode",
235 base::Bind(&DisplayOptionsHandler::HandleSetDisplayMode,
236 base::Unretained(this)));
237 web_ui()->RegisterMessageCallback(
238 "setOrientation",
239 base::Bind(&DisplayOptionsHandler::HandleSetOrientation,
240 base::Unretained(this)));
241 web_ui()->RegisterMessageCallback(
242 "setColorProfile",
243 base::Bind(&DisplayOptionsHandler::HandleSetColorProfile,
244 base::Unretained(this)));
245 web_ui()->RegisterMessageCallback(
246 "setUnifiedDesktopEnabled",
247 base::Bind(&DisplayOptionsHandler::HandleSetUnifiedDesktopEnabled,
248 base::Unretained(this)));
251 void DisplayOptionsHandler::OnDisplayConfigurationChanging() {
254 void DisplayOptionsHandler::OnDisplayConfigurationChanged() {
255 UpdateDisplaySettingsEnabled();
256 SendAllDisplayInfo();
259 void DisplayOptionsHandler::SendAllDisplayInfo() {
260 DisplayManager* display_manager = GetDisplayManager();
262 std::vector<gfx::Display> displays;
263 for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
264 displays.push_back(display_manager->GetDisplayAt(i));
266 SendDisplayInfo(displays);
269 void DisplayOptionsHandler::SendDisplayInfo(
270 const std::vector<gfx::Display>& displays) {
271 DisplayManager* display_manager = GetDisplayManager();
272 base::FundamentalValue mode(
273 display_manager->IsInMirrorMode() ? DisplayManager::MIRRORING :
274 (display_manager->IsInUnifiedMode() ? DisplayManager::UNIFIED :
275 DisplayManager::EXTENDED));
277 int64 primary_id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
278 base::ListValue js_displays;
279 for (const gfx::Display& display : displays) {
280 const ash::DisplayInfo& display_info =
281 display_manager->GetDisplayInfo(display.id());
282 const gfx::Rect& bounds = display.bounds();
283 base::DictionaryValue* js_display = new base::DictionaryValue();
284 js_display->SetString("id", base::Int64ToString(display.id()));
285 js_display->SetInteger("x", bounds.x());
286 js_display->SetInteger("y", bounds.y());
287 js_display->SetInteger("width", bounds.width());
288 js_display->SetInteger("height", bounds.height());
289 js_display->SetString("name",
290 display_manager->GetDisplayNameForId(display.id()));
291 js_display->SetBoolean("isPrimary", display.id() == primary_id);
292 js_display->SetBoolean("isInternal", display.IsInternal());
293 js_display->SetInteger("orientation",
294 static_cast<int>(display_info.GetActiveRotation()));
296 base::ListValue* js_resolutions = new base::ListValue();
297 for (const ash::DisplayMode& display_mode : display_info.display_modes()) {
298 js_resolutions->Append(
299 ConvertDisplayModeToValue(display.id(), display_mode));
301 js_display->Set("resolutions", js_resolutions);
303 js_display->SetInteger("colorProfile", display_info.color_profile());
304 base::ListValue* available_color_profiles = new base::ListValue();
305 for (const auto& color_profile : display_info.available_color_profiles()) {
306 const base::string16 profile_name = GetColorProfileName(color_profile);
307 if (profile_name.empty())
308 continue;
309 base::DictionaryValue* color_profile_dict = new base::DictionaryValue();
310 color_profile_dict->SetInteger("profileId", color_profile);
311 color_profile_dict->SetString("name", profile_name);
312 available_color_profiles->Append(color_profile_dict);
314 js_display->Set("availableColorProfiles", available_color_profiles);
315 js_displays.Append(js_display);
318 scoped_ptr<base::Value> layout_value = base::Value::CreateNullValue();
319 scoped_ptr<base::Value> offset_value = base::Value::CreateNullValue();
320 if (display_manager->GetNumDisplays() > 1) {
321 const ash::DisplayLayout layout =
322 display_manager->GetCurrentDisplayLayout();
323 layout_value.reset(new base::FundamentalValue(layout.position));
324 offset_value.reset(new base::FundamentalValue(layout.offset));
327 web_ui()->CallJavascriptFunction(
328 "options.DisplayOptions.setDisplayInfo",
329 mode, js_displays, *layout_value.get(), *offset_value.get());
332 void DisplayOptionsHandler::UpdateDisplaySettingsEnabled() {
333 bool enabled = GetDisplayManager()->num_connected_displays() <= 2;
334 bool show_unified_desktop = ash::switches::UnifiedDesktopEnabled();
336 web_ui()->CallJavascriptFunction(
337 "options.BrowserOptions.enableDisplaySettings",
338 base::FundamentalValue(enabled),
339 base::FundamentalValue(show_unified_desktop));
342 void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) {
343 ash::Shell::GetInstance()->display_manager()->SetMirrorMode(is_mirroring);
344 // Not necessary to start fade-in animation. DisplayConfigurator will do that.
347 void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
348 int position, int offset) {
349 SetCurrentDisplayLayout(
350 ash::DisplayLayout::FromInts(position, offset));
351 ash::Shell::GetInstance()->display_configurator_animation()->
352 StartFadeInAnimation();
355 void DisplayOptionsHandler::HandleDisplayInfo(
356 const base::ListValue* unused_args) {
357 SendAllDisplayInfo();
360 void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) {
361 DCHECK(!args->empty());
362 content::RecordAction(
363 base::UserMetricsAction("Options_DisplayToggleMirroring"));
364 bool is_mirroring = false;
365 args->GetBoolean(0, &is_mirroring);
366 ash::Shell::GetInstance()->display_configurator_animation()->
367 StartFadeOutAnimation(base::Bind(
368 &DisplayOptionsHandler::OnFadeOutForMirroringFinished,
369 base::Unretained(this),
370 is_mirroring));
373 void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) {
374 DCHECK(!args->empty());
375 int64 display_id = GetDisplayId(args);
376 if (display_id == gfx::Display::kInvalidDisplayID)
377 return;
379 content::RecordAction(base::UserMetricsAction("Options_DisplaySetPrimary"));
380 ash::Shell::GetInstance()->display_controller()->
381 SetPrimaryDisplayId(display_id);
384 void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) {
385 double layout = -1;
386 double offset = -1;
387 if (!args->GetDouble(0, &layout) || !args->GetDouble(1, &offset)) {
388 LOG(ERROR) << "Invalid parameter";
389 SendAllDisplayInfo();
390 return;
392 DCHECK_LE(ash::DisplayLayout::TOP, layout);
393 DCHECK_GE(ash::DisplayLayout::LEFT, layout);
394 content::RecordAction(base::UserMetricsAction("Options_DisplayRearrange"));
395 ash::Shell::GetInstance()->display_configurator_animation()->
396 StartFadeOutAnimation(base::Bind(
397 &DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished,
398 base::Unretained(this),
399 static_cast<int>(layout),
400 static_cast<int>(offset)));
403 void DisplayOptionsHandler::HandleSetDisplayMode(const base::ListValue* args) {
404 DCHECK(!args->empty());
406 int64 display_id = GetDisplayId(args);
407 if (display_id == gfx::Display::kInvalidDisplayID)
408 return;
410 const base::DictionaryValue* mode_data = nullptr;
411 if (!args->GetDictionary(1, &mode_data)) {
412 LOG(ERROR) << "Failed to get mode data";
413 return;
416 ash::DisplayMode mode;
417 if (!ConvertValueToDisplayMode(mode_data, &mode))
418 return;
420 content::RecordAction(
421 base::UserMetricsAction("Options_DisplaySetResolution"));
422 ash::DisplayManager* display_manager = GetDisplayManager();
423 ash::DisplayMode current_mode =
424 display_manager->GetActiveModeForDisplayId(display_id);
425 if (display_manager->SetDisplayMode(display_id, mode)) {
426 ash::Shell::GetInstance()->resolution_notification_controller()->
427 PrepareNotification(
428 display_id, current_mode, mode, base::Bind(&StoreDisplayPrefs));
432 void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) {
433 DCHECK(!args->empty());
435 int64 display_id = GetDisplayId(args);
436 if (display_id == gfx::Display::kInvalidDisplayID)
437 return;
439 std::string rotation_value;
440 gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_0;
441 if (!args->GetString(1, &rotation_value)) {
442 LOG(ERROR) << "Can't find new orientation";
443 return;
445 if (rotation_value == "90")
446 new_rotation = gfx::Display::ROTATE_90;
447 else if (rotation_value == "180")
448 new_rotation = gfx::Display::ROTATE_180;
449 else if (rotation_value == "270")
450 new_rotation = gfx::Display::ROTATE_270;
451 else if (rotation_value != "0")
452 LOG(ERROR) << "Invalid rotation: " << rotation_value << " Falls back to 0";
454 content::RecordAction(
455 base::UserMetricsAction("Options_DisplaySetOrientation"));
456 ash::ScreenRotationAnimator(display_id)
457 .Rotate(new_rotation, gfx::Display::ROTATION_SOURCE_USER);
460 void DisplayOptionsHandler::HandleSetColorProfile(const base::ListValue* args) {
461 DCHECK(!args->empty());
462 int64 display_id = GetDisplayId(args);
463 if (display_id == gfx::Display::kInvalidDisplayID)
464 return;
466 std::string profile_value;
467 if (!args->GetString(1, &profile_value)) {
468 LOG(ERROR) << "Invalid profile_value";
469 return;
472 int profile_id;
473 if (!base::StringToInt(profile_value, &profile_id)) {
474 LOG(ERROR) << "Invalid profile: " << profile_value;
475 return;
478 if (profile_id < ui::COLOR_PROFILE_STANDARD ||
479 profile_id > ui::COLOR_PROFILE_READING) {
480 LOG(ERROR) << "Invalid profile_id: " << profile_id;
481 return;
484 GetDisplayManager()->SetColorCalibrationProfile(
485 display_id, static_cast<ui::ColorCalibrationProfile>(profile_id));
486 SendAllDisplayInfo();
489 void DisplayOptionsHandler::HandleSetUnifiedDesktopEnabled(
490 const base::ListValue* args) {
491 DCHECK(ash::switches::UnifiedDesktopEnabled());
492 bool enable = false;
493 if (args->GetBoolean(0, &enable)) {
494 GetDisplayManager()->SetDefaultMultiDisplayMode(
495 enable ? DisplayManager::UNIFIED : DisplayManager::EXTENDED);
496 GetDisplayManager()->ReconfigureDisplays();
500 } // namespace options
501 } // namespace chromeos