• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "ash/system/chromeos/network/tray_network.h"
6 
7 #include "ash/ash_switches.h"
8 #include "ash/metrics/user_metrics_recorder.h"
9 #include "ash/shell.h"
10 #include "ash/system/chromeos/network/network_icon_animation.h"
11 #include "ash/system/chromeos/network/network_state_list_detailed_view.h"
12 #include "ash/system/chromeos/network/tray_network_state_observer.h"
13 #include "ash/system/tray/system_tray.h"
14 #include "ash/system/tray/system_tray_delegate.h"
15 #include "ash/system/tray/system_tray_notifier.h"
16 #include "ash/system/tray/tray_constants.h"
17 #include "ash/system/tray/tray_item_more.h"
18 #include "ash/system/tray/tray_item_view.h"
19 #include "ash/system/tray/tray_utils.h"
20 #include "base/command_line.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "chromeos/network/network_state.h"
23 #include "chromeos/network/network_state_handler.h"
24 #include "grit/ash_resources.h"
25 #include "grit/ash_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/views/controls/image_view.h"
31 #include "ui/views/controls/link.h"
32 #include "ui/views/controls/link_listener.h"
33 #include "ui/views/layout/box_layout.h"
34 #include "ui/views/widget/widget.h"
35 
36 using chromeos::NetworkHandler;
37 using chromeos::NetworkState;
38 using chromeos::NetworkStateHandler;
39 using chromeos::NetworkTypePattern;
40 
41 namespace ash {
42 namespace tray {
43 
44 class NetworkTrayView : public TrayItemView,
45                         public network_icon::AnimationObserver {
46  public:
NetworkTrayView(TrayNetwork * network_tray)47   explicit NetworkTrayView(TrayNetwork* network_tray)
48       : TrayItemView(network_tray),
49         network_tray_(network_tray) {
50     SetLayoutManager(
51         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
52 
53     image_view_ = new views::ImageView;
54     AddChildView(image_view_);
55 
56     UpdateNetworkStateHandlerIcon();
57   }
58 
~NetworkTrayView()59   virtual ~NetworkTrayView() {
60     network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
61   }
62 
GetClassName() const63   virtual const char* GetClassName() const OVERRIDE {
64     return "NetworkTrayView";
65   }
66 
UpdateNetworkStateHandlerIcon()67   void UpdateNetworkStateHandlerIcon() {
68     NetworkStateHandler* handler =
69         NetworkHandler::Get()->network_state_handler();
70     gfx::ImageSkia image;
71     base::string16 name;
72     bool animating = false;
73     network_icon::GetDefaultNetworkImageAndLabel(
74         network_icon::ICON_TYPE_TRAY, &image, &name, &animating);
75     bool show_in_tray = !image.isNull();
76     UpdateIcon(show_in_tray, image);
77     if (animating)
78       network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
79     else
80       network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
81     // Update accessibility.
82     const NetworkState* connected_network =
83         handler->ConnectedNetworkByType(NetworkTypePattern::NonVirtual());
84     if (connected_network) {
85       UpdateConnectionStatus(
86           base::UTF8ToUTF16(connected_network->name()), true);
87     } else {
88       UpdateConnectionStatus(base::string16(), false);
89     }
90   }
91 
UpdateAlignment(ShelfAlignment alignment)92   void UpdateAlignment(ShelfAlignment alignment) {
93     SetLayoutManager(new views::BoxLayout(
94         alignment == SHELF_ALIGNMENT_BOTTOM ?
95             views::BoxLayout::kHorizontal : views::BoxLayout::kVertical,
96             0, 0, 0));
97     Layout();
98   }
99 
100   // views::View override.
GetAccessibleState(ui::AXViewState * state)101   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE {
102     state->name = connection_status_string_;
103     state->role = ui::AX_ROLE_BUTTON;
104   }
105 
106   // network_icon::AnimationObserver
NetworkIconChanged()107   virtual void NetworkIconChanged() OVERRIDE {
108     UpdateNetworkStateHandlerIcon();
109   }
110 
111  private:
112   // Updates connection status and notifies accessibility event when necessary.
UpdateConnectionStatus(const base::string16 & network_name,bool connected)113   void UpdateConnectionStatus(const base::string16& network_name,
114                               bool connected) {
115     base::string16 new_connection_status_string;
116     if (connected) {
117       new_connection_status_string = l10n_util::GetStringFUTF16(
118           IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, network_name);
119     }
120     if (new_connection_status_string != connection_status_string_) {
121       connection_status_string_ = new_connection_status_string;
122       if(!connection_status_string_.empty())
123         NotifyAccessibilityEvent(ui::AX_EVENT_ALERT, true);
124     }
125   }
126 
UpdateIcon(bool tray_icon_visible,const gfx::ImageSkia & image)127   void UpdateIcon(bool tray_icon_visible, const gfx::ImageSkia& image) {
128     image_view_->SetImage(image);
129     SetVisible(tray_icon_visible);
130     SchedulePaint();
131   }
132 
133   TrayNetwork* network_tray_;
134   views::ImageView* image_view_;
135   base::string16 connection_status_string_;
136 
137   DISALLOW_COPY_AND_ASSIGN(NetworkTrayView);
138 };
139 
140 class NetworkDefaultView : public TrayItemMore,
141                            public network_icon::AnimationObserver {
142  public:
NetworkDefaultView(TrayNetwork * network_tray,bool show_more)143   NetworkDefaultView(TrayNetwork* network_tray, bool show_more)
144       : TrayItemMore(network_tray, show_more),
145         network_tray_(network_tray) {
146     Update();
147   }
148 
~NetworkDefaultView()149   virtual ~NetworkDefaultView() {
150     network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
151   }
152 
Update()153   void Update() {
154     gfx::ImageSkia image;
155     base::string16 label;
156     bool animating = false;
157     network_icon::GetDefaultNetworkImageAndLabel(
158         network_icon::ICON_TYPE_DEFAULT_VIEW, &image, &label, &animating);
159     if (animating)
160       network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
161     else
162       network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
163     SetImage(&image);
164     SetLabel(label);
165     SetAccessibleName(label);
166   }
167 
168   // network_icon::AnimationObserver
NetworkIconChanged()169   virtual void NetworkIconChanged() OVERRIDE {
170     Update();
171   }
172 
173  private:
174   TrayNetwork* network_tray_;
175 
176   DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView);
177 };
178 
179 class NetworkWifiDetailedView : public NetworkDetailedView {
180  public:
NetworkWifiDetailedView(SystemTrayItem * owner)181   explicit NetworkWifiDetailedView(SystemTrayItem* owner)
182       : NetworkDetailedView(owner) {
183     SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
184                                           kTrayPopupPaddingHorizontal,
185                                           10,
186                                           kTrayPopupPaddingBetweenItems));
187     image_view_ = new views::ImageView;
188     AddChildView(image_view_);
189 
190     label_view_ = new views::Label();
191     label_view_->SetMultiLine(true);
192     label_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
193     AddChildView(label_view_);
194 
195     Update();
196   }
197 
~NetworkWifiDetailedView()198   virtual ~NetworkWifiDetailedView() {
199   }
200 
201   // Overridden from NetworkDetailedView:
202 
Init()203   virtual void Init() OVERRIDE {
204   }
205 
GetViewType() const206   virtual NetworkDetailedView::DetailedViewType GetViewType() const OVERRIDE {
207     return NetworkDetailedView::WIFI_VIEW;
208   }
209 
ManagerChanged()210   virtual void ManagerChanged() OVERRIDE {
211     Update();
212   }
213 
NetworkListChanged()214   virtual void NetworkListChanged() OVERRIDE {
215     Update();
216   }
217 
NetworkServiceChanged(const chromeos::NetworkState * network)218   virtual void NetworkServiceChanged(
219       const chromeos::NetworkState* network) OVERRIDE {
220   }
221 
222  private:
Layout()223   virtual void Layout() OVERRIDE {
224     // Center both views vertically.
225     views::View::Layout();
226     image_view_->SetY(
227         (height() - image_view_->GetPreferredSize().height()) / 2);
228     label_view_->SetY(
229         (height() - label_view_->GetPreferredSize().height()) / 2);
230   }
231 
Update()232   void Update() {
233     bool wifi_enabled =
234         NetworkHandler::Get()->network_state_handler()->IsTechnologyEnabled(
235             NetworkTypePattern::WiFi());
236     const int image_id = wifi_enabled ?
237         IDR_AURA_UBER_TRAY_WIFI_ENABLED : IDR_AURA_UBER_TRAY_WIFI_DISABLED;
238     ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
239     image_view_->SetImage(bundle.GetImageNamed(image_id).ToImageSkia());
240 
241     const int string_id = wifi_enabled ?
242         IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED :
243         IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
244     label_view_->SetText(bundle.GetLocalizedString(string_id));
245     label_view_->SizeToFit(kTrayPopupMinWidth -
246         kTrayPopupPaddingHorizontal * 2 - kTrayPopupPaddingBetweenItems -
247         kTrayPopupDetailsIconWidth);
248   }
249 
250   views::ImageView* image_view_;
251   views::Label* label_view_;
252 
253   DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView);
254 };
255 
256 }  // namespace tray
257 
TrayNetwork(SystemTray * system_tray)258 TrayNetwork::TrayNetwork(SystemTray* system_tray)
259     : SystemTrayItem(system_tray),
260       tray_(NULL),
261       default_(NULL),
262       detailed_(NULL),
263       request_wifi_view_(false) {
264   network_state_observer_.reset(new TrayNetworkStateObserver(this));
265   SystemTrayNotifier* notifier = Shell::GetInstance()->system_tray_notifier();
266   notifier->AddNetworkObserver(this);
267   notifier->AddNetworkPortalDetectorObserver(this);
268 }
269 
~TrayNetwork()270 TrayNetwork::~TrayNetwork() {
271   SystemTrayNotifier* notifier = Shell::GetInstance()->system_tray_notifier();
272   notifier->RemoveNetworkObserver(this);
273   notifier->RemoveNetworkPortalDetectorObserver(this);
274 }
275 
CreateTrayView(user::LoginStatus status)276 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) {
277   CHECK(tray_ == NULL);
278   if (!chromeos::NetworkHandler::IsInitialized())
279     return NULL;
280   tray_ = new tray::NetworkTrayView(this);
281   return tray_;
282 }
283 
CreateDefaultView(user::LoginStatus status)284 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) {
285   CHECK(default_ == NULL);
286   if (!chromeos::NetworkHandler::IsInitialized())
287     return NULL;
288   CHECK(tray_ != NULL);
289   default_ = new tray::NetworkDefaultView(
290       this, status != user::LOGGED_IN_LOCKED);
291   return default_;
292 }
293 
CreateDetailedView(user::LoginStatus status)294 views::View* TrayNetwork::CreateDetailedView(user::LoginStatus status) {
295   CHECK(detailed_ == NULL);
296   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
297     ash::UMA_STATUS_AREA_DETAILED_NETWORK_VIEW);
298   if (!chromeos::NetworkHandler::IsInitialized())
299     return NULL;
300   if (request_wifi_view_) {
301     detailed_ = new tray::NetworkWifiDetailedView(this);
302     request_wifi_view_ = false;
303   } else {
304     detailed_ = new tray::NetworkStateListDetailedView(
305         this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK, status);
306     detailed_->Init();
307   }
308   return detailed_;
309 }
310 
DestroyTrayView()311 void TrayNetwork::DestroyTrayView() {
312   tray_ = NULL;
313 }
314 
DestroyDefaultView()315 void TrayNetwork::DestroyDefaultView() {
316   default_ = NULL;
317 }
318 
DestroyDetailedView()319 void TrayNetwork::DestroyDetailedView() {
320   detailed_ = NULL;
321 }
322 
UpdateAfterLoginStatusChange(user::LoginStatus status)323 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) {
324 }
325 
UpdateAfterShelfAlignmentChange(ShelfAlignment alignment)326 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
327   if (tray_) {
328     SetTrayImageItemBorder(tray_, alignment);
329     tray_->UpdateAlignment(alignment);
330   }
331 }
332 
RequestToggleWifi()333 void TrayNetwork::RequestToggleWifi() {
334   // This will always be triggered by a user action (e.g. keyboard shortcut)
335   if (!detailed_ ||
336       detailed_->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW) {
337     request_wifi_view_ = true;
338     PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
339   }
340   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
341   bool enabled = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi());
342   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
343       enabled ?
344       ash::UMA_STATUS_AREA_DISABLE_WIFI :
345       ash::UMA_STATUS_AREA_ENABLE_WIFI);
346   handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
347                                 !enabled,
348                                 chromeos::network_handler::ErrorCallback());
349 }
350 
OnCaptivePortalDetected(const std::string &)351 void TrayNetwork::OnCaptivePortalDetected(
352     const std::string& /* service_path */) {
353   NetworkStateChanged(false);
354 }
355 
NetworkStateChanged(bool list_changed)356 void TrayNetwork::NetworkStateChanged(bool list_changed) {
357   if (tray_)
358     tray_->UpdateNetworkStateHandlerIcon();
359   if (default_)
360     default_->Update();
361   if (detailed_) {
362     if (list_changed)
363       detailed_->NetworkListChanged();
364     else
365       detailed_->ManagerChanged();
366   }
367 }
368 
NetworkServiceChanged(const chromeos::NetworkState * network)369 void TrayNetwork::NetworkServiceChanged(const chromeos::NetworkState* network) {
370   if (detailed_)
371     detailed_->NetworkServiceChanged(network);
372 }
373 
374 }  // namespace ash
375