Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / ash / system / chromeos / network / tray_network.cc
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_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"
37
38 using chromeos::NetworkHandler;
39 using chromeos::NetworkState;
40 using chromeos::NetworkStateHandler;
41 using chromeos::NetworkTypePattern;
42
43 namespace ash {
44 namespace tray {
45
46 class NetworkTrayView : public TrayItemView,
47                         public ui::network_icon::AnimationObserver {
48  public:
49   explicit NetworkTrayView(TrayNetwork* network_tray)
50       : TrayItemView(network_tray),
51         network_tray_(network_tray) {
52     SetLayoutManager(
53         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 0));
54
55     image_view_ = new views::ImageView;
56     AddChildView(image_view_);
57
58     UpdateNetworkStateHandlerIcon();
59   }
60
61   virtual ~NetworkTrayView() {
62     ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
63   }
64
65   virtual const char* GetClassName() const OVERRIDE {
66     return "NetworkTrayView";
67   }
68
69   void UpdateNetworkStateHandlerIcon() {
70     NetworkStateHandler* handler =
71         NetworkHandler::Get()->network_state_handler();
72     gfx::ImageSkia image;
73     base::string16 name;
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);
79     if (animating)
80       ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
81     else
82       ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
83           this);
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);
90     } else {
91       UpdateConnectionStatus(base::string16(), false);
92     }
93   }
94
95   void UpdateAlignment(ShelfAlignment alignment) {
96     SetLayoutManager(new views::BoxLayout(
97         alignment == SHELF_ALIGNMENT_BOTTOM ?
98             views::BoxLayout::kHorizontal : views::BoxLayout::kVertical,
99             0, 0, 0));
100     Layout();
101   }
102
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;
107   }
108
109   // ui::network_icon::AnimationObserver
110   virtual void NetworkIconChanged() OVERRIDE {
111     UpdateNetworkStateHandlerIcon();
112   }
113
114  private:
115   // Updates connection status and notifies accessibility event when necessary.
116   void UpdateConnectionStatus(const base::string16& network_name,
117                               bool connected) {
118     base::string16 new_connection_status_string;
119     if (connected) {
120       new_connection_status_string = l10n_util::GetStringFUTF16(
121           IDS_ASH_STATUS_TRAY_NETWORK_CONNECTED, network_name);
122     }
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);
127     }
128   }
129
130   void UpdateIcon(bool tray_icon_visible, const gfx::ImageSkia& image) {
131     image_view_->SetImage(image);
132     SetVisible(tray_icon_visible);
133     SchedulePaint();
134   }
135
136   TrayNetwork* network_tray_;
137   views::ImageView* image_view_;
138   base::string16 connection_status_string_;
139
140   DISALLOW_COPY_AND_ASSIGN(NetworkTrayView);
141 };
142
143 class NetworkDefaultView : public TrayItemMore,
144                            public ui::network_icon::AnimationObserver {
145  public:
146   NetworkDefaultView(TrayNetwork* network_tray, bool show_more)
147       : TrayItemMore(network_tray, show_more),
148         network_tray_(network_tray) {
149     Update();
150   }
151
152   virtual ~NetworkDefaultView() {
153     ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
154   }
155
156   void Update() {
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);
162     if (animating)
163       ui::network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
164     else
165       ui::network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(
166           this);
167     SetImage(&image);
168     SetLabel(label);
169     SetAccessibleName(label);
170   }
171
172   // ui::network_icon::AnimationObserver
173   virtual void NetworkIconChanged() OVERRIDE {
174     Update();
175   }
176
177  private:
178   TrayNetwork* network_tray_;
179
180   DISALLOW_COPY_AND_ASSIGN(NetworkDefaultView);
181 };
182
183 class NetworkWifiDetailedView : public NetworkDetailedView {
184  public:
185   explicit NetworkWifiDetailedView(SystemTrayItem* owner)
186       : NetworkDetailedView(owner) {
187     SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal,
188                                           kTrayPopupPaddingHorizontal,
189                                           10,
190                                           kTrayPopupPaddingBetweenItems));
191     image_view_ = new views::ImageView;
192     AddChildView(image_view_);
193
194     label_view_ = new views::Label();
195     label_view_->SetMultiLine(true);
196     label_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
197     AddChildView(label_view_);
198
199     Update();
200   }
201
202   virtual ~NetworkWifiDetailedView() {
203   }
204
205   // Overridden from NetworkDetailedView:
206
207   virtual void Init() OVERRIDE {
208   }
209
210   virtual NetworkDetailedView::DetailedViewType GetViewType() const OVERRIDE {
211     return NetworkDetailedView::WIFI_VIEW;
212   }
213
214   virtual void ManagerChanged() OVERRIDE {
215     Update();
216   }
217
218   virtual void NetworkListChanged() OVERRIDE {
219     Update();
220   }
221
222   virtual void NetworkServiceChanged(
223       const chromeos::NetworkState* network) OVERRIDE {
224   }
225
226  private:
227   virtual void Layout() OVERRIDE {
228     // Center both views vertically.
229     views::View::Layout();
230     image_view_->SetY(
231         (height() - image_view_->GetPreferredSize().height()) / 2);
232     label_view_->SetY(
233         (height() - label_view_->GetPreferredSize().height()) / 2);
234   }
235
236   void Update() {
237     bool wifi_enabled =
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());
244
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);
252   }
253
254   views::ImageView* image_view_;
255   views::Label* label_view_;
256
257   DISALLOW_COPY_AND_ASSIGN(NetworkWifiDetailedView);
258 };
259
260 }  // namespace tray
261
262 TrayNetwork::TrayNetwork(SystemTray* system_tray)
263     : SystemTrayItem(system_tray),
264       tray_(NULL),
265       default_(NULL),
266       detailed_(NULL),
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);
272 }
273
274 TrayNetwork::~TrayNetwork() {
275   SystemTrayNotifier* notifier = Shell::GetInstance()->system_tray_notifier();
276   notifier->RemoveNetworkObserver(this);
277   notifier->RemoveNetworkPortalDetectorObserver(this);
278 }
279
280 views::View* TrayNetwork::CreateTrayView(user::LoginStatus status) {
281   CHECK(tray_ == NULL);
282   if (!chromeos::NetworkHandler::IsInitialized())
283     return NULL;
284   tray_ = new tray::NetworkTrayView(this);
285   return tray_;
286 }
287
288 views::View* TrayNetwork::CreateDefaultView(user::LoginStatus status) {
289   CHECK(default_ == NULL);
290   if (!chromeos::NetworkHandler::IsInitialized())
291     return NULL;
292   CHECK(tray_ != NULL);
293   default_ = new tray::NetworkDefaultView(
294       this, status != user::LOGGED_IN_LOCKED);
295   return default_;
296 }
297
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())
303     return NULL;
304   if (request_wifi_view_) {
305     detailed_ = new tray::NetworkWifiDetailedView(this);
306     request_wifi_view_ = false;
307   } else {
308     detailed_ = new tray::NetworkStateListDetailedView(
309         this, tray::NetworkStateListDetailedView::LIST_TYPE_NETWORK, status);
310     detailed_->Init();
311   }
312   return detailed_;
313 }
314
315 void TrayNetwork::DestroyTrayView() {
316   tray_ = NULL;
317 }
318
319 void TrayNetwork::DestroyDefaultView() {
320   default_ = NULL;
321 }
322
323 void TrayNetwork::DestroyDetailedView() {
324   detailed_ = NULL;
325 }
326
327 void TrayNetwork::UpdateAfterLoginStatusChange(user::LoginStatus status) {
328 }
329
330 void TrayNetwork::UpdateAfterShelfAlignmentChange(ShelfAlignment alignment) {
331   if (tray_) {
332     SetTrayImageItemBorder(tray_, alignment);
333     tray_->UpdateAlignment(alignment);
334   }
335 }
336
337 void TrayNetwork::RequestToggleWifi() {
338   // This will always be triggered by a user action (e.g. keyboard shortcut)
339   if (!detailed_ ||
340       detailed_->GetViewType() == tray::NetworkDetailedView::WIFI_VIEW) {
341     request_wifi_view_ = true;
342     PopupDetailedView(kTrayPopupAutoCloseDelayForTextInSeconds, false);
343   }
344   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
345   bool enabled = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi());
346   Shell::GetInstance()->metrics()->RecordUserMetricsAction(
347       enabled ?
348       ash::UMA_STATUS_AREA_DISABLE_WIFI :
349       ash::UMA_STATUS_AREA_ENABLE_WIFI);
350   handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
351                                 !enabled,
352                                 chromeos::network_handler::ErrorCallback());
353 }
354
355 void TrayNetwork::OnCaptivePortalDetected(
356     const std::string& /* service_path */) {
357   NetworkStateChanged(false);
358 }
359
360 void TrayNetwork::NetworkStateChanged(bool list_changed) {
361   if (tray_)
362     tray_->UpdateNetworkStateHandlerIcon();
363   if (default_)
364     default_->Update();
365   if (detailed_) {
366     if (list_changed)
367       detailed_->NetworkListChanged();
368     else
369       detailed_->ManagerChanged();
370   }
371 }
372
373 void TrayNetwork::NetworkServiceChanged(const chromeos::NetworkState* network) {
374   if (detailed_)
375     detailed_->NetworkServiceChanged(network);
376 }
377
378 }  // namespace ash