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.
5 #include "ash/system/chromeos/network/tray_network.h"
7 #include "ash/ash_switches.h"
8 #include "ash/metrics/user_metrics_recorder.h"
10 #include "ash/system/chromeos/network/network_state_list_detailed_view.h"
11 #include "ash/system/chromeos/network/tray_network_state_observer.h"
12 #include "ash/system/tray/system_tray.h"
13 #include "ash/system/tray/system_tray_delegate.h"
14 #include "ash/system/tray/system_tray_notifier.h"
15 #include "ash/system/tray/tray_constants.h"
16 #include "ash/system/tray/tray_item_more.h"
17 #include "ash/system/tray/tray_item_view.h"
18 #include "ash/system/tray/tray_utils.h"
19 #include "base/command_line.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "chromeos/network/network_state.h"
22 #include "chromeos/network/network_state_handler.h"
23 #include "grit/ash_resources.h"
24 #include "grit/ash_strings.h"
25 #include "grit/ui_chromeos_strings.h"
26 #include "third_party/cros_system_api/dbus/service_constants.h"
27 #include "ui/accessibility/ax_view_state.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/resource/resource_bundle.h"
30 #include "ui/chromeos/network/network_icon.h"
31 #include "ui/chromeos/network/network_icon_animation.h"
32 #include "ui/views/controls/image_view.h"
33 #include "ui/views/controls/link.h"
34 #include "ui/views/controls/link_listener.h"
35 #include "ui/views/layout/box_layout.h"
36 #include "ui/views/widget/widget.h"
38 using chromeos::NetworkHandler;
39 using chromeos::NetworkState;
40 using chromeos::NetworkStateHandler;
41 using chromeos::NetworkTypePattern;
46 class NetworkTrayView : public TrayItemView,
47 public ui::network_icon::AnimationObserver {
49 explicit NetworkTrayView(TrayNetwork* network_tray)
50 : TrayItemView(network_tray),
51 network_tray_(network_tray) {
53 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
55 image_view_ = new views::ImageView;
56 AddChildView(image_view_);
58 UpdateNetworkStateHandlerIcon();
61 virtual ~NetworkTrayView() {
62 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
65 virtual const char* GetClassName() const OVERRIDE {
66 return "NetworkTrayView";
69 void UpdateNetworkStateHandlerIcon() {
70 NetworkStateHandler* handler =
71 NetworkHandler::Get()->network_state_handler();
74 bool animating = false;
75 ui::network_icon::GetDefaultNetworkImageAndLabel(
76 ui::network_icon::ICON_TYPE_TRAY, &image, &name, &animating);
77 bool show_in_tray = !image.isNull();
78 UpdateIcon(show_in_tray, image);
80 ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
82 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
84 // Update accessibility.
85 const NetworkState* connected_network =
86 handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
87 if (connected_network) {
88 UpdateConnectionStatus(
89 base::UTF8ToUTF16(connected_network->name()), true);
91 UpdateConnectionStatus(base::string16(), false);
95 void UpdateAlignment(ShelfAlignment alignment) {
96 SetLayoutManager(new views::BoxLayout(
97 alignment == SHELF_ALIGNMENT_BOTTOM ?
98 views::BoxLayout::kHorizontal : views::BoxLayout::kVertical,
103 // views::View override.
104 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
105 state->name = connection_status_string_;
106 state->role = ui::AX_ROLE_BUTTON;
109 // ui::network_icon::AnimationObserver
110 virtual void NetworkIconChanged() OVERRIDE {
111 UpdateNetworkStateHandlerIcon();
115 // Updates connection status and notifies accessibility event when necessary.
116 void UpdateConnectionStatus(const base::string16& network_name,
118 base::string16 new_connection_status_string;
120 new_connection_status_string = l10n_util::GetStringFUTF16(
121 IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, network_name);
123 if (new_connection_status_string != connection_status_string_) {
124 connection_status_string_ = new_connection_status_string;
125 if(!connection_status_string_.empty())
126 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
130 void UpdateIcon(bool tray_icon_visible, const gfx::ImageSkia& image) {
131 image_view_->SetImage(image);
132 SetVisible(tray_icon_visible);
136 TrayNetwork* network_tray_;
137 views::ImageView* image_view_;
138 base::string16 connection_status_string_;
140 DISALLOW_COPY_AND_ASSIGN(NetworkTrayView);
143 class NetworkDefaultView : public TrayItemMore,
144 public ui::network_icon::AnimationObserver {
146 NetworkDefaultView(TrayNetwork* network_tray, bool show_more)
147 : TrayItemMore(network_tray, show_more),
148 network_tray_(network_tray) {
152 virtual ~NetworkDefaultView() {
153 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
157 gfx::ImageSkia image;
158 base::string16 label;
159 bool animating = false;
160 ui::network_icon::GetDefaultNetworkImageAndLabel(
161 ui::network_icon::ICON_TYPE_DEFAULT_VIEW, &image, &label, &animating);
163 ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
165 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
169 SetAccessibleName(label);
172 // ui::network_icon::AnimationObserver
173 virtual void NetworkIconChanged() OVERRIDE {
178 TrayNetwork* network_tray_;
180 DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView);
183 class NetworkWifiDetailedView : public NetworkDetailedView {
185 explicit NetworkWifiDetailedView(SystemTrayItem* owner)
186 : NetworkDetailedView(owner) {
187 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
188 kTrayPopupPaddingHorizontal,
190 kTrayPopupPaddingBetweenItems));
191 image_view_ = new views::ImageView;
192 AddChildView(image_view_);
194 label_view_ = new views::Label();
195 label_view_->SetMultiLine(true);
196 label_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
197 AddChildView(label_view_);
202 virtual ~NetworkWifiDetailedView() {
205 // Overridden from NetworkDetailedView:
207 virtual void Init() OVERRIDE {
210 virtual NetworkDetailedView::DetailedViewType GetViewType() const OVERRIDE {
211 return NetworkDetailedView::WIFI_VIEW;
214 virtual void ManagerChanged() OVERRIDE {
218 virtual void NetworkListChanged() OVERRIDE {
222 virtual void NetworkServiceChanged(
223 const chromeos::NetworkState* network) OVERRIDE {
227 virtual void Layout() OVERRIDE {
228 // Center both views vertically.
229 views::View::Layout();
231 (height() - image_view_->GetPreferredSize().height()) / 2);
233 (height() - label_view_->GetPreferredSize().height()) / 2);
238 NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled(
239 NetworkTypePattern::WiFi());
240 const int image_id = wifi_enabled ?
241 IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED;
242 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
243 image_view_->SetImage(bundle.GetImageNamed(image_id).ToImageSkia());
245 const int string_id = wifi_enabled ?
246 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED :
247 IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
248 label_view_->SetText(bundle.GetLocalizedString(string_id));
249 label_view_->SizeToFit(kTrayPopupMinWidth -
250 kTrayPopupPaddingHorizontal * 2 - kTrayPopupPaddingBetweenItems -
251 kTrayPopupDetailsIconWidth);
254 views::ImageView* image_view_;
255 views::Label* label_view_;
257 DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView);
262 TrayNetwork::TrayNetwork(SystemTray* system_tray)
263 : SystemTrayItem(system_tray),
267 request_wifi_view_(false) {
268 network_state_observer_.reset(new TrayNetworkStateObserver(this));
269 SystemTrayNotifier* notifier = Shell::GetInstance()->system_tray_notifier();
270 notifier->AddNetworkObserver(this);
271 notifier->AddNetworkPortalDetectorObserver(this);
274 TrayNetwork::~TrayNetwork() {
275 SystemTrayNotifier* notifier = Shell::GetInstance()->system_tray_notifier();
276 notifier->RemoveNetworkObserver(this);
277 notifier->RemoveNetworkPortalDetectorObserver(this);
280 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) {
281 CHECK(tray_ == NULL);
282 if (!chromeos::NetworkHandler::IsInitialized())
284 tray_ = new tray::NetworkTrayView(this);
288 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) {
289 CHECK(default_ == NULL);
290 if (!chromeos::NetworkHandler::IsInitialized())
292 CHECK(tray_ != NULL);
293 default_ = new tray::NetworkDefaultView(
294 this, status != user::LOGGED_IN_LOCKED);
298 views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) {
299 CHECK(detailed_ == NULL);
300 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
301 ash::UMA_STATUS_AREA_DETAILED_NETWORK_VIEW);
302 if (!chromeos::NetworkHandler::IsInitialized())
304 if (request_wifi_view_) {
305 detailed_ = new tray::NetworkWifiDetailedView(this);
306 request_wifi_view_ = false;
308 detailed_ = new tray::NetworkStateListDetailedView(
309 this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK, status);
315 void TrayNetwork::DestroyTrayView() {
319 void TrayNetwork::DestroyDefaultView() {
323 void TrayNetwork::DestroyDetailedView() {
327 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) {
330 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
332 SetTrayImageItemBorder(tray_, alignment);
333 tray_->UpdateAlignment(alignment);
337 void TrayNetwork::RequestToggleWifi() {
338 // This will always be triggered by a user action (e.g. keyboard shortcut)
340 detailed_->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW) {
341 request_wifi_view_ = true;
342 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
344 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
345 bool enabled = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi());
346 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
348 ash::UMA_STATUS_AREA_DISABLE_WIFI :
349 ash::UMA_STATUS_AREA_ENABLE_WIFI);
350 handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
352 chromeos::network_handler::ErrorCallback());
355 void TrayNetwork::OnCaptivePortalDetected(
356 const std::string& /* service_path */) {
357 NetworkStateChanged(false);
360 void TrayNetwork::NetworkStateChanged(bool list_changed) {
362 tray_->UpdateNetworkStateHandlerIcon();
367 detailed_->NetworkListChanged();
369 detailed_->ManagerChanged();
373 void TrayNetwork::NetworkServiceChanged(const chromeos::NetworkState* network) {
375 detailed_->NetworkServiceChanged(network);