1ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// found in the LICENSE file.
4ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
5ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ash/display/resolution_notification_controller.h"
6ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
7ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ash/display/display_controller.h"
85f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ash/display/display_info.h"
9ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ash/display/display_manager.h"
10ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ash/shell.h"
11424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/system/system_notifier.h"
12ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "base/strings/utf_string_conversions.h"
13ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "grit/ash_resources.h"
14ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "grit/ash_strings.h"
15ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/base/l10n/l10n_util.h"
16ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/base/l10n/time_format.h"
17ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/base/resource/resource_bundle.h"
18ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/gfx/display.h"
19ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/gfx/screen.h"
20ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/message_center/message_center.h"
21ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/message_center/notification.h"
22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "ui/message_center/notification_delegate.h"
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
24ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochusing message_center::Notification;
25ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
26ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace ash {
27ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochnamespace {
28ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
29ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool g_use_timer = true;
30ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
31ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochclass ResolutionChangeNotificationDelegate
32ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : public message_center::NotificationDelegate {
33ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch public:
34ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ResolutionChangeNotificationDelegate(
35ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ResolutionNotificationController* controller,
36ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      bool has_timeout);
37ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
38ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch protected:
39ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual ~ResolutionChangeNotificationDelegate();
40ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
41ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
42ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // message_center::NotificationDelegate overrides:
43ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void Display() OVERRIDE;
44ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void Error() OVERRIDE;
45ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void Close(bool by_user) OVERRIDE;
46ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void Click() OVERRIDE;
47ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual bool HasClickedListener() OVERRIDE;
48ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  virtual void ButtonClick(int button_index) OVERRIDE;
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ResolutionNotificationController* controller_;
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool has_timeout_;
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
53ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeNotificationDelegate);
54ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
55ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
56ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochResolutionChangeNotificationDelegate::ResolutionChangeNotificationDelegate(
57ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ResolutionNotificationController* controller,
58ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bool has_timeout)
59ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : controller_(controller),
60ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      has_timeout_(has_timeout) {
61ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DCHECK(controller_);
62ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
63ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
64ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochResolutionChangeNotificationDelegate::~ResolutionChangeNotificationDelegate() {
65ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
66ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
67ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionChangeNotificationDelegate::Display() {
68ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
69ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
70ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionChangeNotificationDelegate::Error() {
71ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
72ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
73ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionChangeNotificationDelegate::Close(bool by_user) {
74ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (by_user)
753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    controller_->AcceptResolutionChange(false);
76ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
77ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionChangeNotificationDelegate::Click() {
793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  controller_->AcceptResolutionChange(true);
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
82ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ResolutionChangeNotificationDelegate::HasClickedListener() {
83ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return true;
84ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
85ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
86ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionChangeNotificationDelegate::ButtonClick(int button_index) {
87ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If there's the timeout, the first button is "Accept". Otherwise the
88ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // button click should be "Revert".
89ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (has_timeout_ && button_index == 0)
903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    controller_->AcceptResolutionChange(true);
91ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  else
92ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    controller_->RevertResolutionChange();
93ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
94ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
95ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace
96ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
97ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
98ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst int ResolutionNotificationController::kTimeoutInSec = 15;
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// static
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst char ResolutionNotificationController::kNotificationId[] =
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    "chrome://settings/display/resolution";
103ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
104ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochstruct ResolutionNotificationController::ResolutionChangeInfo {
105ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ResolutionChangeInfo(int64 display_id,
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       const DisplayMode& old_resolution,
1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                       const DisplayMode& new_resolution,
108ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                       const base::Closure& accept_callback);
109ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ~ResolutionChangeInfo();
110ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
111ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The id of the display where the resolution change happens.
112ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int64 display_id;
113ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
114ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The resolution before the change.
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode old_resolution;
116ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The requested resolution. Note that this may be different from
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // |current_resolution| which is the actual resolution set.
1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode new_resolution;
120ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // The actual resolution after the change.
1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode current_resolution;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
124ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The callback when accept is chosen.
125ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::Closure accept_callback;
126ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
127ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The remaining timeout in seconds. 0 if the change does not time out.
128ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  uint8 timeout_count;
129ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
130ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // The timer to invoke OnTimerTick() every second. This cannot be
131ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // OneShotTimer since the message contains text "automatically closed in xx
132ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // seconds..." which has to be updated every second.
133ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::RepeatingTimer<ResolutionNotificationController> timer;
134ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
135ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch private:
136ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeInfo);
137ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch};
138ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
139ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochResolutionNotificationController::ResolutionChangeInfo::ResolutionChangeInfo(
140ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int64 display_id,
1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const DisplayMode& old_resolution,
1425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const DisplayMode& new_resolution,
143ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::Closure& accept_callback)
144ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    : display_id(display_id),
145ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      old_resolution(old_resolution),
146ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new_resolution(new_resolution),
147ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      accept_callback(accept_callback),
148ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      timeout_count(0) {
149ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
150ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!display_manager->HasInternalDisplay() &&
151ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      display_manager->num_connected_displays() == 1u) {
152ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    timeout_count = kTimeoutInSec;
153ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
154ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
155ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
156ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochResolutionNotificationController::ResolutionChangeInfo::
157ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ~ResolutionChangeInfo() {
158ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
159ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
160ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochResolutionNotificationController::ResolutionNotificationController() {
161ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Shell::GetInstance()->display_controller()->AddObserver(this);
162ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Shell::GetScreen()->AddObserver(this);
163ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
164ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
165ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochResolutionNotificationController::~ResolutionNotificationController() {
166ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Shell::GetInstance()->display_controller()->RemoveObserver(this);
167ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  Shell::GetScreen()->RemoveObserver(this);
168ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
169ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void ResolutionNotificationController::PrepareNotification(
171ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    int64 display_id,
1725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const DisplayMode& old_resolution,
1735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    const DisplayMode& new_resolution,
174ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const base::Closure& accept_callback) {
175ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If multiple resolution changes are invoked for the same display,
176ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // the original resolution for the first resolution change has to be used
177ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // instead of the specified |old_resolution|.
1785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode original_resolution;
179ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (change_info_ && change_info_->display_id == display_id) {
1805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    DCHECK(change_info_->new_resolution.size == old_resolution.size);
181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    original_resolution = change_info_->old_resolution;
182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
184ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  change_info_.reset(new ResolutionChangeInfo(
185ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      display_id, old_resolution, new_resolution, accept_callback));
1865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (!original_resolution.size.IsEmpty())
187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    change_info_->old_resolution = original_resolution;
188ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
190ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochbool ResolutionNotificationController::DoesNotificationTimeout() {
191ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  return change_info_ && change_info_->timeout_count > 0;
192ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
193ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)void ResolutionNotificationController::CreateOrUpdateNotification(
195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    bool enable_spoken_feedback) {
196ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  message_center::MessageCenter* message_center =
197ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      message_center::MessageCenter::Get();
198ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!change_info_) {
199ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    message_center->RemoveNotification(kNotificationId, false /* by_user */);
200ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
201ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
202ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
203ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::string16 timeout_message;
204ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  message_center::RichNotificationData data;
205ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (change_info_->timeout_count > 0) {
206ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    data.buttons.push_back(message_center::ButtonInfo(
207ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT)));
208ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    timeout_message = l10n_util::GetStringFUTF16(
209ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        IDS_ASH_DISPLAY_RESOLUTION_TIMEOUT,
210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        ui::TimeFormat::Simple(
211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            ui::TimeFormat::FORMAT_DURATION, ui::TimeFormat::LENGTH_LONG,
212ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch            base::TimeDelta::FromSeconds(change_info_->timeout_count)));
213ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  data.buttons.push_back(message_center::ButtonInfo(
215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_REVERT)));
216ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  data.should_make_spoken_feedback_for_popup_updates = enable_spoken_feedback;
218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::string16 display_name = base::UTF8ToUTF16(
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      Shell::GetInstance()->display_manager()->GetDisplayNameForId(
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          change_info_->display_id));
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::string16 message =
2235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      (change_info_->new_resolution.size ==
2245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)       change_info_->current_resolution.size) ?
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      l10n_util::GetStringFUTF16(
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          display_name,
2285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::UTF8ToUTF16(change_info_->new_resolution.size.ToString())) :
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      l10n_util::GetStringFUTF16(
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED_TO_UNSUPPORTED,
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          display_name,
2325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::UTF8ToUTF16(change_info_->new_resolution.size.ToString()),
2335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)          base::UTF8ToUTF16(change_info_->current_resolution.size.ToString()));
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
235ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
236ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  scoped_ptr<Notification> notification(new Notification(
237ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      message_center::NOTIFICATION_TYPE_SIMPLE,
238ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      kNotificationId,
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message,
240ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      timeout_message,
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      bundle.GetImageNamed(IDR_AURA_NOTIFICATION_DISPLAY),
242ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      base::string16() /* display_source */,
24358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      message_center::NotifierId(
244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          message_center::NotifierId::SYSTEM_COMPONENT,
245a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          system_notifier::kNotifierDisplayResolutionChange),
246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      data,
247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      new ResolutionChangeNotificationDelegate(
248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch          this, change_info_->timeout_count > 0)));
249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  notification->SetSystemPriority();
250ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  message_center->AddNotification(notification.Pass());
251ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionNotificationController::OnTimerTick() {
254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!change_info_)
255ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
256ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
257ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  --change_info_->timeout_count;
258ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (change_info_->timeout_count == 0)
259ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    RevertResolutionChange();
260ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  else
261424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    CreateOrUpdateNotification(false);
262ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
263ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
2643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ResolutionNotificationController::AcceptResolutionChange(
2653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    bool close_notification) {
2663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (close_notification) {
2673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    message_center::MessageCenter::Get()->RemoveNotification(
2683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        kNotificationId, false /* by_user */);
2693551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
270ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  base::Closure callback = change_info_->accept_callback;
271ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  change_info_.reset();
272ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  callback.Run();
273ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
274ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
275ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionNotificationController::RevertResolutionChange() {
276ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  message_center::MessageCenter::Get()->RemoveNotification(
277ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      kNotificationId, false /* by_user */);
278ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int64 display_id = change_info_->display_id;
2795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  DisplayMode old_resolution = change_info_->old_resolution;
280ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  change_info_.reset();
2815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  Shell::GetInstance()->display_manager()->SetDisplayMode(
282ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      display_id, old_resolution);
283ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
284ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
285ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionNotificationController::OnDisplayAdded(
286ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Display& new_display) {
287ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
288ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
289ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionNotificationController::OnDisplayRemoved(
290ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    const gfx::Display& old_display) {
291ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (change_info_ && change_info_->display_id == old_display.id())
292ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    RevertResolutionChange();
293ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
294ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ResolutionNotificationController::OnDisplayMetricsChanged(
296cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const gfx::Display&, uint32_t) {
297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
298cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
299ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionNotificationController::OnDisplayConfigurationChanged() {
300ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!change_info_)
301ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
302ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  change_info_->current_resolution = Shell::GetInstance()->display_manager()->
3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      GetActiveModeForDisplayId(change_info_->display_id);
305424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  CreateOrUpdateNotification(true);
306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (g_use_timer && change_info_->timeout_count > 0) {
307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    change_info_->timer.Start(FROM_HERE,
308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              base::TimeDelta::FromSeconds(1),
309ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              this,
310ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch                              &ResolutionNotificationController::OnTimerTick);
311ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
312ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
313ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
314ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochvoid ResolutionNotificationController::SuppressTimerForTest() {
315ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  g_use_timer = false;
316ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
317ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
318ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}  // namespace ash
319