resolution_notification_controller.cc revision 3551c9c881056c480085172ff9840cab31610854
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/resolution_notification_controller.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "ash/display/display_controller.h"
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/display/display_manager.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shell.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/utf_string_conversions.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ash_resources.h"
129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "grit/ash_strings.h"
13f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
14f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ui/base/l10n/time_format.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/display.h"
17a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/gfx/screen.h"
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/message_center/message_center.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/message_center/notification_delegate.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using message_center::Notification;
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace ash {
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace internal {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool g_use_timer = true;
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ResolutionChangeNotificationDelegate
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public message_center::NotificationDelegate {
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResolutionChangeNotificationDelegate(
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ResolutionNotificationController* controller,
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool has_timeout);
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) protected:
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~ResolutionChangeNotificationDelegate();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // message_center::NotificationDelegate overrides:
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Display() OVERRIDE;
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Error() OVERRIDE;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Close(bool by_user) OVERRIDE;
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void Click() OVERRIDE;
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool HasClickedListener() OVERRIDE;
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void ButtonClick(int button_index) OVERRIDE;
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResolutionNotificationController* controller_;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool has_timeout_;
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeNotificationDelegate);
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResolutionChangeNotificationDelegate::ResolutionChangeNotificationDelegate(
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResolutionNotificationController* controller,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool has_timeout)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : controller_(controller),
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      has_timeout_(has_timeout) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(controller_);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResolutionChangeNotificationDelegate::~ResolutionChangeNotificationDelegate() {
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResolutionChangeNotificationDelegate::Display() {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResolutionChangeNotificationDelegate::Error() {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResolutionChangeNotificationDelegate::Close(bool by_user) {
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (by_user)
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller_->AcceptResolutionChange(false);
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResolutionChangeNotificationDelegate::Click() {
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  controller_->AcceptResolutionChange(true);
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ResolutionChangeNotificationDelegate::HasClickedListener() {
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResolutionChangeNotificationDelegate::ButtonClick(int button_index) {
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there's the timeout, the first button is "Accept". Otherwise the
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // button click should be "Revert".
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (has_timeout_ && button_index == 0)
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller_->AcceptResolutionChange(true);
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    controller_->RevertResolutionChange();
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int ResolutionNotificationController::kTimeoutInSec = 15;
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char ResolutionNotificationController::kNotificationId[] =
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "chrome://settings/display/resolution";
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct ResolutionNotificationController::ResolutionChangeInfo {
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResolutionChangeInfo(int64 display_id,
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const gfx::Size& old_resolution,
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const gfx::Size& new_resolution,
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       const base::Closure& accept_callback);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ~ResolutionChangeInfo();
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The id of the display where the resolution change happens.
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int64 display_id;
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // The resolution before the change.
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size old_resolution;
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The new resolution after the change.
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size new_resolution;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The callback when accept is chosen.
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::Closure accept_callback;
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The remaining timeout in seconds. 0 if the change does not time out.
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  uint8 timeout_count;
1247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The timer to invoke OnTimerTick() every second. This cannot be
1267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // OneShotTimer since the message contains text "automatically closed in xx
1273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // seconds..." which has to be updated every second.
128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::RepeatingTimer<ResolutionNotificationController> timer;
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
13158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ResolutionChangeInfo);
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
13458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)ResolutionNotificationController::ResolutionChangeInfo::ResolutionChangeInfo(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 display_id,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& old_resolution,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& new_resolution,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::Closure& accept_callback)
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : display_id(display_id),
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      old_resolution(old_resolution),
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new_resolution(new_resolution),
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      accept_callback(accept_callback),
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      timeout_count(0) {
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DisplayManager* display_manager = Shell::GetInstance()->display_manager();
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!display_manager->HasInternalDisplay() &&
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      display_manager->num_connected_displays() == 1u) {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timeout_count = kTimeoutInSec;
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResolutionNotificationController::ResolutionChangeInfo::
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ~ResolutionChangeInfo() {
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResolutionNotificationController::ResolutionNotificationController() {
156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Shell::GetInstance()->display_controller()->AddObserver(this);
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Shell::GetScreen()->AddObserver(this);
158f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
159f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
160f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ResolutionNotificationController::~ResolutionNotificationController() {
161f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Shell::GetInstance()->display_controller()->RemoveObserver(this);
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Shell::GetScreen()->RemoveObserver(this);
163f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
164f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
165f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ResolutionNotificationController::SetDisplayResolutionAndNotify(
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int64 display_id,
167f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const gfx::Size& old_resolution,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const gfx::Size& new_resolution,
169f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const base::Closure& accept_callback) {
170f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // If multiple resolution changes are invoked for the same display,
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the original resolution for the first resolution change has to be used
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // instead of the specified |old_resolution|.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Size original_resolution;
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (change_info_ && change_info_->display_id == display_id) {
175f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(change_info_->new_resolution == old_resolution);
176f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    original_resolution = change_info_->old_resolution;
177f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
178f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
179f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  change_info_.reset(new ResolutionChangeInfo(
180f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      display_id, old_resolution, new_resolution, accept_callback));
181f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!original_resolution.IsEmpty())
182f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    change_info_->old_resolution = original_resolution;
183f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
184f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // SetDisplayResolution() causes OnConfigurationChanged() and the notification
1857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // will be shown at that point.
186f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  Shell::GetInstance()->display_manager()->SetDisplayResolution(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      display_id, new_resolution);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ResolutionNotificationController::DoesNotificationTimeout() {
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return change_info_ && change_info_->timeout_count > 0;
192f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
193f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
194f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ResolutionNotificationController::CreateOrUpdateNotification() {
195f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  message_center::MessageCenter* message_center =
196f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      message_center::MessageCenter::Get();
197f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (!change_info_) {
198f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    message_center->RemoveNotification(kNotificationId, false /* by_user */);
199f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return;
200f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
201f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
202f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  base::string16 timeout_message;
2037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  message_center::RichNotificationData data;
204f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (change_info_->timeout_count > 0) {
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    data.buttons.push_back(message_center::ButtonInfo(
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_ACCEPT)));
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    timeout_message = l10n_util::GetStringFUTF16(
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        IDS_ASH_DISPLAY_RESOLUTION_TIMEOUT,
209f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        ui::TimeFormat::TimeDurationLong(
210f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            base::TimeDelta::FromSeconds(change_info_->timeout_count)));
211f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
212f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  data.buttons.push_back(message_center::ButtonInfo(
213f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        l10n_util::GetStringUTF16(IDS_ASH_DISPLAY_RESOLUTION_CHANGE_REVERT)));
214f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
215f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
216f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  scoped_ptr<Notification> notification(new Notification(
217f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      message_center::NOTIFICATION_TYPE_SIMPLE,
218f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kNotificationId,
219f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      l10n_util::GetStringFUTF16(
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          IDS_ASH_STATUS_TRAY_DISPLAY_RESOLUTION_CHANGED,
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          UTF8ToUTF16(Shell::GetInstance()->display_manager()->
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              GetDisplayNameForId(change_info_->display_id)),
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          UTF8ToUTF16(change_info_->new_resolution.ToString())),
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      timeout_message,
225f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      bundle.GetImageNamed(IDR_AURA_UBER_TRAY_DISPLAY),
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::string16() /* display_source */,
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      std::string() /* extension_id */,
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      data,
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new ResolutionChangeNotificationDelegate(
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          this, change_info_->timeout_count > 0)));
231  notification->SetSystemPriority();
232  message_center->AddNotification(notification.Pass());
233}
234
235void ResolutionNotificationController::OnTimerTick() {
236  if (!change_info_)
237    return;
238
239  --change_info_->timeout_count;
240  if (change_info_->timeout_count == 0)
241    RevertResolutionChange();
242  else
243    CreateOrUpdateNotification();
244}
245
246void ResolutionNotificationController::AcceptResolutionChange(
247    bool close_notification) {
248  if (close_notification) {
249    message_center::MessageCenter::Get()->RemoveNotification(
250        kNotificationId, false /* by_user */);
251  }
252  base::Closure callback = change_info_->accept_callback;
253  change_info_.reset();
254  callback.Run();
255}
256
257void ResolutionNotificationController::RevertResolutionChange() {
258  message_center::MessageCenter::Get()->RemoveNotification(
259      kNotificationId, false /* by_user */);
260  int64 display_id = change_info_->display_id;
261  gfx::Size old_resolution = change_info_->old_resolution;
262  change_info_.reset();
263  Shell::GetInstance()->display_manager()->SetDisplayResolution(
264      display_id, old_resolution);
265}
266
267void ResolutionNotificationController::OnDisplayBoundsChanged(
268    const gfx::Display& display) {
269}
270
271void ResolutionNotificationController::OnDisplayAdded(
272    const gfx::Display& new_display) {
273}
274
275void ResolutionNotificationController::OnDisplayRemoved(
276    const gfx::Display& old_display) {
277  if (change_info_ && change_info_->display_id == old_display.id())
278    RevertResolutionChange();
279}
280
281void ResolutionNotificationController::OnDisplayConfigurationChanged() {
282  if (!change_info_)
283    return;
284
285  CreateOrUpdateNotification();
286  if (g_use_timer && change_info_->timeout_count > 0) {
287    change_info_->timer.Start(FROM_HERE,
288                              base::TimeDelta::FromSeconds(1),
289                              this,
290                              &ResolutionNotificationController::OnTimerTick);
291  }
292}
293
294void ResolutionNotificationController::SuppressTimerForTest() {
295  g_use_timer = false;
296}
297
298}  // namespace internal
299}  // namespace ash
300