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
) {
52 new views::BoxLayout(views::BoxLayout::kHorizontal
, 0, 0, 0));
54 image_view_
= new views::ImageView
;
55 AddChildView(image_view_
);
57 UpdateNetworkStateHandlerIcon();
60 ~NetworkTrayView() override
{
61 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
64 const char* GetClassName() const override
{ return "NetworkTrayView"; }
66 void UpdateNetworkStateHandlerIcon() {
67 NetworkStateHandler
* handler
=
68 NetworkHandler::Get()->network_state_handler();
71 bool animating
= false;
72 ui::network_icon::GetDefaultNetworkImageAndLabel(
73 ui::network_icon::ICON_TYPE_TRAY
, &image
, &name
, &animating
);
74 bool show_in_tray
= !image
.isNull();
75 UpdateIcon(show_in_tray
, image
);
77 ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
79 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
81 // Update accessibility.
82 const NetworkState
* connected_network
=
83 handler
->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
84 if (connected_network
) {
85 UpdateConnectionStatus(base::UTF8ToUTF16(connected_network
->name()),
88 UpdateConnectionStatus(base::string16(), false);
92 void UpdateAlignment(ShelfAlignment alignment
) {
93 SetLayoutManager(new views::BoxLayout(alignment
== SHELF_ALIGNMENT_BOTTOM
94 ? views::BoxLayout::kHorizontal
95 : views::BoxLayout::kVertical
,
100 // views::View override.
101 void GetAccessibleState(ui::AXViewState
* state
) override
{
102 state
->name
= connection_status_string_
;
103 state
->role
= ui::AX_ROLE_BUTTON
;
106 // ui::network_icon::AnimationObserver
107 void NetworkIconChanged() override
{ UpdateNetworkStateHandlerIcon(); }
110 // Updates connection status and notifies accessibility event when necessary.
111 void UpdateConnectionStatus(const base::string16
& network_name
,
113 base::string16 new_connection_status_string
;
115 new_connection_status_string
= l10n_util::GetStringFUTF16(
116 IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED
, network_name
);
118 if (new_connection_status_string
!= connection_status_string_
) {
119 connection_status_string_
= new_connection_status_string
;
120 if (!connection_status_string_
.empty())
121 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT
, true);
125 void UpdateIcon(bool tray_icon_visible
, const gfx::ImageSkia
& image
) {
126 image_view_
->SetImage(image
);
127 SetVisible(tray_icon_visible
);
131 views::ImageView
* image_view_
;
132 base::string16 connection_status_string_
;
134 DISALLOW_COPY_AND_ASSIGN(NetworkTrayView
);
137 class NetworkDefaultView
: public TrayItemMore
,
138 public ui::network_icon::AnimationObserver
{
140 NetworkDefaultView(TrayNetwork
* network_tray
, bool show_more
)
141 : TrayItemMore(network_tray
, show_more
) {
145 ~NetworkDefaultView() override
{
146 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
150 gfx::ImageSkia image
;
151 base::string16 label
;
152 bool animating
= false;
153 ui::network_icon::GetDefaultNetworkImageAndLabel(
154 ui::network_icon::ICON_TYPE_DEFAULT_VIEW
, &image
, &label
, &animating
);
156 ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
158 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
162 SetAccessibleName(label
);
165 // ui::network_icon::AnimationObserver
166 void NetworkIconChanged() override
{ Update(); }
169 DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView
);
172 class NetworkWifiDetailedView
: public NetworkDetailedView
{
174 explicit NetworkWifiDetailedView(SystemTrayItem
* owner
)
175 : NetworkDetailedView(owner
) {
176 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal
,
177 kTrayPopupPaddingHorizontal
, 10,
178 kTrayPopupPaddingBetweenItems
));
179 image_view_
= new views::ImageView
;
180 AddChildView(image_view_
);
182 label_view_
= new views::Label();
183 label_view_
->SetMultiLine(true);
184 label_view_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
185 AddChildView(label_view_
);
190 ~NetworkWifiDetailedView() override
{}
192 // Overridden from NetworkDetailedView:
194 void Init() override
{}
196 NetworkDetailedView::DetailedViewType
GetViewType() const override
{
197 return NetworkDetailedView::WIFI_VIEW
;
200 void Layout() override
{
201 // Center both views vertically.
202 views::View::Layout();
203 image_view_
->SetY((height() - image_view_
->GetPreferredSize().height()) /
205 label_view_
->SetY((height() - label_view_
->GetPreferredSize().height()) /
209 void Update() override
{
211 NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled(
212 NetworkTypePattern::WiFi());
213 const int image_id
= wifi_enabled
? IDR_AURA_UBER_TRAY_WIFI_ENABLED
214 : IDR_AURA_UBER_TRAY_WIFI_DISABLED
;
215 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
216 image_view_
->SetImage(bundle
.GetImageNamed(image_id
).ToImageSkia());
218 const int string_id
= wifi_enabled
219 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
220 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED
;
221 label_view_
->SetText(bundle
.GetLocalizedString(string_id
));
222 label_view_
->SizeToFit(
223 kTrayPopupMinWidth
- kTrayPopupPaddingHorizontal
* 2 -
224 kTrayPopupPaddingBetweenItems
- kTrayPopupDetailsIconWidth
);
228 views::ImageView
* image_view_
;
229 views::Label
* label_view_
;
231 DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView
);
236 TrayNetwork::TrayNetwork(SystemTray
* system_tray
)
237 : SystemTrayItem(system_tray
),
241 request_wifi_view_(false) {
242 network_state_observer_
.reset(new TrayNetworkStateObserver(this));
243 SystemTrayNotifier
* notifier
= Shell::GetInstance()->system_tray_notifier();
244 notifier
->AddNetworkObserver(this);
245 notifier
->AddNetworkPortalDetectorObserver(this);
248 TrayNetwork::~TrayNetwork() {
249 SystemTrayNotifier
* notifier
= Shell::GetInstance()->system_tray_notifier();
250 notifier
->RemoveNetworkObserver(this);
251 notifier
->RemoveNetworkPortalDetectorObserver(this);
254 views::View
* TrayNetwork::CreateTrayView(user::LoginStatus status
) {
255 CHECK(tray_
== NULL
);
256 if (!chromeos::NetworkHandler::IsInitialized())
258 tray_
= new tray::NetworkTrayView(this);
262 views::View
* TrayNetwork::CreateDefaultView(user::LoginStatus status
) {
263 CHECK(default_
== NULL
);
264 if (!chromeos::NetworkHandler::IsInitialized())
266 CHECK(tray_
!= NULL
);
268 new tray::NetworkDefaultView(this, status
!= user::LOGGED_IN_LOCKED
);
272 views::View
* TrayNetwork::CreateDetailedView(user::LoginStatus status
) {
273 CHECK(detailed_
== NULL
);
274 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
275 ash::UMA_STATUS_AREA_DETAILED_NETWORK_VIEW
);
276 if (!chromeos::NetworkHandler::IsInitialized())
278 if (request_wifi_view_
) {
279 detailed_
= new tray::NetworkWifiDetailedView(this);
280 request_wifi_view_
= false;
282 detailed_
= new tray::NetworkStateListDetailedView(
283 this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK
, status
);
289 void TrayNetwork::DestroyTrayView() {
293 void TrayNetwork::DestroyDefaultView() {
297 void TrayNetwork::DestroyDetailedView() {
301 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status
) {
304 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment
) {
306 SetTrayImageItemBorder(tray_
, alignment
);
307 tray_
->UpdateAlignment(alignment
);
311 void TrayNetwork::RequestToggleWifi() {
312 // This will always be triggered by a user action (e.g. keyboard shortcut)
314 detailed_
->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW
) {
315 request_wifi_view_
= true;
316 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds
, false);
318 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
319 bool enabled
= handler
->IsTechnologyEnabled(NetworkTypePattern::WiFi());
320 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
321 enabled
? ash::UMA_STATUS_AREA_DISABLE_WIFI
322 : ash::UMA_STATUS_AREA_ENABLE_WIFI
);
323 handler
->SetTechnologyEnabled(NetworkTypePattern::WiFi(), !enabled
,
324 chromeos::network_handler::ErrorCallback());
327 void TrayNetwork::OnCaptivePortalDetected(
328 const std::string
& /* service_path */) {
329 NetworkStateChanged();
332 void TrayNetwork::NetworkStateChanged() {
334 tray_
->UpdateNetworkStateHandlerIcon();