Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / options / chromeos / display_options_handler.cc
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.
4
5 #include "chrome/browser/ui/webui/options/chromeos/display_options_handler.h"
6
7 #include <string>
8
9 #include "ash/display/display_configurator_animation.h"
10 #include "ash/display/display_controller.h"
11 #include "ash/display/display_manager.h"
12 #include "ash/display/resolution_notification_controller.h"
13 #include "ash/shell.h"
14 #include "base/bind.h"
15 #include "base/logging.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/values.h"
19 #include "chrome/browser/chromeos/display/display_preferences.h"
20 #include "content/public/browser/user_metrics.h"
21 #include "content/public/browser/web_ui.h"
22 #include "grit/ash_strings.h"
23 #include "grit/generated_resources.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/gfx/display.h"
26 #include "ui/gfx/rect.h"
27 #include "ui/gfx/screen.h"
28 #include "ui/gfx/size_conversions.h"
29
30 using ash::DisplayManager;
31
32 namespace chromeos {
33 namespace options {
34 namespace {
35
36 DisplayManager* GetDisplayManager() {
37   return ash::Shell::GetInstance()->display_manager();
38 }
39
40 int64 GetDisplayId(const base::ListValue* args) {
41   // Assumes the display ID is specified as the first argument.
42   std::string id_value;
43   if (!args->GetString(0, &id_value)) {
44     LOG(ERROR) << "Can't find ID";
45     return gfx::Display::kInvalidDisplayID;
46   }
47
48   int64 display_id = gfx::Display::kInvalidDisplayID;
49   if (!base::StringToInt64(id_value, &display_id)) {
50     LOG(ERROR) << "Invalid display id: " << id_value;
51     return gfx::Display::kInvalidDisplayID;
52   }
53
54   return display_id;
55 }
56
57 base::string16 GetColorProfileName(ui::ColorCalibrationProfile profile) {
58   switch (profile) {
59     case ui::COLOR_PROFILE_STANDARD:
60       return l10n_util::GetStringUTF16(
61           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_STANDARD);
62     case ui::COLOR_PROFILE_DYNAMIC:
63       return l10n_util::GetStringUTF16(
64           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_DYNAMIC);
65     case ui::COLOR_PROFILE_MOVIE:
66       return l10n_util::GetStringUTF16(
67           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_MOVIE);
68     case ui::COLOR_PROFILE_READING:
69       return l10n_util::GetStringUTF16(
70           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE_READING);
71     case ui::NUM_COLOR_PROFILES:
72       break;
73   }
74
75   NOTREACHED();
76   return base::string16();
77 }
78
79 int GetIntOrDouble(const base::DictionaryValue* dict,
80                    const std::string& field) {
81   double double_result = 0;
82   if (dict->GetDouble(field, &double_result))
83     return static_cast<int>(double_result);
84
85   int result = 0;
86   dict->GetInteger(field, &result);
87   return result;
88 }
89
90 bool GetFloat(const base::DictionaryValue* dict,
91               const std::string& field,
92               float* result) {
93   double double_result = 0;
94   if (dict->GetDouble(field, &double_result)) {
95     *result = static_cast<float>(double_result);
96     return true;
97   }
98   return false;
99 }
100
101 bool ConvertValueToDisplayMode(const base::DictionaryValue* dict,
102                                ash::DisplayMode* mode) {
103   mode->size.set_width(GetIntOrDouble(dict, "originalWidth"));
104   mode->size.set_height(GetIntOrDouble(dict, "originalHeight"));
105   if (mode->size.IsEmpty()) {
106     LOG(ERROR) << "missing width or height.";
107     return false;
108   }
109   if (!GetFloat(dict, "refreshRate", &mode->refresh_rate)) {
110     LOG(ERROR) << "missing refreshRate.";
111     return false;
112   }
113   if (!GetFloat(dict, "scale", &mode->ui_scale)) {
114     LOG(ERROR) << "missing ui-scale.";
115     return false;
116   }
117   if (!GetFloat(dict, "deviceScaleFactor", &mode->device_scale_factor)) {
118     LOG(ERROR) << "missing deviceScaleFactor.";
119     return false;
120   }
121   return true;
122 }
123
124 base::DictionaryValue* ConvertDisplayModeToValue(int64 display_id,
125                                                  const ash::DisplayMode& mode) {
126   base::DictionaryValue* result = new base::DictionaryValue();
127   gfx::Size size_dip = mode.GetSizeInDIP();
128   result->SetInteger("width", size_dip.width());
129   result->SetInteger("height", size_dip.height());
130   result->SetInteger("originalWidth", mode.size.width());
131   result->SetInteger("originalHeight", mode.size.height());
132   result->SetDouble("deviceScaleFactor", mode.device_scale_factor);
133   result->SetDouble("scale", mode.ui_scale);
134   result->SetDouble("refreshRate", mode.refresh_rate);
135   result->SetBoolean("isBest", mode.native);
136   result->SetBoolean(
137       "selected", mode.IsEquivalent(
138           GetDisplayManager()->GetActiveModeForDisplayId(display_id)));
139   return result;
140 }
141
142 }  // namespace
143
144 DisplayOptionsHandler::DisplayOptionsHandler() {
145   ash::Shell::GetInstance()->display_controller()->AddObserver(this);
146 }
147
148 DisplayOptionsHandler::~DisplayOptionsHandler() {
149   ash::Shell::GetInstance()->display_controller()->RemoveObserver(this);
150 }
151
152 void DisplayOptionsHandler::GetLocalizedValues(
153     base::DictionaryValue* localized_strings) {
154   DCHECK(localized_strings);
155   RegisterTitle(localized_strings, "displayOptionsPage",
156                 IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_TAB_TITLE);
157
158   localized_strings->SetString(
159       "selectedDisplayTitleOptions", l10n_util::GetStringUTF16(
160           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OPTIONS));
161   localized_strings->SetString(
162       "selectedDisplayTitleResolution", l10n_util::GetStringUTF16(
163           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION));
164   localized_strings->SetString(
165       "selectedDisplayTitleOrientation", l10n_util::GetStringUTF16(
166           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_ORIENTATION));
167   localized_strings->SetString(
168       "selectedDisplayTitleOverscan", l10n_util::GetStringUTF16(
169           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_OVERSCAN));
170
171   localized_strings->SetString("startMirroring", l10n_util::GetStringUTF16(
172       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_MIRRORING));
173   localized_strings->SetString("stopMirroring", l10n_util::GetStringUTF16(
174       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STOP_MIRRORING));
175   localized_strings->SetString("mirroringDisplay", l10n_util::GetStringUTF16(
176       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_MIRRORING_DISPLAY_NAME));
177   localized_strings->SetString("setPrimary", l10n_util::GetStringUTF16(
178       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_SET_PRIMARY));
179   localized_strings->SetString("annotateBest", l10n_util::GetStringUTF16(
180       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_RESOLUTION_ANNOTATION_BEST));
181   localized_strings->SetString("orientation0", l10n_util::GetStringUTF16(
182       IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_STANDARD_ORIENTATION));
183   localized_strings->SetString("orientation90", l10n_util::GetStringUTF16(
184       IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_90));
185   localized_strings->SetString("orientation180", l10n_util::GetStringUTF16(
186       IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_180));
187   localized_strings->SetString("orientation270", l10n_util::GetStringUTF16(
188       IDS_ASH_STATUS_TRAY_DISPLAY_ORIENTATION_270));
189   localized_strings->SetString(
190       "startCalibratingOverscan", l10n_util::GetStringUTF16(
191           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_START_CALIBRATING_OVERSCAN));
192   localized_strings->SetString(
193       "selectedDisplayColorProfile", l10n_util::GetStringUTF16(
194           IDS_OPTIONS_SETTINGS_DISPLAY_OPTIONS_COLOR_PROFILE));
195 }
196
197 void DisplayOptionsHandler::InitializePage() {
198   DCHECK(web_ui());
199 }
200
201 void DisplayOptionsHandler::RegisterMessages() {
202   web_ui()->RegisterMessageCallback(
203       "getDisplayInfo",
204       base::Bind(&DisplayOptionsHandler::HandleDisplayInfo,
205                  base::Unretained(this)));
206   web_ui()->RegisterMessageCallback(
207       "setMirroring",
208       base::Bind(&DisplayOptionsHandler::HandleMirroring,
209                  base::Unretained(this)));
210   web_ui()->RegisterMessageCallback(
211       "setPrimary",
212       base::Bind(&DisplayOptionsHandler::HandleSetPrimary,
213                  base::Unretained(this)));
214   web_ui()->RegisterMessageCallback(
215       "setDisplayLayout",
216       base::Bind(&DisplayOptionsHandler::HandleDisplayLayout,
217                  base::Unretained(this)));
218   web_ui()->RegisterMessageCallback(
219       "setDisplayMode",
220       base::Bind(&DisplayOptionsHandler::HandleSetDisplayMode,
221                  base::Unretained(this)));
222   web_ui()->RegisterMessageCallback(
223       "setOrientation",
224       base::Bind(&DisplayOptionsHandler::HandleSetOrientation,
225                  base::Unretained(this)));
226   web_ui()->RegisterMessageCallback(
227       "setColorProfile",
228       base::Bind(&DisplayOptionsHandler::HandleSetColorProfile,
229                  base::Unretained(this)));
230 }
231
232 void DisplayOptionsHandler::OnDisplayConfigurationChanging() {
233 }
234
235 void DisplayOptionsHandler::OnDisplayConfigurationChanged() {
236   SendAllDisplayInfo();
237 }
238
239 void DisplayOptionsHandler::SendAllDisplayInfo() {
240   DisplayManager* display_manager = GetDisplayManager();
241
242   std::vector<gfx::Display> displays;
243   for (size_t i = 0; i < display_manager->GetNumDisplays(); ++i) {
244     displays.push_back(display_manager->GetDisplayAt(i));
245   }
246   SendDisplayInfo(displays);
247 }
248
249 void DisplayOptionsHandler::SendDisplayInfo(
250     const std::vector<gfx::Display>& displays) {
251   DisplayManager* display_manager = GetDisplayManager();
252   base::FundamentalValue mirroring(display_manager->IsMirrored());
253
254   int64 primary_id = ash::Shell::GetScreen()->GetPrimaryDisplay().id();
255   base::ListValue js_displays;
256   for (size_t i = 0; i < displays.size(); ++i) {
257     const gfx::Display& display = displays[i];
258     const ash::DisplayInfo& display_info =
259         display_manager->GetDisplayInfo(display.id());
260     const gfx::Rect& bounds = display.bounds();
261     base::DictionaryValue* js_display = new base::DictionaryValue();
262     js_display->SetString("id", base::Int64ToString(display.id()));
263     js_display->SetInteger("x", bounds.x());
264     js_display->SetInteger("y", bounds.y());
265     js_display->SetInteger("width", bounds.width());
266     js_display->SetInteger("height", bounds.height());
267     js_display->SetString("name",
268                           display_manager->GetDisplayNameForId(display.id()));
269     js_display->SetBoolean("isPrimary", display.id() == primary_id);
270     js_display->SetBoolean("isInternal", display.IsInternal());
271     js_display->SetInteger("orientation",
272                            static_cast<int>(display_info.rotation()));
273
274     base::ListValue* js_resolutions = new base::ListValue();
275     const std::vector<ash::DisplayMode>& display_modes =
276         display_info.display_modes();
277     for (size_t i = 0; i < display_modes.size(); ++i) {
278       js_resolutions->Append(
279           ConvertDisplayModeToValue(display.id(), display_modes[i]));
280     }
281     js_display->Set("resolutions", js_resolutions);
282
283     js_display->SetInteger("colorProfile", display_info.color_profile());
284     base::ListValue* available_color_profiles = new base::ListValue();
285     for (size_t i = 0;
286          i < display_info.available_color_profiles().size(); ++i) {
287       base::DictionaryValue* color_profile_dict = new base::DictionaryValue();
288       ui::ColorCalibrationProfile color_profile =
289           display_info.available_color_profiles()[i];
290       color_profile_dict->SetInteger("profileId", color_profile);
291       color_profile_dict->SetString("name", GetColorProfileName(color_profile));
292       available_color_profiles->Append(color_profile_dict);
293     }
294     js_display->Set("availableColorProfiles", available_color_profiles);
295     js_displays.Append(js_display);
296   }
297
298   scoped_ptr<base::Value> layout_value(base::Value::CreateNullValue());
299   scoped_ptr<base::Value> offset_value(base::Value::CreateNullValue());
300   if (display_manager->GetNumDisplays() > 1) {
301     const ash::DisplayLayout layout =
302         display_manager->GetCurrentDisplayLayout();
303     layout_value.reset(new base::FundamentalValue(layout.position));
304     offset_value.reset(new base::FundamentalValue(layout.offset));
305   }
306
307   web_ui()->CallJavascriptFunction(
308       "options.DisplayOptions.setDisplayInfo",
309       mirroring, js_displays, *layout_value.get(), *offset_value.get());
310 }
311
312 void DisplayOptionsHandler::OnFadeOutForMirroringFinished(bool is_mirroring) {
313   ash::Shell::GetInstance()->display_manager()->SetMirrorMode(is_mirroring);
314   // Not necessary to start fade-in animation. DisplayConfigurator will do that.
315 }
316
317 void DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished(
318     int position, int offset) {
319   SetCurrentDisplayLayout(
320       ash::DisplayLayout::FromInts(position, offset));
321   ash::Shell::GetInstance()->display_configurator_animation()->
322       StartFadeInAnimation();
323 }
324
325 void DisplayOptionsHandler::HandleDisplayInfo(
326     const base::ListValue* unused_args) {
327   SendAllDisplayInfo();
328 }
329
330 void DisplayOptionsHandler::HandleMirroring(const base::ListValue* args) {
331   DCHECK(!args->empty());
332   content::RecordAction(
333       base::UserMetricsAction("Options_DisplayToggleMirroring"));
334   bool is_mirroring = false;
335   args->GetBoolean(0, &is_mirroring);
336   ash::Shell::GetInstance()->display_configurator_animation()->
337       StartFadeOutAnimation(base::Bind(
338           &DisplayOptionsHandler::OnFadeOutForMirroringFinished,
339           base::Unretained(this),
340           is_mirroring));
341 }
342
343 void DisplayOptionsHandler::HandleSetPrimary(const base::ListValue* args) {
344   DCHECK(!args->empty());
345   int64 display_id = GetDisplayId(args);
346   if (display_id == gfx::Display::kInvalidDisplayID)
347     return;
348
349   content::RecordAction(base::UserMetricsAction("Options_DisplaySetPrimary"));
350   ash::Shell::GetInstance()->display_controller()->
351       SetPrimaryDisplayId(display_id);
352 }
353
354 void DisplayOptionsHandler::HandleDisplayLayout(const base::ListValue* args) {
355   double layout = -1;
356   double offset = -1;
357   if (!args->GetDouble(0, &layout) || !args->GetDouble(1, &offset)) {
358     LOG(ERROR) << "Invalid parameter";
359     SendAllDisplayInfo();
360     return;
361   }
362   DCHECK_LE(ash::DisplayLayout::TOP, layout);
363   DCHECK_GE(ash::DisplayLayout::LEFT, layout);
364   content::RecordAction(base::UserMetricsAction("Options_DisplayRearrange"));
365   ash::Shell::GetInstance()->display_configurator_animation()->
366       StartFadeOutAnimation(base::Bind(
367           &DisplayOptionsHandler::OnFadeOutForDisplayLayoutFinished,
368           base::Unretained(this),
369           static_cast<int>(layout),
370           static_cast<int>(offset)));
371 }
372
373 void DisplayOptionsHandler::HandleSetDisplayMode(const base::ListValue* args) {
374   DCHECK(!args->empty());
375
376   int64 display_id = GetDisplayId(args);
377   if (display_id == gfx::Display::kInvalidDisplayID)
378     return;
379
380   const base::DictionaryValue* mode_data = NULL;
381   if (!args->GetDictionary(1, &mode_data)) {
382     LOG(ERROR) << "Failed to get mode data";
383     return;
384   }
385
386   ash::DisplayMode mode;
387   if (!ConvertValueToDisplayMode(mode_data, &mode))
388     return;
389
390   content::RecordAction(
391       base::UserMetricsAction("Options_DisplaySetResolution"));
392   ash::DisplayManager* display_manager = GetDisplayManager();
393   ash::DisplayMode current_mode =
394       display_manager->GetActiveModeForDisplayId(display_id);
395   if (display_manager->SetDisplayMode(display_id, mode)) {
396     ash::Shell::GetInstance()->resolution_notification_controller()->
397         PrepareNotification(
398             display_id, current_mode, mode, base::Bind(&StoreDisplayPrefs));
399   }
400 }
401
402 void DisplayOptionsHandler::HandleSetOrientation(const base::ListValue* args) {
403   DCHECK(!args->empty());
404
405   int64 display_id = GetDisplayId(args);
406   if (display_id == gfx::Display::kInvalidDisplayID)
407     return;
408
409   std::string rotation_value;
410   gfx::Display::Rotation new_rotation = gfx::Display::ROTATE_0;
411   if (!args->GetString(1, &rotation_value)) {
412     LOG(ERROR) << "Can't find new orientation";
413     return;
414   }
415   if (rotation_value == "90")
416     new_rotation = gfx::Display::ROTATE_90;
417   else if (rotation_value == "180")
418     new_rotation = gfx::Display::ROTATE_180;
419   else if (rotation_value == "270")
420     new_rotation = gfx::Display::ROTATE_270;
421   else if (rotation_value != "0")
422     LOG(ERROR) << "Invalid rotation: " << rotation_value << " Falls back to 0";
423
424   content::RecordAction(
425       base::UserMetricsAction("Options_DisplaySetOrientation"));
426   GetDisplayManager()->SetDisplayRotation(display_id, new_rotation);
427 }
428
429 void DisplayOptionsHandler::HandleSetColorProfile(const base::ListValue* args) {
430   DCHECK(!args->empty());
431   int64 display_id = GetDisplayId(args);
432   if (display_id == gfx::Display::kInvalidDisplayID)
433     return;
434
435   std::string profile_value;
436   if (!args->GetString(1, &profile_value)) {
437     LOG(ERROR) << "Invalid profile_value";
438     return;
439   }
440
441   int profile_id;
442   if (!base::StringToInt(profile_value, &profile_id)) {
443     LOG(ERROR) << "Invalid profile: " << profile_value;
444     return;
445   }
446
447   if (profile_id < ui::COLOR_PROFILE_STANDARD ||
448       profile_id > ui::COLOR_PROFILE_READING) {
449     LOG(ERROR) << "Invalid profile_id: " << profile_id;
450     return;
451   }
452
453   GetDisplayManager()->SetColorCalibrationProfile(
454       display_id, static_cast<ui::ColorCalibrationProfile>(profile_id));
455   SendAllDisplayInfo();
456 }
457
458 }  // namespace options
459 }  // namespace chromeos