text: // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  // Use of this source code is governed by a BSD-style license that can be
  // found in the LICENSE file.
  
  #include "ash/system/status_area_widget.h"
  
  #include "ash/root_window_controller.h"
  #include "ash/shell.h"
  #include "ash/shell_delegate.h"
  #include "ash/shell_window_ids.h"
  #include "ash/system/bluetooth/bluetooth_observer.h"
  #include "ash/system/network/network_observer.h"
  #include "ash/system/status_area_widget_delegate.h"
  #include "ash/system/tray/system_tray.h"
  #include "ash/system/tray/system_tray_delegate.h"
  #include "ash/system/web_notification/web_notification_tray.h"
  #include "ash/volume_control_delegate.h"
  #include "ash/wm/shelf_layout_manager.h"
  #include "ash/wm/window_properties.h"
  #include "base/i18n/time_formatting.h"
  #include "base/utf_string_conversions.h"
  #include "ui/aura/window.h"
  #include "ui/gfx/screen.h"
  
  namespace ash {
  
  namespace {
  
  class DummyVolumeControlDelegate : public VolumeControlDelegate {
   public:
    DummyVolumeControlDelegate() {}
    virtual ~DummyVolumeControlDelegate() {}
  
    virtual bool HandleVolumeMute(const ui::Accelerator& accelerator) OVERRIDE {
      return true;
    }
    virtual bool HandleVolumeDown(const ui::Accelerator& accelerator) OVERRIDE {
      return true;
    }
    virtual bool HandleVolumeUp(const ui::Accelerator& accelerator) OVERRIDE {
      return true;
    }
    virtual void SetVolumePercent(double percent) OVERRIDE {
    }
    virtual bool IsAudioMuted() const OVERRIDE {
      return true;
    }
    virtual void SetAudioMuted(bool muted) OVERRIDE {
    }
    virtual float GetVolumeLevel() const OVERRIDE {
      return 0.0;
    }
    virtual void SetVolumeLevel(float level) OVERRIDE {
    }
  
   private:
    DISALLOW_COPY_AND_ASSIGN(DummyVolumeControlDelegate);
  };
  
  class DummySystemTrayDelegate : public SystemTrayDelegate {
   public:
    DummySystemTrayDelegate()
        : wifi_enabled_(true),
          cellular_enabled_(true),
          bluetooth_enabled_(true),
          caps_lock_enabled_(false),
          volume_control_delegate_(
              ALLOW_THIS_IN_INITIALIZER_LIST(new DummyVolumeControlDelegate)) {
    }
  
    virtual ~DummySystemTrayDelegate() {}
  
   private:
    virtual bool GetTrayVisibilityOnStartup() OVERRIDE { return true; }
  
    // Overridden from SystemTrayDelegate:
    virtual const string16 GetUserDisplayName() const OVERRIDE {
      return UTF8ToUTF16("Über tray Über tray Über tray Über tray");
    }
  
    virtual const std::string GetUserEmail() const OVERRIDE {
      return "über@tray";
    }
  
    virtual const gfx::ImageSkia& GetUserImage() const OVERRIDE {
      return null_image_;
    }
  
    virtual user::LoginStatus GetUserLoginStatus() const OVERRIDE {
      return user::LOGGED_IN_USER;
    }
  
    virtual bool SystemShouldUpgrade() const OVERRIDE {
      return true;
    }
  
    virtual base::HourClockType GetHourClockType() const OVERRIDE {
      return base::k24HourClock;
    }
  
    virtual PowerSupplyStatus GetPowerSupplyStatus() const OVERRIDE {
      return PowerSupplyStatus();
    }
  
    virtual void RequestStatusUpdate() const OVERRIDE {
    }
  
    virtual void ShowSettings() OVERRIDE {
    }
  
    virtual void ShowDateSettings() OVERRIDE {
    }
  
    virtual void ShowNetworkSettings() OVERRIDE {
    }
  
    virtual void ShowBluetoothSettings() OVERRIDE {
    }
  
    virtual void ShowDisplaySettings() OVERRIDE {
    }
  
    virtual void ShowDriveSettings() OVERRIDE {
    }
  
    virtual void ShowIMESettings() OVERRIDE {
    }
  
    virtual void ShowHelp() OVERRIDE {
    }
  
    virtual void ShutDown() OVERRIDE {
      MessageLoop::current()->Quit();
    }
  
    virtual void SignOut() OVERRIDE {
      MessageLoop::current()->Quit();
    }
  
    virtual void RequestLockScreen() OVERRIDE {}
  
    virtual void RequestRestart() OVERRIDE {}
  
    virtual void GetAvailableBluetoothDevices(
        BluetoothDeviceList* list) OVERRIDE {
    }
  
    virtual void ToggleBluetoothConnection(const std::string& address) OVERRIDE {
    }
  
    virtual void GetCurrentIME(IMEInfo* info) OVERRIDE {
    }
  
    virtual void GetAvailableIMEList(IMEInfoList* list) OVERRIDE {
    }
  
    virtual void GetCurrentIMEProperties(IMEPropertyInfoList* list) OVERRIDE {
    }
  
    virtual void SwitchIME(const std::string& ime_id) OVERRIDE {
    }
  
    virtual void ActivateIMEProperty(const std::string& key) OVERRIDE {
    }
  
    virtual void CancelDriveOperation(const FilePath&) OVERRIDE {
    }
  
    virtual void GetDriveOperationStatusList(
        ash::DriveOperationStatusList*) OVERRIDE {
    }
  
    virtual void GetMostRelevantNetworkIcon(NetworkIconInfo* info,
                                            bool large) OVERRIDE {
    }
  
    virtual void GetAvailableNetworks(
        std::vector<NetworkIconInfo>* list) OVERRIDE {
    }
  
    virtual void ConnectToNetwork(const std::string& network_id) OVERRIDE {
    }
  
    virtual void GetNetworkAddresses(std::string* ip_address,
                                     std::string* ethernet_mac_address,
                                     std::string* wifi_mac_address) OVERRIDE {
      *ip_address = "127.0.0.1";
      *ethernet_mac_address = "00:11:22:33:44:55";
      *wifi_mac_address = "66:77:88:99:00:11";
    }
  
    virtual void RequestNetworkScan() OVERRIDE {
    }
  
    virtual void AddBluetoothDevice() OVERRIDE {
    }
  
    virtual void ToggleAirplaneMode() OVERRIDE {
    }
  
    virtual void ToggleWifi() OVERRIDE {
      wifi_enabled_ = !wifi_enabled_;
      ash::NetworkObserver* observer =
          ash::Shell::GetInstance()->system_tray()->network_observer();
      if (observer) {
        ash::NetworkIconInfo info;
        observer->OnNetworkRefresh(info);
      }
    }
  
    virtual void ToggleMobile() OVERRIDE {
      cellular_enabled_ = !cellular_enabled_;
      ash::NetworkObserver* observer =
          ash::Shell::GetInstance()->system_tray()->network_observer();
      if (observer) {
        ash::NetworkIconInfo info;
        observer->OnNetworkRefresh(info);
      }
    }
  
    virtual void ToggleBluetooth() OVERRIDE {
      bluetooth_enabled_ = !bluetooth_enabled_;
      ash::BluetoothObserver* observer =
          ash::Shell::GetInstance()->system_tray()->bluetooth_observer();
      if (observer)
        observer->OnBluetoothRefresh();
    }
  
    virtual void ShowOtherWifi() OVERRIDE {
    }
  
    virtual void ShowOtherCellular() OVERRIDE {
    }
  
    virtual bool IsNetworkConnected() OVERRIDE {
      return true;
    }
  
    virtual bool GetWifiAvailable() OVERRIDE {
      return true;
    }
  
    virtual bool GetMobileAvailable() OVERRIDE {
      return true;
    }
  
    virtual bool GetBluetoothAvailable() OVERRIDE {
      return true;
    }
  
    virtual bool GetWifiEnabled() OVERRIDE {
      return wifi_enabled_;
    }
  
    virtual bool GetMobileEnabled() OVERRIDE {
      return cellular_enabled_;
    }
  
    virtual bool GetBluetoothEnabled() OVERRIDE {
      return bluetooth_enabled_;
    }
  
    virtual bool GetMobileScanSupported() OVERRIDE {
      return true;
    }
  
    virtual bool GetCellularCarrierInfo(std::string* carrier_id,
                                        std::string* topup_url,
                                        std::string* setup_url) OVERRIDE {
      return false;
    }
  
    virtual void ShowCellularURL(const std::string& url) OVERRIDE {
    }
  
    virtual void ChangeProxySettings() OVERRIDE {
    }
  
    virtual VolumeControlDelegate* GetVolumeControlDelegate() const OVERRIDE {
      return volume_control_delegate_.get();
    }
  
    virtual void SetVolumeControlDelegate(
        scoped_ptr<VolumeControlDelegate> delegate) OVERRIDE {
      volume_control_delegate_.swap(delegate);
    }
  
  
    bool wifi_enabled_;
    bool cellular_enabled_;
    bool bluetooth_enabled_;
    bool caps_lock_enabled_;
    gfx::ImageSkia null_image_;
    scoped_ptr<VolumeControlDelegate> volume_control_delegate_;
  
    DISALLOW_COPY_AND_ASSIGN(DummySystemTrayDelegate);
  };
  
  }  // namespace
  
  namespace internal {
  
  StatusAreaWidget::StatusAreaWidget()
      : status_area_widget_delegate_(new internal::StatusAreaWidgetDelegate),
        system_tray_(NULL),
        web_notification_tray_(NULL),
        login_status_(user::LOGGED_IN_NONE) {
    views::Widget::InitParams params(
        views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    params.delegate = status_area_widget_delegate_;
    params.parent =
        Shell::GetPrimaryRootWindowController()->GetContainer(
            ash::internal::kShellWindowId_StatusContainer);
    params.transparent = true;
    Init(params);
    set_focus_on_creation(false);
    SetContentsView(status_area_widget_delegate_);
    GetNativeView()->SetName("StatusAreaWidget");
    GetNativeView()->SetProperty(internal::kStayInSameRootWindowKey, true);
  }
  
  StatusAreaWidget::~StatusAreaWidget() {
  }
  
  void StatusAreaWidget::CreateTrayViews(ShellDelegate* shell_delegate) {
    AddSystemTray(shell_delegate);
    AddWebNotificationTray();
    // Initialize() must be called after all trays have been created.
    if (system_tray_)
      system_tray_->Initialize();
    if (web_notification_tray_)
      web_notification_tray_->Initialize();
    UpdateAfterLoginStatusChange(system_tray_delegate_->GetUserLoginStatus());
  }
  
  void StatusAreaWidget::Shutdown() {
    // Destroy the trays early, causing them to be removed from the view
    // hierarchy. Do not used scoped pointers since we don't want to destroy them
    // in the destructor if Shutdown() is not called (e.g. in tests).
    system_tray_delegate_.reset();
    delete web_notification_tray_;
    web_notification_tray_ = NULL;
    delete system_tray_;
    system_tray_ = NULL;
  }
  
  bool StatusAreaWidget::ShouldShowLauncher() const {
    if ((system_tray_ && system_tray_->HasSystemBubble()) ||
        (web_notification_tray_ &&
         web_notification_tray_->IsMessageCenterBubbleVisible()))
      return true;
  
    if (!Shell::GetInstance()->shelf()->IsVisible())
      return false;
  
    // If the launcher is currently visible, don't hide the launcher if the mouse
    // is in any of the notification bubbles.
    return (system_tray_ && system_tray_->IsMouseInNotificationBubble()) ||
          (web_notification_tray_ &&
           web_notification_tray_->IsMouseInNotificationBubble());
  }
  
  bool StatusAreaWidget::IsMessageBubbleShown() const {
    return ((system_tray_ && system_tray_->IsAnyBubbleVisible()) ||
            (web_notification_tray_ &&
             web_notification_tray_->IsMessageCenterBubbleVisible()));
  }
  
  void StatusAreaWidget::AddSystemTray(ShellDelegate* shell_delegate) {
    system_tray_ = new SystemTray(this);
    status_area_widget_delegate_->AddTray(system_tray_);
  
    if (shell_delegate) {
      system_tray_delegate_.reset(
          shell_delegate->CreateSystemTrayDelegate(system_tray_));
    }
    if (!system_tray_delegate_.get())
      system_tray_delegate_.reset(new DummySystemTrayDelegate());
  }
  
  void StatusAreaWidget::AddWebNotificationTray() {
    web_notification_tray_ = new WebNotificationTray(this);
    status_area_widget_delegate_->AddTray(web_notification_tray_);
  }
  
  void StatusAreaWidget::SetShelfAlignment(ShelfAlignment alignment) {
    status_area_widget_delegate_->set_alignment(alignment);
    if (system_tray_)
      system_tray_->SetShelfAlignment(alignment);
    if (web_notification_tray_)
      web_notification_tray_->SetShelfAlignment(alignment);
    status_area_widget_delegate_->UpdateLayout();
  }
  
  void StatusAreaWidget::SetPaintsBackground(
      bool value,
      internal::BackgroundAnimator::ChangeType change_type) {
    if (system_tray_)
      system_tray_->SetPaintsBackground(value, change_type);
    if (web_notification_tray_)
      web_notification_tray_->SetPaintsBackground(value, change_type);
  }
  
  void StatusAreaWidget::SetHideWebNotifications(bool hide) {
    if (web_notification_tray_)
      web_notification_tray_->SetHidePopupBubble(hide);
  }
  
  void StatusAreaWidget::SetHideSystemNotifications(bool hide) {
    if (system_tray_)
      system_tray_->SetHideNotifications(hide);
  }
  
  bool StatusAreaWidget::ShouldShowWebNotifications() {
    return !(system_tray_ && system_tray_->IsAnyBubbleVisible());
  }
  
  void StatusAreaWidget::UpdateAfterLoginStatusChange(
      user::LoginStatus login_status) {
    if (login_status_ == login_status)
      return;
    login_status_ = login_status;
    if (system_tray_)
      system_tray_->UpdateAfterLoginStatusChange(login_status);
    if (web_notification_tray_)
      web_notification_tray_->UpdateAfterLoginStatusChange(login_status);
  }
  
  }  // namespace internal
  }  // namespace ash
  