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/chromeos/network/network_icon_animation_observer.h"
33 #include "ui/views/controls/image_view.h"
34 #include "ui/views/controls/link.h"
35 #include "ui/views/controls/link_listener.h"
36 #include "ui/views/layout/box_layout.h"
37 #include "ui/views/widget/widget.h"
39 using chromeos::NetworkHandler
;
40 using chromeos::NetworkState
;
41 using chromeos::NetworkStateHandler
;
42 using chromeos::NetworkTypePattern
;
47 class NetworkTrayView
: public TrayItemView
,
48 public ui::network_icon::AnimationObserver
{
50 explicit NetworkTrayView(TrayNetwork
* network_tray
)
51 : TrayItemView(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 ~NetworkTrayView() override
{
62 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
65 const char* GetClassName() const override
{ return "NetworkTrayView"; }
67 void UpdateNetworkStateHandlerIcon() {
68 NetworkStateHandler
* handler
=
69 NetworkHandler::Get()->network_state_handler();
72 bool animating
= false;
73 ui::network_icon::GetDefaultNetworkImageAndLabel(
74 ui::network_icon::ICON_TYPE_TRAY
, &image
, &name
, &animating
);
75 bool show_in_tray
= !image
.isNull();
76 UpdateIcon(show_in_tray
, image
);
78 ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
80 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
82 // Update accessibility.
83 const NetworkState
* connected_network
=
84 handler
->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
85 if (connected_network
) {
86 UpdateConnectionStatus(base::UTF8ToUTF16(connected_network
->name()),
89 UpdateConnectionStatus(base::string16(), false);
93 void UpdateAlignment(ShelfAlignment alignment
) {
94 SetLayoutManager(new views::BoxLayout(alignment
== SHELF_ALIGNMENT_BOTTOM
95 ? views::BoxLayout::kHorizontal
96 : views::BoxLayout::kVertical
,
101 // views::View override.
102 void GetAccessibleState(ui::AXViewState
* state
) override
{
103 state
->name
= connection_status_string_
;
104 state
->role
= ui::AX_ROLE_BUTTON
;
107 // ui::network_icon::AnimationObserver
108 void NetworkIconChanged() override
{ UpdateNetworkStateHandlerIcon(); }
111 // Updates connection status and notifies accessibility event when necessary.
112 void UpdateConnectionStatus(const base::string16
& network_name
,
114 base::string16 new_connection_status_string
;
116 new_connection_status_string
= l10n_util::GetStringFUTF16(
117 IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED
, network_name
);
119 if (new_connection_status_string
!= connection_status_string_
) {
120 connection_status_string_
= new_connection_status_string
;
121 if (!connection_status_string_
.empty())
122 NotifyAccessibilityEvent(ui::AX_EVENT_ALERT
, true);
126 void UpdateIcon(bool tray_icon_visible
, const gfx::ImageSkia
& image
) {
127 image_view_
->SetImage(image
);
128 SetVisible(tray_icon_visible
);
132 views::ImageView
* image_view_
;
133 base::string16 connection_status_string_
;
135 DISALLOW_COPY_AND_ASSIGN(NetworkTrayView
);
138 class NetworkDefaultView
: public TrayItemMore
,
139 public ui::network_icon::AnimationObserver
{
141 NetworkDefaultView(TrayNetwork
* network_tray
, bool show_more
)
142 : TrayItemMore(network_tray
, show_more
) {
146 ~NetworkDefaultView() override
{
147 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
151 gfx::ImageSkia image
;
152 base::string16 label
;
153 bool animating
= false;
154 ui::network_icon::GetDefaultNetworkImageAndLabel(
155 ui::network_icon::ICON_TYPE_DEFAULT_VIEW
, &image
, &label
, &animating
);
157 ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
159 ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
163 SetAccessibleName(label
);
166 // ui::network_icon::AnimationObserver
167 void NetworkIconChanged() override
{ Update(); }
170 DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView
);
173 class NetworkWifiDetailedView
: public NetworkDetailedView
{
175 explicit NetworkWifiDetailedView(SystemTrayItem
* owner
)
176 : NetworkDetailedView(owner
) {
177 SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal
,
178 kTrayPopupPaddingHorizontal
, 10,
179 kTrayPopupPaddingBetweenItems
));
180 image_view_
= new views::ImageView
;
181 AddChildView(image_view_
);
183 label_view_
= new views::Label();
184 label_view_
->SetMultiLine(true);
185 label_view_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
186 AddChildView(label_view_
);
191 ~NetworkWifiDetailedView() override
{}
193 // Overridden from NetworkDetailedView:
195 void Init() override
{}
197 NetworkDetailedView::DetailedViewType
GetViewType() const override
{
198 return NetworkDetailedView::WIFI_VIEW
;
201 void Layout() override
{
202 // Center both views vertically.
203 views::View::Layout();
204 image_view_
->SetY((height() - image_view_
->GetPreferredSize().height()) /
206 label_view_
->SetY((height() - label_view_
->GetPreferredSize().height()) /
210 void Update() override
{
212 NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled(
213 NetworkTypePattern::WiFi());
214 const int image_id
= wifi_enabled
? IDR_AURA_UBER_TRAY_WIFI_ENABLED
215 : IDR_AURA_UBER_TRAY_WIFI_DISABLED
;
216 ui::ResourceBundle
& bundle
= ui::ResourceBundle::GetSharedInstance();
217 image_view_
->SetImage(bundle
.GetImageNamed(image_id
).ToImageSkia());
219 const int string_id
= wifi_enabled
220 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
221 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED
;
222 label_view_
->SetText(bundle
.GetLocalizedString(string_id
));
223 label_view_
->SizeToFit(
224 kTrayPopupMinWidth
- kTrayPopupPaddingHorizontal
* 2 -
225 kTrayPopupPaddingBetweenItems
- kTrayPopupDetailsIconWidth
);
229 views::ImageView
* image_view_
;
230 views::Label
* label_view_
;
232 DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView
);
237 TrayNetwork::TrayNetwork(SystemTray
* system_tray
)
238 : SystemTrayItem(system_tray
),
242 request_wifi_view_(false) {
243 network_state_observer_
.reset(new TrayNetworkStateObserver(this));
244 SystemTrayNotifier
* notifier
= Shell::GetInstance()->system_tray_notifier();
245 notifier
->AddNetworkObserver(this);
246 notifier
->AddNetworkPortalDetectorObserver(this);
249 TrayNetwork::~TrayNetwork() {
250 SystemTrayNotifier
* notifier
= Shell::GetInstance()->system_tray_notifier();
251 notifier
->RemoveNetworkObserver(this);
252 notifier
->RemoveNetworkPortalDetectorObserver(this);
255 views::View
* TrayNetwork::CreateTrayView(user::LoginStatus status
) {
256 CHECK(tray_
== NULL
);
257 if (!chromeos::NetworkHandler::IsInitialized())
259 tray_
= new tray::NetworkTrayView(this);
263 views::View
* TrayNetwork::CreateDefaultView(user::LoginStatus status
) {
264 CHECK(default_
== NULL
);
265 if (!chromeos::NetworkHandler::IsInitialized())
267 CHECK(tray_
!= NULL
);
269 new tray::NetworkDefaultView(this, status
!= user::LOGGED_IN_LOCKED
);
273 views::View
* TrayNetwork::CreateDetailedView(user::LoginStatus status
) {
274 CHECK(detailed_
== NULL
);
275 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
276 ash::UMA_STATUS_AREA_DETAILED_NETWORK_VIEW
);
277 if (!chromeos::NetworkHandler::IsInitialized())
279 if (request_wifi_view_
) {
280 detailed_
= new tray::NetworkWifiDetailedView(this);
281 request_wifi_view_
= false;
283 detailed_
= new tray::NetworkStateListDetailedView(
284 this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK
, status
);
290 void TrayNetwork::DestroyTrayView() {
294 void TrayNetwork::DestroyDefaultView() {
298 void TrayNetwork::DestroyDetailedView() {
302 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status
) {
305 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment
) {
307 SetTrayImageItemBorder(tray_
, alignment
);
308 tray_
->UpdateAlignment(alignment
);
312 void TrayNetwork::RequestToggleWifi() {
313 // This will always be triggered by a user action (e.g. keyboard shortcut)
315 detailed_
->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW
) {
316 request_wifi_view_
= true;
317 PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds
, false);
319 NetworkStateHandler
* handler
= NetworkHandler::Get()->network_state_handler();
320 bool enabled
= handler
->IsTechnologyEnabled(NetworkTypePattern::WiFi());
321 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
322 enabled
? ash::UMA_STATUS_AREA_DISABLE_WIFI
323 : ash::UMA_STATUS_AREA_ENABLE_WIFI
);
324 handler
->SetTechnologyEnabled(NetworkTypePattern::WiFi(), !enabled
,
325 chromeos::network_handler::ErrorCallback());
328 void TrayNetwork::OnCaptivePortalDetected(
329 const std::string
& /* service_path */) {
330 NetworkStateChanged();
333 void TrayNetwork::NetworkStateChanged() {
335 tray_
->UpdateNetworkStateHandlerIcon();