Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / ash / system / chromeos / network / network_state_list_detailed_view.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/network_state_list_detailed_view.h"
6
7 #include "ash/ash_switches.h"
8 #include "ash/metrics/user_metrics_recorder.h"
9 #include "ash/root_window_controller.h"
10 #include "ash/shell.h"
11 #include "ash/shell_delegate.h"
12 #include "ash/shell_window_ids.h"
13 #include "ash/system/chromeos/network/tray_network_state_observer.h"
14 #include "ash/system/tray/fixed_sized_scroll_view.h"
15 #include "ash/system/tray/hover_highlight_view.h"
16 #include "ash/system/tray/system_tray.h"
17 #include "ash/system/tray/system_tray_delegate.h"
18 #include "ash/system/tray/tray_constants.h"
19 #include "ash/system/tray/tray_details_view.h"
20 #include "ash/system/tray/tray_popup_header_button.h"
21 #include "ash/system/tray/tray_popup_label_button.h"
22 #include "base/command_line.h"
23 #include "base/message_loop/message_loop.h"
24 #include "base/strings/utf_string_conversions.h"
25 #include "base/time/time.h"
26 #include "chromeos/chromeos_switches.h"
27 #include "chromeos/network/device_state.h"
28 #include "chromeos/network/network_configuration_handler.h"
29 #include "chromeos/network/network_state.h"
30 #include "chromeos/network/network_state_handler.h"
31 #include "grit/ash_resources.h"
32 #include "grit/ash_strings.h"
33 #include "grit/ui_chromeos_strings.h"
34 #include "third_party/cros_system_api/dbus/service_constants.h"
35 #include "ui/aura/window.h"
36 #include "ui/base/l10n/l10n_util.h"
37 #include "ui/base/resource/resource_bundle.h"
38 #include "ui/chromeos/network/network_connect.h"
39 #include "ui/chromeos/network/network_icon.h"
40 #include "ui/chromeos/network/network_icon_animation.h"
41 #include "ui/chromeos/network/network_info.h"
42 #include "ui/views/bubble/bubble_delegate.h"
43 #include "ui/views/controls/label.h"
44 #include "ui/views/layout/box_layout.h"
45 #include "ui/views/layout/fill_layout.h"
46 #include "ui/views/widget/widget.h"
47
48 using chromeos::DeviceState;
49 using chromeos::NetworkHandler;
50 using chromeos::NetworkState;
51 using chromeos::NetworkStateHandler;
52 using chromeos::NetworkTypePattern;
53 using ui::NetworkInfo;
54
55 namespace ash {
56 namespace tray {
57 namespace {
58
59 // Delay between scan requests.
60 const int kRequestScanDelaySeconds = 10;
61
62 // Create a label with the font size and color used in the network info bubble.
63 views::Label* CreateInfoBubbleLabel(const base::string16& text) {
64   views::Label* label = new views::Label(text);
65   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
66   label->SetFontList(rb.GetFontList(ui::ResourceBundle::SmallFont));
67   label->SetEnabledColor(SkColorSetARGB(127, 0, 0, 0));
68   return label;
69 }
70
71 // Create a row of labels for the network info bubble.
72 views::View* CreateInfoBubbleLine(const base::string16& text_label,
73                                   const std::string& text_string) {
74   views::View* view = new views::View;
75   view->SetLayoutManager(
76       new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1));
77   view->AddChildView(CreateInfoBubbleLabel(text_label));
78   view->AddChildView(CreateInfoBubbleLabel(base::UTF8ToUTF16(": ")));
79   view->AddChildView(CreateInfoBubbleLabel(base::UTF8ToUTF16(text_string)));
80   return view;
81 }
82
83 }  // namespace
84
85
86 //------------------------------------------------------------------------------
87
88 // A bubble which displays network info.
89 class NetworkStateListDetailedView::InfoBubble
90     : public views::BubbleDelegateView {
91  public:
92   InfoBubble(views::View* anchor,
93              views::View* content,
94              NetworkStateListDetailedView* detailed_view)
95       : views::BubbleDelegateView(anchor, views::BubbleBorder::TOP_RIGHT),
96         detailed_view_(detailed_view) {
97     set_can_activate(false);
98     set_parent_window(ash::Shell::GetContainer(
99         anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
100         ash::kShellWindowId_SettingBubbleContainer));
101     SetLayoutManager(new views::FillLayout());
102     AddChildView(content);
103   }
104
105   virtual ~InfoBubble() {
106     detailed_view_->OnInfoBubbleDestroyed();
107   }
108
109  private:
110   // Not owned.
111   NetworkStateListDetailedView* detailed_view_;
112
113   DISALLOW_COPY_AND_ASSIGN(InfoBubble);
114 };
115
116 //------------------------------------------------------------------------------
117 // NetworkStateListDetailedView
118
119 NetworkStateListDetailedView::NetworkStateListDetailedView(
120     SystemTrayItem* owner,
121     ListType list_type,
122     user::LoginStatus login)
123     : NetworkDetailedView(owner),
124       list_type_(list_type),
125       login_(login),
126       info_icon_(NULL),
127       button_wifi_(NULL),
128       button_mobile_(NULL),
129       other_wifi_(NULL),
130       turn_on_wifi_(NULL),
131       other_mobile_(NULL),
132       other_vpn_(NULL),
133       settings_(NULL),
134       proxy_settings_(NULL),
135       info_bubble_(NULL),
136       network_list_view_(this) {
137 }
138
139 NetworkStateListDetailedView::~NetworkStateListDetailedView() {
140   if (info_bubble_)
141     info_bubble_->GetWidget()->CloseNow();
142 }
143
144 void NetworkStateListDetailedView::ManagerChanged() {
145   UpdateNetworkList();
146   UpdateHeaderButtons();
147   UpdateNetworkExtra();
148   Layout();
149 }
150
151 void NetworkStateListDetailedView::NetworkListChanged() {
152   UpdateNetworkList();
153   UpdateHeaderButtons();
154   UpdateNetworkExtra();
155   Layout();
156 }
157
158 void NetworkStateListDetailedView::NetworkServiceChanged(
159     const NetworkState* network) {
160   UpdateNetworkList();
161   Layout();
162 }
163
164 // Overridden from NetworkDetailedView:
165
166 void NetworkStateListDetailedView::Init() {
167   Reset();
168   info_icon_ = NULL;
169   button_wifi_ = NULL;
170   button_mobile_ = NULL;
171   other_wifi_ = NULL;
172   turn_on_wifi_ = NULL;
173   other_mobile_ = NULL;
174   other_vpn_ = NULL;
175   settings_ = NULL;
176   proxy_settings_ = NULL;
177
178   CreateScrollableList();
179   CreateNetworkExtra();
180   CreateHeaderEntry();
181   CreateHeaderButtons();
182
183   network_list_view_.set_content_view(scroll_content());
184   NetworkListChanged();
185
186   CallRequestScan();
187 }
188
189 NetworkDetailedView::DetailedViewType
190 NetworkStateListDetailedView::GetViewType() const {
191   return STATE_LIST_VIEW;
192 }
193
194 // Views overrides
195
196 void NetworkStateListDetailedView::ButtonPressed(views::Button* sender,
197                                                  const ui::Event& event) {
198   if (sender == info_icon_) {
199     ToggleInfoBubble();
200     return;
201   }
202
203   // If the info bubble was visible, close it when some other item is clicked.
204   ResetInfoBubble();
205
206   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
207   ash::SystemTrayDelegate* delegate =
208       ash::Shell::GetInstance()->system_tray_delegate();
209   if (sender == button_wifi_) {
210     bool enabled = handler->IsTechnologyEnabled(
211         NetworkTypePattern::WiFi());
212     handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
213                                   !enabled,
214                                   chromeos::network_handler::ErrorCallback());
215   } else if (sender == turn_on_wifi_) {
216     handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
217                                   true,
218                                   chromeos::network_handler::ErrorCallback());
219   } else if (sender == button_mobile_) {
220     ToggleMobile();
221   } else if (sender == settings_) {
222     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
223         list_type_ == LIST_TYPE_VPN ?
224         ash::UMA_STATUS_AREA_VPN_SETTINGS_CLICKED :
225         ash::UMA_STATUS_AREA_NETWORK_SETTINGS_CLICKED);
226     delegate->ShowNetworkSettings("");
227   } else if (sender == proxy_settings_) {
228     delegate->ChangeProxySettings();
229   } else if (sender == other_mobile_) {
230     delegate->ShowOtherNetworkDialog(shill::kTypeCellular);
231   } else if (sender == other_wifi_) {
232     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
233         ash::UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED);
234     delegate->ShowOtherNetworkDialog(shill::kTypeWifi);
235   } else if (sender == other_vpn_) {
236     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
237         ash::UMA_STATUS_AREA_VPN_JOIN_OTHER_CLICKED);
238     delegate->ShowOtherNetworkDialog(shill::kTypeVPN);
239   } else {
240     NOTREACHED();
241   }
242 }
243
244 void NetworkStateListDetailedView::OnViewClicked(views::View* sender) {
245   // If the info bubble was visible, close it when some other item is clicked.
246   ResetInfoBubble();
247
248   if (sender == footer()->content()) {
249     TransitionToDefaultView();
250     return;
251   }
252
253   if (login_ == user::LOGGED_IN_LOCKED)
254     return;
255
256   std::string service_path;
257   if (!network_list_view_.IsViewInList(sender, &service_path))
258     return;
259
260   const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
261       GetNetworkState(service_path);
262   if (!network || network->IsConnectedState() || network->IsConnectingState()) {
263     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
264         list_type_ == LIST_TYPE_VPN ?
265         ash::UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS :
266         ash::UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS);
267     Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
268         service_path);
269   } else {
270     Shell::GetInstance()->metrics()->RecordUserMetricsAction(
271         list_type_ == LIST_TYPE_VPN ?
272         ash::UMA_STATUS_AREA_CONNECT_TO_VPN :
273         ash::UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK);
274     ui::NetworkConnect::Get()->ConnectToNetwork(service_path);
275   }
276 }
277
278 // Create UI components.
279
280 void NetworkStateListDetailedView::CreateHeaderEntry() {
281   CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this);
282 }
283
284 void NetworkStateListDetailedView::CreateHeaderButtons() {
285   if (list_type_ != LIST_TYPE_VPN) {
286     button_wifi_ = new TrayPopupHeaderButton(
287         this,
288         IDR_AURA_UBER_TRAY_WIFI_ENABLED,
289         IDR_AURA_UBER_TRAY_WIFI_DISABLED,
290         IDR_AURA_UBER_TRAY_WIFI_ENABLED_HOVER,
291         IDR_AURA_UBER_TRAY_WIFI_DISABLED_HOVER,
292         IDS_ASH_STATUS_TRAY_WIFI);
293     button_wifi_->SetTooltipText(
294         l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_WIFI));
295     button_wifi_->SetToggledTooltipText(
296         l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_WIFI));
297     footer()->AddButton(button_wifi_);
298
299     button_mobile_ = new TrayPopupHeaderButton(
300         this,
301         IDR_AURA_UBER_TRAY_CELLULAR_ENABLED,
302         IDR_AURA_UBER_TRAY_CELLULAR_DISABLED,
303         IDR_AURA_UBER_TRAY_CELLULAR_ENABLED_HOVER,
304         IDR_AURA_UBER_TRAY_CELLULAR_DISABLED_HOVER,
305         IDS_ASH_STATUS_TRAY_CELLULAR);
306     button_mobile_->SetTooltipText(
307         l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_MOBILE));
308     button_mobile_->SetToggledTooltipText(
309         l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_MOBILE));
310     footer()->AddButton(button_mobile_);
311   }
312
313   info_icon_ = new TrayPopupHeaderButton(
314       this,
315       IDR_AURA_UBER_TRAY_NETWORK_INFO,
316       IDR_AURA_UBER_TRAY_NETWORK_INFO,
317       IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
318       IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
319       IDS_ASH_STATUS_TRAY_NETWORK_INFO);
320   info_icon_->SetTooltipText(
321       l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO));
322   footer()->AddButton(info_icon_);
323 }
324
325 void NetworkStateListDetailedView::CreateNetworkExtra() {
326   if (login_ == user::LOGGED_IN_LOCKED)
327     return;
328
329   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
330
331   views::View* bottom_row = new views::View();
332   views::BoxLayout* layout = new views::BoxLayout(
333       views::BoxLayout::kHorizontal,
334       kTrayMenuBottomRowPadding,
335       kTrayMenuBottomRowPadding,
336       kTrayMenuBottomRowPaddingBetweenItems);
337   layout->SetDefaultFlex(1);
338   bottom_row->SetLayoutManager(layout);
339
340   if (list_type_ != LIST_TYPE_VPN) {
341     other_wifi_ = new TrayPopupLabelButton(
342         this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_WIFI));
343     bottom_row->AddChildView(other_wifi_);
344
345     turn_on_wifi_ = new TrayPopupLabelButton(
346         this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_TURN_ON_WIFI));
347     bottom_row->AddChildView(turn_on_wifi_);
348
349     other_mobile_ = new TrayPopupLabelButton(
350         this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_MOBILE));
351     bottom_row->AddChildView(other_mobile_);
352   } else {
353     other_vpn_ = new TrayPopupLabelButton(
354         this,
355         ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
356             IDS_ASH_STATUS_TRAY_OTHER_VPN));
357     bottom_row->AddChildView(other_vpn_);
358   }
359
360   CreateSettingsEntry();
361
362   // Both settings_ and proxy_settings_ can be NULL. This happens when
363   // we're logged in but showing settings page is not enabled.
364   // Example: supervised user creation flow where user session is active
365   // but all action happens on the login window.
366   // Allowing opening proxy settigns dialog will break assumption in
367   //  SystemTrayDelegateChromeOS::ChangeProxySettings(), see CHECK.
368   if (settings_ || proxy_settings_)
369     bottom_row->AddChildView(settings_ ? settings_ : proxy_settings_);
370
371   AddChildView(bottom_row);
372 }
373
374 // Update UI components.
375
376 void NetworkStateListDetailedView::UpdateHeaderButtons() {
377   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
378   if (button_wifi_)
379     UpdateTechnologyButton(button_wifi_, NetworkTypePattern::WiFi());
380   if (button_mobile_) {
381     UpdateTechnologyButton(button_mobile_, NetworkTypePattern::Mobile());
382   }
383   if (proxy_settings_)
384     proxy_settings_->SetEnabled(handler->DefaultNetwork() != NULL);
385
386   static_cast<views::View*>(footer())->Layout();
387 }
388
389 void NetworkStateListDetailedView::UpdateTechnologyButton(
390     TrayPopupHeaderButton* button,
391     const NetworkTypePattern& technology) {
392   NetworkStateHandler::TechnologyState state =
393       NetworkHandler::Get()->network_state_handler()->GetTechnologyState(
394           technology);
395   if (state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
396     button->SetVisible(false);
397     return;
398   }
399   button->SetVisible(true);
400   if (state == NetworkStateHandler::TECHNOLOGY_AVAILABLE) {
401     button->SetEnabled(true);
402     button->SetToggled(true);
403   } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLED) {
404     button->SetEnabled(true);
405     button->SetToggled(false);
406   } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLING) {
407     button->SetEnabled(false);
408     button->SetToggled(false);
409   } else {  // Initializing
410     button->SetEnabled(false);
411     button->SetToggled(true);
412   }
413 }
414
415 void NetworkStateListDetailedView::UpdateNetworkList() {
416   network_list_view_.UpdateNetworkList();
417 }
418
419 bool NetworkStateListDetailedView::OrderChild(views::View* view, int index) {
420   if (scroll_content()->child_at(index) != view) {
421     scroll_content()->ReorderChildView(view, index);
422     return true;
423   }
424   return false;
425 }
426
427 void NetworkStateListDetailedView::UpdateNetworkExtra() {
428   if (login_ == user::LOGGED_IN_LOCKED)
429     return;
430
431   View* layout_parent = NULL;  // All these buttons have the same parent.
432   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
433   if (other_wifi_) {
434     DCHECK(turn_on_wifi_);
435     NetworkStateHandler::TechnologyState state =
436         handler->GetTechnologyState(NetworkTypePattern::WiFi());
437     if (state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
438       turn_on_wifi_->SetVisible(false);
439       other_wifi_->SetVisible(false);
440     } else {
441       if (state == NetworkStateHandler::TECHNOLOGY_AVAILABLE) {
442         turn_on_wifi_->SetVisible(true);
443         turn_on_wifi_->SetEnabled(true);
444         other_wifi_->SetVisible(false);
445       } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLED) {
446         turn_on_wifi_->SetVisible(false);
447         other_wifi_->SetVisible(true);
448       } else {
449         // Initializing or Enabling
450         turn_on_wifi_->SetVisible(true);
451         turn_on_wifi_->SetEnabled(false);
452         other_wifi_->SetVisible(false);
453       }
454     }
455     layout_parent = other_wifi_->parent();
456   }
457
458   if (other_mobile_) {
459     bool show_other_mobile = false;
460     NetworkStateHandler::TechnologyState state =
461         handler->GetTechnologyState(NetworkTypePattern::Mobile());
462     if (state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
463       const chromeos::DeviceState* device =
464           handler->GetDeviceStateByType(NetworkTypePattern::Mobile());
465       show_other_mobile = (device && device->support_network_scan());
466     }
467     if (show_other_mobile) {
468       other_mobile_->SetVisible(true);
469       other_mobile_->SetEnabled(
470           state == NetworkStateHandler::TECHNOLOGY_ENABLED);
471     } else {
472       other_mobile_->SetVisible(false);
473     }
474     if (!layout_parent)
475       layout_parent = other_wifi_->parent();
476   }
477
478   if (layout_parent)
479     layout_parent->Layout();
480 }
481
482 void NetworkStateListDetailedView::CreateSettingsEntry() {
483   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
484   bool show_settings = ash::Shell::GetInstance()->
485       system_tray_delegate()->ShouldShowSettings();
486   if (login_ != user::LOGGED_IN_NONE) {
487     // Allow user access settings only if user is logged in
488     // and showing settings is allowed. There're situations (supervised user
489     // creation flow) when session is started but UI flow continues within
490     // login UI i.e. no browser window is yet avaialable.
491     if (show_settings) {
492       settings_ = new TrayPopupLabelButton(
493           this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS));
494     }
495   } else  {
496     // Allow users to change proxy settings only when not logged in.
497     proxy_settings_ = new TrayPopupLabelButton(
498         this,
499         rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS));
500   }
501 }
502
503 void NetworkStateListDetailedView::ToggleInfoBubble() {
504   if (ResetInfoBubble())
505     return;
506
507   info_bubble_ = new InfoBubble(
508       info_icon_, CreateNetworkInfoView(), this);
509   views::BubbleDelegateView::CreateBubble(info_bubble_)->Show();
510 }
511
512 bool NetworkStateListDetailedView::ResetInfoBubble() {
513   if (!info_bubble_)
514     return false;
515   info_bubble_->GetWidget()->Close();
516   info_bubble_ = NULL;
517   return true;
518 }
519
520 void NetworkStateListDetailedView::OnInfoBubbleDestroyed() {
521   info_bubble_ = NULL;
522 }
523
524 views::View* NetworkStateListDetailedView::CreateNetworkInfoView() {
525   ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
526   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
527
528   std::string ip_address("0.0.0.0");
529   const NetworkState* network = handler->DefaultNetwork();
530   if (network)
531     ip_address = network->ip_address();
532
533   views::View* container = new views::View;
534   container->SetLayoutManager(
535       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
536   container->SetBorder(views::Border::CreateEmptyBorder(0, 5, 0, 5));
537
538   std::string ethernet_address, wifi_address, vpn_address;
539   if (list_type_ != LIST_TYPE_VPN) {
540     ethernet_address = handler->FormattedHardwareAddressForType(
541         NetworkTypePattern::Ethernet());
542     wifi_address =
543         handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi());
544   } else {
545     vpn_address =
546         handler->FormattedHardwareAddressForType(NetworkTypePattern::VPN());
547   }
548
549   if (!ip_address.empty()) {
550     container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
551         IDS_ASH_STATUS_TRAY_IP), ip_address));
552   }
553   if (!ethernet_address.empty()) {
554     container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
555         IDS_ASH_STATUS_TRAY_ETHERNET), ethernet_address));
556   }
557   if (!wifi_address.empty()) {
558     container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
559         IDS_ASH_STATUS_TRAY_WIFI), wifi_address));
560   }
561   if (!vpn_address.empty()) {
562     container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
563         IDS_ASH_STATUS_TRAY_VPN), vpn_address));
564   }
565
566   // Avoid an empty bubble in the unlikely event that there is no network
567   // information at all.
568   if (!container->has_children()) {
569     container->AddChildView(CreateInfoBubbleLabel(bundle.GetLocalizedString(
570         IDS_ASH_STATUS_TRAY_NO_NETWORKS)));
571   }
572
573   return container;
574 }
575
576 void NetworkStateListDetailedView::CallRequestScan() {
577   VLOG(1) << "Requesting Network Scan.";
578   NetworkHandler::Get()->network_state_handler()->RequestScan();
579   // Periodically request a scan while this UI is open.
580   base::MessageLoopForUI::current()->PostDelayedTask(
581       FROM_HERE,
582       base::Bind(&NetworkStateListDetailedView::CallRequestScan, AsWeakPtr()),
583       base::TimeDelta::FromSeconds(kRequestScanDelaySeconds));
584 }
585
586 void NetworkStateListDetailedView::ToggleMobile() {
587   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
588   bool enabled =
589       handler->IsTechnologyEnabled(NetworkTypePattern::Mobile());
590   ui::NetworkConnect::Get()->SetTechnologyEnabled(NetworkTypePattern::Mobile(),
591                                                   !enabled);
592 }
593
594 views::View* NetworkStateListDetailedView::CreateViewForNetwork(
595     const ui::NetworkInfo& info) {
596   gfx::Font::FontStyle font =
597       info.highlight ? gfx::Font::BOLD : gfx::Font::NORMAL;
598   HoverHighlightView* view = new HoverHighlightView(this);
599   view->AddIconAndLabel(info.image, info.label, font);
600   view->SetBorder(
601       views::Border::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal, 0, 0));
602   return view;
603 }
604
605 bool NetworkStateListDetailedView::IsViewHovered(views::View* view) {
606   return static_cast<HoverHighlightView*>(view)->hover();
607 }
608
609 NetworkTypePattern NetworkStateListDetailedView::GetNetworkTypePattern() const {
610   return list_type_ == LIST_TYPE_VPN ? NetworkTypePattern::VPN()
611                                      : NetworkTypePattern::NonVirtual();
612 }
613
614 void NetworkStateListDetailedView::UpdateViewForNetwork(
615     views::View* view,
616     const NetworkInfo& info) {
617   gfx::Font::FontStyle font =
618       info.highlight ? gfx::Font::BOLD : gfx::Font::NORMAL;
619   HoverHighlightView* highlight = static_cast<HoverHighlightView*>(view);
620   highlight->AddIconAndLabel(info.image, info.label, font);
621 }
622
623 views::Label* NetworkStateListDetailedView::CreateInfoLabel() {
624   views::Label* label = new views::Label();
625   label->SetBorder(
626       views::Border::CreateEmptyBorder(ash::kTrayPopupPaddingBetweenItems,
627                                        ash::kTrayPopupPaddingHorizontal,
628                                        ash::kTrayPopupPaddingBetweenItems,
629                                        0));
630   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
631   label->SetEnabledColor(SkColorSetARGB(192, 0, 0, 0));
632   return label;
633 }
634
635 void NetworkStateListDetailedView::RelayoutScrollList() {
636   scroller()->Layout();
637 }
638
639 }  // namespace tray
640 }  // namespace ash