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/network_state_list_detailed_view.h"
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/network_connect.h"
14 #include "ash/system/chromeos/network/network_icon.h"
15 #include "ash/system/chromeos/network/network_icon_animation.h"
16 #include "ash/system/chromeos/network/tray_network_state_observer.h"
17 #include "ash/system/tray/fixed_sized_scroll_view.h"
18 #include "ash/system/tray/hover_highlight_view.h"
19 #include "ash/system/tray/system_tray.h"
20 #include "ash/system/tray/system_tray_delegate.h"
21 #include "ash/system/tray/tray_constants.h"
22 #include "ash/system/tray/tray_details_view.h"
23 #include "ash/system/tray/tray_popup_header_button.h"
24 #include "ash/system/tray/tray_popup_label_button.h"
25 #include "base/command_line.h"
26 #include "base/message_loop/message_loop.h"
27 #include "base/strings/utf_string_conversions.h"
28 #include "base/time/time.h"
29 #include "chromeos/chromeos_switches.h"
30 #include "chromeos/network/device_state.h"
31 #include "chromeos/network/network_configuration_handler.h"
32 #include "chromeos/network/network_state.h"
33 #include "chromeos/network/network_state_handler.h"
34 #include "chromeos/network/shill_property_util.h"
35 #include "grit/ash_resources.h"
36 #include "grit/ash_strings.h"
37 #include "third_party/cros_system_api/dbus/service_constants.h"
38 #include "ui/aura/window.h"
39 #include "ui/base/l10n/l10n_util.h"
40 #include "ui/base/resource/resource_bundle.h"
41 #include "ui/views/bubble/bubble_delegate.h"
42 #include "ui/views/controls/label.h"
43 #include "ui/views/layout/box_layout.h"
44 #include "ui/views/layout/fill_layout.h"
45 #include "ui/views/widget/widget.h"
47 using chromeos::DeviceState;
48 using chromeos::NetworkHandler;
49 using chromeos::NetworkState;
50 using chromeos::NetworkStateHandler;
51 using chromeos::NetworkTypePattern;
59 // Delay between scan requests.
60 const int kRequestScanDelaySeconds = 10;
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));
71 // Create a label formatted for info items in the menu
72 views::Label* CreateMenuInfoLabel(const base::string16& text) {
73 views::Label* label = new views::Label(text);
75 views::Border::CreateEmptyBorder(ash::kTrayPopupPaddingBetweenItems,
76 ash::kTrayPopupPaddingHorizontal,
77 ash::kTrayPopupPaddingBetweenItems,
79 label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
80 label->SetEnabledColor(SkColorSetARGB(192, 0, 0, 0));
84 // Create a row of labels for the network info bubble.
85 views::View* CreateInfoBubbleLine(const base::string16& text_label,
86 const std::string& text_string) {
87 views::View* view = new views::View;
88 view->SetLayoutManager(
89 new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 1));
90 view->AddChildView(CreateInfoBubbleLabel(text_label));
91 view->AddChildView(CreateInfoBubbleLabel(base::UTF8ToUTF16(": ")));
92 view->AddChildView(CreateInfoBubbleLabel(base::UTF8ToUTF16(text_string)));
99 //------------------------------------------------------------------------------
102 NetworkInfo(const std::string& path)
103 : service_path(path),
108 std::string service_path;
109 base::string16 label;
110 gfx::ImageSkia image;
115 //------------------------------------------------------------------------------
117 // A bubble which displays network info.
118 class NetworkStateListDetailedView::InfoBubble
119 : public views::BubbleDelegateView {
121 InfoBubble(views::View* anchor,
122 views::View* content,
123 NetworkStateListDetailedView* detailed_view)
124 : views::BubbleDelegateView(anchor, views::BubbleBorder::TOP_RIGHT),
125 detailed_view_(detailed_view) {
126 set_use_focusless(true);
127 set_parent_window(ash::Shell::GetContainer(
128 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(),
129 ash::internal::kShellWindowId_SettingBubbleContainer));
130 SetLayoutManager(new views::FillLayout());
131 AddChildView(content);
134 virtual ~InfoBubble() {
135 detailed_view_->OnInfoBubbleDestroyed();
138 virtual bool CanActivate() const OVERRIDE { return false; }
142 NetworkStateListDetailedView* detailed_view_;
144 DISALLOW_COPY_AND_ASSIGN(InfoBubble);
147 //------------------------------------------------------------------------------
148 // NetworkStateListDetailedView
150 NetworkStateListDetailedView::NetworkStateListDetailedView(
151 SystemTrayItem* owner,
153 user::LoginStatus login)
154 : NetworkDetailedView(owner),
155 list_type_(list_type),
159 button_mobile_(NULL),
165 proxy_settings_(NULL),
166 scanning_view_(NULL),
167 no_wifi_networks_view_(NULL),
168 no_cellular_networks_view_(NULL),
172 NetworkStateListDetailedView::~NetworkStateListDetailedView() {
174 info_bubble_->GetWidget()->CloseNow();
175 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
178 void NetworkStateListDetailedView::ManagerChanged() {
180 UpdateHeaderButtons();
181 UpdateNetworkExtra();
185 void NetworkStateListDetailedView::NetworkListChanged() {
186 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
187 NetworkStateHandler::NetworkStateList network_list;
188 handler->GetNetworkList(&network_list);
189 UpdateNetworks(network_list);
191 UpdateHeaderButtons();
192 UpdateNetworkExtra();
196 void NetworkStateListDetailedView::NetworkServiceChanged(
197 const NetworkState* network) {
202 void NetworkStateListDetailedView::NetworkIconChanged() {
207 // Overridden from NetworkDetailedView:
209 void NetworkStateListDetailedView::Init() {
211 network_map_.clear();
212 service_path_map_.clear();
215 button_mobile_ = NULL;
217 turn_on_wifi_ = NULL;
218 other_mobile_ = NULL;
221 proxy_settings_ = NULL;
222 scanning_view_ = NULL;
223 no_wifi_networks_view_ = NULL;
224 no_cellular_networks_view_ = NULL;
226 CreateScrollableList();
227 CreateNetworkExtra();
229 CreateHeaderButtons();
231 NetworkListChanged();
236 NetworkDetailedView::DetailedViewType
237 NetworkStateListDetailedView::GetViewType() const {
238 return STATE_LIST_VIEW;
243 void NetworkStateListDetailedView::ButtonPressed(views::Button* sender,
244 const ui::Event& event) {
245 if (sender == info_icon_) {
250 // If the info bubble was visible, close it when some other item is clicked.
253 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
254 ash::SystemTrayDelegate* delegate =
255 ash::Shell::GetInstance()->system_tray_delegate();
256 if (sender == button_wifi_) {
257 bool enabled = handler->IsTechnologyEnabled(
258 NetworkTypePattern::WiFi());
259 handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
261 chromeos::network_handler::ErrorCallback());
262 } else if (sender == turn_on_wifi_) {
263 handler->SetTechnologyEnabled(NetworkTypePattern::WiFi(),
265 chromeos::network_handler::ErrorCallback());
266 } else if (sender == button_mobile_) {
268 } else if (sender == settings_) {
269 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
270 list_type_ == LIST_TYPE_VPN ?
271 ash::UMA_STATUS_AREA_VPN_SETTINGS_CLICKED :
272 ash::UMA_STATUS_AREA_NETWORK_SETTINGS_CLICKED);
273 delegate->ShowNetworkSettings("");
274 } else if (sender == proxy_settings_) {
275 delegate->ChangeProxySettings();
276 } else if (sender == other_mobile_) {
277 delegate->ShowOtherNetworkDialog(shill::kTypeCellular);
278 } else if (sender == other_wifi_) {
279 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
280 ash::UMA_STATUS_AREA_NETWORK_JOIN_OTHER_CLICKED);
281 delegate->ShowOtherNetworkDialog(shill::kTypeWifi);
282 } else if (sender == other_vpn_) {
283 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
284 ash::UMA_STATUS_AREA_VPN_JOIN_OTHER_CLICKED);
285 delegate->ShowOtherNetworkDialog(shill::kTypeVPN);
291 void NetworkStateListDetailedView::OnViewClicked(views::View* sender) {
292 // If the info bubble was visible, close it when some other item is clicked.
295 if (sender == footer()->content()) {
296 TransitionToDefaultView();
300 if (login_ == user::LOGGED_IN_LOCKED)
303 std::map<views::View*, std::string>::iterator found =
304 network_map_.find(sender);
305 if (found == network_map_.end())
308 const std::string& service_path = found->second;
309 const NetworkState* network = NetworkHandler::Get()->network_state_handler()->
310 GetNetworkState(service_path);
311 if (!network || network->IsConnectedState() || network->IsConnectingState()) {
312 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
313 list_type_ == LIST_TYPE_VPN ?
314 ash::UMA_STATUS_AREA_SHOW_NETWORK_CONNECTION_DETAILS :
315 ash::UMA_STATUS_AREA_SHOW_VPN_CONNECTION_DETAILS);
316 Shell::GetInstance()->system_tray_delegate()->ShowNetworkSettings(
319 Shell::GetInstance()->metrics()->RecordUserMetricsAction(
320 list_type_ == LIST_TYPE_VPN ?
321 ash::UMA_STATUS_AREA_CONNECT_TO_VPN :
322 ash::UMA_STATUS_AREA_CONNECT_TO_CONFIGURED_NETWORK);
323 ash::network_connect::ConnectToNetwork(service_path, NULL);
327 // Create UI components.
329 void NetworkStateListDetailedView::CreateHeaderEntry() {
330 CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this);
333 void NetworkStateListDetailedView::CreateHeaderButtons() {
334 if (list_type_ != LIST_TYPE_VPN) {
335 button_wifi_ = new TrayPopupHeaderButton(
337 IDR_AURA_UBER_TRAY_WIFI_ENABLED,
338 IDR_AURA_UBER_TRAY_WIFI_DISABLED,
339 IDR_AURA_UBER_TRAY_WIFI_ENABLED_HOVER,
340 IDR_AURA_UBER_TRAY_WIFI_DISABLED_HOVER,
341 IDS_ASH_STATUS_TRAY_WIFI);
342 button_wifi_->SetTooltipText(
343 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_WIFI));
344 button_wifi_->SetToggledTooltipText(
345 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_WIFI));
346 footer()->AddButton(button_wifi_);
348 button_mobile_ = new TrayPopupHeaderButton(
350 IDR_AURA_UBER_TRAY_CELLULAR_ENABLED,
351 IDR_AURA_UBER_TRAY_CELLULAR_DISABLED,
352 IDR_AURA_UBER_TRAY_CELLULAR_ENABLED_HOVER,
353 IDR_AURA_UBER_TRAY_CELLULAR_DISABLED_HOVER,
354 IDS_ASH_STATUS_TRAY_CELLULAR);
355 button_mobile_->SetTooltipText(
356 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_DISABLE_MOBILE));
357 button_mobile_->SetToggledTooltipText(
358 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_ENABLE_MOBILE));
359 footer()->AddButton(button_mobile_);
362 info_icon_ = new TrayPopupHeaderButton(
364 IDR_AURA_UBER_TRAY_NETWORK_INFO,
365 IDR_AURA_UBER_TRAY_NETWORK_INFO,
366 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
367 IDR_AURA_UBER_TRAY_NETWORK_INFO_HOVER,
368 IDS_ASH_STATUS_TRAY_NETWORK_INFO);
369 info_icon_->SetTooltipText(
370 l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_NETWORK_INFO));
371 footer()->AddButton(info_icon_);
374 void NetworkStateListDetailedView::CreateNetworkExtra() {
375 if (login_ == user::LOGGED_IN_LOCKED)
378 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
380 views::View* bottom_row = new views::View();
381 views::BoxLayout* layout = new views::BoxLayout(
382 views::BoxLayout::kHorizontal,
383 kTrayMenuBottomRowPadding,
384 kTrayMenuBottomRowPadding,
385 kTrayMenuBottomRowPaddingBetweenItems);
386 layout->set_spread_blank_space(true);
387 bottom_row->SetLayoutManager(layout);
389 if (list_type_ != LIST_TYPE_VPN) {
390 other_wifi_ = new TrayPopupLabelButton(
391 this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_WIFI));
392 bottom_row->AddChildView(other_wifi_);
394 turn_on_wifi_ = new TrayPopupLabelButton(
395 this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_TURN_ON_WIFI));
396 bottom_row->AddChildView(turn_on_wifi_);
398 other_mobile_ = new TrayPopupLabelButton(
399 this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_OTHER_MOBILE));
400 bottom_row->AddChildView(other_mobile_);
402 other_vpn_ = new TrayPopupLabelButton(
404 ui::ResourceBundle::GetSharedInstance().GetLocalizedString(
405 IDS_ASH_STATUS_TRAY_OTHER_VPN));
406 bottom_row->AddChildView(other_vpn_);
409 CreateSettingsEntry();
411 // Both settings_ and proxy_settings_ can be NULL. This happens when
412 // we're logged in but showing settings page is not enabled.
413 // Example: supervised user creation flow where user session is active
414 // but all action happens on the login window.
415 // Allowing opening proxy settigns dialog will break assumption in
416 // SystemTrayDelegateChromeOS::ChangeProxySettings(), see CHECK.
417 if (settings_ || proxy_settings_)
418 bottom_row->AddChildView(settings_ ? settings_ : proxy_settings_);
420 AddChildView(bottom_row);
423 // Update UI components.
425 void NetworkStateListDetailedView::UpdateHeaderButtons() {
426 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
428 UpdateTechnologyButton(button_wifi_, NetworkTypePattern::WiFi());
429 if (button_mobile_) {
430 UpdateTechnologyButton(button_mobile_, NetworkTypePattern::Mobile());
433 proxy_settings_->SetEnabled(handler->DefaultNetwork() != NULL);
435 static_cast<views::View*>(footer())->Layout();
438 void NetworkStateListDetailedView::UpdateTechnologyButton(
439 TrayPopupHeaderButton* button,
440 const NetworkTypePattern& technology) {
441 NetworkStateHandler::TechnologyState state =
442 NetworkHandler::Get()->network_state_handler()->GetTechnologyState(
444 if (state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
445 button->SetVisible(false);
448 button->SetVisible(true);
449 if (state == NetworkStateHandler::TECHNOLOGY_AVAILABLE) {
450 button->SetEnabled(true);
451 button->SetToggled(true);
452 } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLED) {
453 button->SetEnabled(true);
454 button->SetToggled(false);
455 } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLING) {
456 button->SetEnabled(false);
457 button->SetToggled(false);
458 } else { // Initializing
459 button->SetEnabled(false);
460 button->SetToggled(true);
464 void NetworkStateListDetailedView::UpdateNetworks(
465 const NetworkStateHandler::NetworkStateList& networks) {
466 network_list_.clear();
467 for (NetworkStateHandler::NetworkStateList::const_iterator iter =
468 networks.begin(); iter != networks.end(); ++iter) {
469 const NetworkState* network = *iter;
470 if ((list_type_ == LIST_TYPE_NETWORK &&
471 network->type() != shill::kTypeVPN) ||
472 (list_type_ == LIST_TYPE_VPN &&
473 network->type() == shill::kTypeVPN)) {
474 NetworkInfo* info = new NetworkInfo(network->path());
475 network_list_.push_back(info);
480 void NetworkStateListDetailedView::UpdateNetworkList() {
481 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
483 // First, update state for all networks
484 bool animating = false;
485 for (size_t i = 0; i < network_list_.size(); ++i) {
486 NetworkInfo* info = network_list_[i];
487 const NetworkState* network =
488 handler->GetNetworkState(info->service_path);
491 info->image = network_icon::GetImageForNetwork(
492 network, network_icon::ICON_TYPE_LIST);
493 info->label = network_icon::GetLabelForNetwork(
494 network, network_icon::ICON_TYPE_LIST);
496 network->IsConnectedState() || network->IsConnectingState();
498 network->activation_state() == shill::kActivationStateActivating;
499 if (!animating && network->IsConnectingState())
503 network_icon::NetworkIconAnimation::GetInstance()->AddObserver(this);
505 network_icon::NetworkIconAnimation::GetInstance()->RemoveObserver(this);
507 // Get the updated list entries
508 network_map_.clear();
509 std::set<std::string> new_service_paths;
510 bool needs_relayout = UpdateNetworkListEntries(&new_service_paths);
512 // Remove old children
513 std::set<std::string> remove_service_paths;
514 for (ServicePathMap::const_iterator it = service_path_map_.begin();
515 it != service_path_map_.end(); ++it) {
516 if (new_service_paths.find(it->first) == new_service_paths.end()) {
517 remove_service_paths.insert(it->first);
518 network_map_.erase(it->second);
519 scroll_content()->RemoveChildView(it->second);
520 needs_relayout = true;
524 for (std::set<std::string>::const_iterator remove_it =
525 remove_service_paths.begin();
526 remove_it != remove_service_paths.end(); ++remove_it) {
527 service_path_map_.erase(*remove_it);
530 if (needs_relayout) {
531 views::View* selected_view = NULL;
532 for (ServicePathMap::const_iterator iter = service_path_map_.begin();
533 iter != service_path_map_.end(); ++iter) {
534 if (iter->second->hover()) {
535 selected_view = iter->second;
539 scroll_content()->SizeToPreferredSize();
540 static_cast<views::View*>(scroller())->Layout();
542 scroll_content()->ScrollRectToVisible(selected_view->bounds());
546 bool NetworkStateListDetailedView::CreateOrUpdateInfoLabel(
547 int index, const base::string16& text, views::Label** label) {
548 if (*label == NULL) {
549 *label = CreateMenuInfoLabel(text);
550 scroll_content()->AddChildViewAt(*label, index);
553 (*label)->SetText(text);
554 return OrderChild(*label, index);
558 bool NetworkStateListDetailedView::UpdateNetworkChild(int index,
559 const NetworkInfo* info) {
560 bool needs_relayout = false;
561 HoverHighlightView* container = NULL;
562 ServicePathMap::const_iterator found =
563 service_path_map_.find(info->service_path);
564 gfx::Font::FontStyle font =
565 info->highlight ? gfx::Font::BOLD : gfx::Font::NORMAL;
566 if (found == service_path_map_.end()) {
567 container = new HoverHighlightView(this);
568 container->AddIconAndLabel(info->image, info->label, font);
569 scroll_content()->AddChildViewAt(container, index);
570 container->SetBorder(
571 views::Border::CreateEmptyBorder(0, kTrayPopupPaddingHorizontal, 0, 0));
572 needs_relayout = true;
574 container = found->second;
575 container->RemoveAllChildViews(true);
576 container->AddIconAndLabel(info->image, info->label, font);
578 container->SchedulePaint();
579 needs_relayout = OrderChild(container, index);
582 container->SetEnabled(false);
583 network_map_[container] = info->service_path;
584 service_path_map_[info->service_path] = container;
585 return needs_relayout;
588 bool NetworkStateListDetailedView::OrderChild(views::View* view, int index) {
589 if (scroll_content()->child_at(index) != view) {
590 scroll_content()->ReorderChildView(view, index);
596 bool NetworkStateListDetailedView::UpdateNetworkListEntries(
597 std::set<std::string>* new_service_paths) {
598 bool needs_relayout = false;
599 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
600 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
602 // Insert child views
605 // Highlighted networks
606 for (size_t i = 0; i < network_list_.size(); ++i) {
607 const NetworkInfo* info = network_list_[i];
608 if (info->highlight) {
609 if (UpdateNetworkChild(index++, info))
610 needs_relayout = true;
611 new_service_paths->insert(info->service_path);
615 if (list_type_ == LIST_TYPE_NETWORK) {
616 // Cellular initializing
617 int status_message_id = network_icon::GetCellularUninitializedMsg();
618 if (!status_message_id &&
619 handler->IsTechnologyEnabled(NetworkTypePattern::Mobile()) &&
620 !handler->FirstNetworkByType(NetworkTypePattern::Mobile())) {
621 status_message_id = IDS_ASH_STATUS_TRAY_NO_CELLULAR_NETWORKS;
623 if (status_message_id) {
624 base::string16 text = rb.GetLocalizedString(status_message_id);
625 if (CreateOrUpdateInfoLabel(index++, text, &no_cellular_networks_view_))
626 needs_relayout = true;
627 } else if (no_cellular_networks_view_) {
628 scroll_content()->RemoveChildView(no_cellular_networks_view_);
629 no_cellular_networks_view_ = NULL;
630 needs_relayout = true;
633 // "Wifi Enabled / Disabled"
634 if (network_list_.empty()) {
635 int message_id = handler->IsTechnologyEnabled(NetworkTypePattern::WiFi())
636 ? IDS_ASH_STATUS_TRAY_NETWORK_WIFI_ENABLED
637 : IDS_ASH_STATUS_TRAY_NETWORK_WIFI_DISABLED;
638 base::string16 text = rb.GetLocalizedString(message_id);
639 if (CreateOrUpdateInfoLabel(index++, text, &no_wifi_networks_view_))
640 needs_relayout = true;
641 } else if (no_wifi_networks_view_) {
642 scroll_content()->RemoveChildView(no_wifi_networks_view_);
643 no_wifi_networks_view_ = NULL;
644 needs_relayout = true;
648 if (handler->GetScanningByType(NetworkTypePattern::WiFi())) {
649 base::string16 text =
650 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE);
651 if (CreateOrUpdateInfoLabel(index++, text, &scanning_view_))
652 needs_relayout = true;
653 } else if (scanning_view_ != NULL) {
654 scroll_content()->RemoveChildView(scanning_view_);
655 scanning_view_ = NULL;
656 needs_relayout = true;
660 // Un-highlighted networks
661 for (size_t i = 0; i < network_list_.size(); ++i) {
662 const NetworkInfo* info = network_list_[i];
663 if (!info->highlight) {
664 if (UpdateNetworkChild(index++, info))
665 needs_relayout = true;
666 new_service_paths->insert(info->service_path);
670 // No networks or other messages (fallback)
673 if (list_type_ == LIST_TYPE_VPN)
674 text = rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_NO_VPN);
676 text = rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NO_NETWORKS);
677 if (CreateOrUpdateInfoLabel(index++, text, &scanning_view_))
678 needs_relayout = true;
681 return needs_relayout;
684 void NetworkStateListDetailedView::UpdateNetworkExtra() {
685 if (login_ == user::LOGGED_IN_LOCKED)
688 View* layout_parent = NULL; // All these buttons have the same parent.
689 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
691 DCHECK(turn_on_wifi_);
692 NetworkStateHandler::TechnologyState state =
693 handler->GetTechnologyState(NetworkTypePattern::WiFi());
694 if (state == NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
695 turn_on_wifi_->SetVisible(false);
696 other_wifi_->SetVisible(false);
698 if (state == NetworkStateHandler::TECHNOLOGY_AVAILABLE) {
699 turn_on_wifi_->SetVisible(true);
700 turn_on_wifi_->SetEnabled(true);
701 other_wifi_->SetVisible(false);
702 } else if (state == NetworkStateHandler::TECHNOLOGY_ENABLED) {
703 turn_on_wifi_->SetVisible(false);
704 other_wifi_->SetVisible(true);
706 // Initializing or Enabling
707 turn_on_wifi_->SetVisible(true);
708 turn_on_wifi_->SetEnabled(false);
709 other_wifi_->SetVisible(false);
712 layout_parent = other_wifi_->parent();
716 bool show_other_mobile = false;
717 NetworkStateHandler::TechnologyState state =
718 handler->GetTechnologyState(NetworkTypePattern::Mobile());
719 if (state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE) {
720 const chromeos::DeviceState* device =
721 handler->GetDeviceStateByType(NetworkTypePattern::Mobile());
722 show_other_mobile = (device && device->support_network_scan());
724 if (show_other_mobile) {
725 other_mobile_->SetVisible(true);
726 other_mobile_->SetEnabled(
727 state == NetworkStateHandler::TECHNOLOGY_ENABLED);
729 other_mobile_->SetVisible(false);
732 layout_parent = other_wifi_->parent();
736 layout_parent->Layout();
739 void NetworkStateListDetailedView::CreateSettingsEntry() {
740 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
741 bool show_settings = ash::Shell::GetInstance()->
742 system_tray_delegate()->ShouldShowSettings();
743 if (login_ != user::LOGGED_IN_NONE) {
744 // Allow user access settings only if user is logged in
745 // and showing settings is allowed. There're situations (supervised user
746 // creation flow) when session is started but UI flow continues within
747 // login UI i.e. no browser window is yet avaialable.
749 settings_ = new TrayPopupLabelButton(
750 this, rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_SETTINGS));
753 // Allow users to change proxy settings only when not logged in.
754 proxy_settings_ = new TrayPopupLabelButton(
756 rb.GetLocalizedString(IDS_ASH_STATUS_TRAY_NETWORK_PROXY_SETTINGS));
760 void NetworkStateListDetailedView::ToggleInfoBubble() {
761 if (ResetInfoBubble())
764 info_bubble_ = new InfoBubble(
765 info_icon_, CreateNetworkInfoView(), this);
766 views::BubbleDelegateView::CreateBubble(info_bubble_)->Show();
769 bool NetworkStateListDetailedView::ResetInfoBubble() {
772 info_bubble_->GetWidget()->Close();
777 void NetworkStateListDetailedView::OnInfoBubbleDestroyed() {
781 views::View* NetworkStateListDetailedView::CreateNetworkInfoView() {
782 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
783 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
785 std::string ip_address("0.0.0.0");
786 const NetworkState* network = handler->DefaultNetwork();
788 ip_address = network->ip_address();
790 views::View* container = new views::View;
791 container->SetLayoutManager(
792 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
793 container->SetBorder(views::Border::CreateEmptyBorder(0, 5, 0, 5));
795 std::string ethernet_address, wifi_address, vpn_address;
796 if (list_type_ != LIST_TYPE_VPN) {
797 ethernet_address = handler->FormattedHardwareAddressForType(
798 NetworkTypePattern::Ethernet());
800 handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi());
803 handler->FormattedHardwareAddressForType(NetworkTypePattern::VPN());
806 if (!ip_address.empty()) {
807 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
808 IDS_ASH_STATUS_TRAY_IP), ip_address));
810 if (!ethernet_address.empty()) {
811 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
812 IDS_ASH_STATUS_TRAY_ETHERNET), ethernet_address));
814 if (!wifi_address.empty()) {
815 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
816 IDS_ASH_STATUS_TRAY_WIFI), wifi_address));
818 if (!vpn_address.empty()) {
819 container->AddChildView(CreateInfoBubbleLine(bundle.GetLocalizedString(
820 IDS_ASH_STATUS_TRAY_VPN), vpn_address));
823 // Avoid an empty bubble in the unlikely event that there is no network
824 // information at all.
825 if (!container->has_children()) {
826 container->AddChildView(CreateInfoBubbleLabel(bundle.GetLocalizedString(
827 IDS_ASH_STATUS_TRAY_NO_NETWORKS)));
833 void NetworkStateListDetailedView::CallRequestScan() {
834 VLOG(1) << "Requesting Network Scan.";
835 NetworkHandler::Get()->network_state_handler()->RequestScan();
836 // Periodically request a scan while this UI is open.
837 base::MessageLoopForUI::current()->PostDelayedTask(
839 base::Bind(&NetworkStateListDetailedView::CallRequestScan, AsWeakPtr()),
840 base::TimeDelta::FromSeconds(kRequestScanDelaySeconds));
843 void NetworkStateListDetailedView::ToggleMobile() {
844 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
846 handler->IsTechnologyEnabled(NetworkTypePattern::Mobile());
847 ash::network_connect::SetTechnologyEnabled(NetworkTypePattern::Mobile(),
852 } // namespace internal