summaryrefslogtreecommitdiff
path: root/chromium/ash/system/chromeos/network/tray_network.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ash/system/chromeos/network/tray_network.cc')
-rw-r--r--chromium/ash/system/chromeos/network/tray_network.cc367
1 files changed, 367 insertions, 0 deletions
diff --git a/chromium/ash/system/chromeos/network/tray_network.cc b/chromium/ash/system/chromeos/network/tray_network.cc
new file mode 100644
index 00000000000..4d2c82a2181
--- /dev/null
+++ b/chromium/ash/system/chromeos/network/tray_network.cc
@@ -0,0 +1,367 @@
+// 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/chromeos/network/tray_network.h"
+
+#include "ash/ash_switches.h"
+#include "ash/metrics/user_metrics_recorder.h"
+#include "ash/shell.h"
+#include "ash/system/chromeos/network/network_icon_animation.h"
+#include "ash/system/chromeos/network/network_state_list_detailed_view.h"
+#include "ash/system/chromeos/network/tray_network_state_observer.h"
+#include "ash/system/tray/system_tray.h"
+#include "ash/system/tray/system_tray_delegate.h"
+#include "ash/system/tray/system_tray_notifier.h"
+#include "ash/system/tray/tray_constants.h"
+#include "ash/system/tray/tray_item_more.h"
+#include "ash/system/tray/tray_item_view.h"
+#include "ash/system/tray/tray_utils.h"
+#include "base/command_line.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/shill_property_util.h"
+#include "grit/ash_resources.h"
+#include "grit/ash_strings.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/base/accessibility/accessible_view_state.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/link.h"
+#include "ui/views/controls/link_listener.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/widget/widget.h"
+
+using chromeos::NetworkHandler;
+using chromeos::NetworkState;
+using chromeos::NetworkStateHandler;
+using chromeos::NetworkTypePattern;
+
+namespace ash {
+namespace internal {
+
+namespace tray {
+
+class NetworkTrayView : public TrayItemView,
+ public network_icon::AnimationObserver {
+ public:
+ explicit NetworkTrayView(TrayNetwork* network_tray)
+ : TrayItemView(network_tray),
+ network_tray_(network_tray) {
+ SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
+
+ image_view_ = new views::ImageView;
+ AddChildView(image_view_);
+
+ UpdateNetworkStateHandlerIcon();
+ }
+
+ virtual ~NetworkTrayView() {
+ network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
+ }
+
+ virtual const char* GetClassName() const OVERRIDE {
+ return "NetworkTrayView";
+ }
+
+ void UpdateNetworkStateHandlerIcon() {
+ NetworkStateHandler* handler =
+ NetworkHandler::Get()->network_state_handler();
+ gfx::ImageSkia image;
+ base::string16 name;
+ bool animating = false;
+ network_icon::GetDefaultNetworkImageAndLabel(
+ network_icon::ICON_TYPE_TRAY, &image, &name, &animating);
+ bool show_in_tray = !image.isNull();
+ UpdateIcon(show_in_tray, image);
+ if (animating)
+ network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
+ else
+ network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
+ // Update accessibility.
+ const NetworkState* connected_network =
+ handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
+ if (connected_network)
+ UpdateConnectionStatus(UTF8ToUTF16(connected_network->name()), true);
+ else
+ UpdateConnectionStatus(base::string16(), false);
+ }
+
+ void UpdateAlignment(ShelfAlignment alignment) {
+ SetLayoutManager(new views::BoxLayout(
+ alignment == SHELF_ALIGNMENT_BOTTOM ?
+ views::BoxLayout::kHorizontal : views::BoxLayout::kVertical,
+ 0, 0, 0));
+ Layout();
+ }
+
+ // views::View override.
+ virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE {
+ state->name = connection_status_string_;
+ state->role = ui::AccessibilityTypes::ROLE_PUSHBUTTON;
+ }
+
+ // network_icon::AnimationObserver
+ virtual void NetworkIconChanged() OVERRIDE {
+ UpdateNetworkStateHandlerIcon();
+ }
+
+ private:
+ // Updates connection status and notifies accessibility event when necessary.
+ void UpdateConnectionStatus(const base::string16& network_name,
+ bool connected) {
+ base::string16 new_connection_status_string;
+ if (connected) {
+ new_connection_status_string = l10n_util::GetStringFUTF16(
+ IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, network_name);
+ }
+ if (new_connection_status_string != connection_status_string_) {
+ connection_status_string_ = new_connection_status_string;
+ if(!connection_status_string_.empty())
+ NotifyAccessibilityEvent(ui::AccessibilityTypes::EVENT_ALERT, true);
+ }
+ }
+
+ void UpdateIcon(bool tray_icon_visible, const gfx::ImageSkia& image) {
+ image_view_->SetImage(image);
+ SetVisible(tray_icon_visible);
+ SchedulePaint();
+ }
+
+ TrayNetwork* network_tray_;
+ views::ImageView* image_view_;
+ base::string16 connection_status_string_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkTrayView);
+};
+
+class NetworkDefaultView : public TrayItemMore,
+ public network_icon::AnimationObserver {
+ public:
+ NetworkDefaultView(TrayNetwork* network_tray, bool show_more)
+ : TrayItemMore(network_tray, show_more),
+ network_tray_(network_tray) {
+ Update();
+ }
+
+ virtual ~NetworkDefaultView() {
+ network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
+ }
+
+ void Update() {
+ gfx::ImageSkia image;
+ base::string16 label;
+ bool animating = false;
+ network_icon::GetDefaultNetworkImageAndLabel(
+ network_icon::ICON_TYPE_DEFAULT_VIEW, &image, &label, &animating);
+ if (animating)
+ network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
+ else
+ network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
+ SetImage(&image);
+ SetLabel(label);
+ SetAccessibleName(label);
+ }
+
+ // network_icon::AnimationObserver
+ virtual void NetworkIconChanged() OVERRIDE {
+ Update();
+ }
+
+ private:
+ TrayNetwork* network_tray_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView);
+};
+
+class NetworkWifiDetailedView : public NetworkDetailedView {
+ public:
+ explicit NetworkWifiDetailedView(SystemTrayItem* owner)
+ : NetworkDetailedView(owner) {
+ SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
+ kTrayPopupPaddingHorizontal,
+ 10,
+ kTrayPopupPaddingBetweenItems));
+ image_view_ = new views::ImageView;
+ AddChildView(image_view_);
+
+ label_view_ = new views::Label();
+ label_view_->SetMultiLine(true);
+ label_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ AddChildView(label_view_);
+
+ Update();
+ }
+
+ virtual ~NetworkWifiDetailedView() {
+ }
+
+ // Overridden from NetworkDetailedView:
+
+ virtual void Init() OVERRIDE {
+ }
+
+ virtual NetworkDetailedView::DetailedViewType GetViewType() const OVERRIDE {
+ return NetworkDetailedView::WIFI_VIEW;
+ }
+
+ virtual void ManagerChanged() OVERRIDE {
+ Update();
+ }
+
+ virtual void NetworkListChanged() OVERRIDE {
+ Update();
+ }
+
+ virtual void NetworkServiceChanged(
+ const chromeos::NetworkState* network) OVERRIDE {
+ }
+
+ private:
+ virtual void Layout() OVERRIDE {
+ // Center both views vertically.
+ views::View::Layout();
+ image_view_->SetY(
+ (height() - image_view_->GetPreferredSize().height()) / 2);
+ label_view_->SetY(
+ (height() - label_view_->GetPreferredSize().height()) / 2);
+ }
+
+ void Update() {
+ bool wifi_enabled =
+ NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled(
+ NetworkTypePattern::WiFi());
+ const int image_id = wifi_enabled ?
+ IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED;
+ ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
+ image_view_->SetImage(bundle.GetImageNamed(image_id).ToImageSkia());
+
+ const int string_id = wifi_enabled ?
+ IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED :
+ IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
+ label_view_->SetText(bundle.GetLocalizedString(string_id));
+ label_view_->SizeToFit(kTrayPopupMinWidth -
+ kTrayPopupPaddingHorizontal * 2 - kTrayPopupPaddingBetweenItems -
+ kTrayPopupDetailsIconWidth);
+ }
+
+ views::ImageView* image_view_;
+ views::Label* label_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView);
+};
+
+} // namespace tray
+
+TrayNetwork::TrayNetwork(SystemTray* system_tray)
+ : SystemTrayItem(system_tray),
+ tray_(NULL),
+ default_(NULL),
+ detailed_(NULL),
+ request_wifi_view_(false) {
+ network_state_observer_.reset(new TrayNetworkStateObserver(this));
+ Shell::GetInstance()->system_tray_notifier()->AddNetworkObserver(this);
+}
+
+TrayNetwork::~TrayNetwork() {
+ Shell::GetInstance()->system_tray_notifier()->RemoveNetworkObserver(this);
+}
+
+views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) {
+ CHECK(tray_ == NULL);
+ if (!chromeos::NetworkHandler::IsInitialized())
+ return NULL;
+ tray_ = new tray::NetworkTrayView(this);
+ return tray_;
+}
+
+views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) {
+ CHECK(default_ == NULL);
+ if (!chromeos::NetworkHandler::IsInitialized())
+ return NULL;
+ CHECK(tray_ != NULL);
+ default_ = new tray::NetworkDefaultView(
+ this, status != user::LOGGED_IN_LOCKED);
+ return default_;
+}
+
+views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) {
+ CHECK(detailed_ == NULL);
+ Shell::GetInstance()->metrics()->RecordUserMetricsAction(
+ ash::UMA_STATUS_AREA_DETAILED_NETWORK_VIEW);
+ if (!chromeos::NetworkHandler::IsInitialized())
+ return NULL;
+ if (request_wifi_view_) {
+ detailed_ = new tray::NetworkWifiDetailedView(this);
+ request_wifi_view_ = false;
+ } else {
+ detailed_ = new tray::NetworkStateListDetailedView(
+ this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK, status);
+ detailed_->Init();
+ }
+ return detailed_;
+}
+
+void TrayNetwork::DestroyTrayView() {
+ tray_ = NULL;
+}
+
+void TrayNetwork::DestroyDefaultView() {
+ default_ = NULL;
+}
+
+void TrayNetwork::DestroyDetailedView() {
+ detailed_ = NULL;
+}
+
+void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) {
+}
+
+void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
+ if (tray_) {
+ SetTrayImageItemBorder(tray_, alignment);
+ tray_->UpdateAlignment(alignment);
+ }
+}
+
+void TrayNetwork::RequestToggleWifi() {
+ // This will always be triggered by a user action (e.g. keyboard shortcut)
+ if (!detailed_ ||
+ detailed_->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW) {
+ request_wifi_view_ = true;
+ PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
+ }
+ NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
+ bool enabled = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi());
+ Shell::GetInstance()->metrics()->RecordUserMetricsAction(
+ enabled ?
+ ash::UMA_STATUS_AREA_DISABLE_WIFI :
+ ash::UMA_STATUS_AREA_ENABLE_WIFI);
+ handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
+ !enabled,
+ chromeos::network_handler::ErrorCallback());
+}
+
+void TrayNetwork::NetworkStateChanged(bool list_changed) {
+ if (tray_)
+ tray_->UpdateNetworkStateHandlerIcon();
+ if (default_)
+ default_->Update();
+ if (detailed_) {
+ if (list_changed)
+ detailed_->NetworkListChanged();
+ else
+ detailed_->ManagerChanged();
+ }
+}
+
+void TrayNetwork::NetworkServiceChanged(const chromeos::NetworkState* network) {
+ if (detailed_)
+ detailed_->NetworkServiceChanged(network);
+}
+
+} // namespace internal
+} // namespace ash