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/network_connect.h" 14#include "ash/system/chromeos/network/tray_network_state_observer.h" 15#include "ash/system/tray/fixed_sized_scroll_view.h" 16#include "ash/system/tray/hover_highlight_view.h" 17#include "ash/system/tray/system_tray.h" 18#include "ash/system/tray/system_tray_delegate.h" 19#include "ash/system/tray/tray_constants.h" 20#include "ash/system/tray/tray_details_view.h" 21#include "ash/system/tray/tray_popup_header_button.h" 22#include "ash/system/tray/tray_popup_label_button.h" 23#include "base/command_line.h" 24#include "base/message_loop/message_loop.h" 25#include "base/strings/utf_string_conversions.h" 26#include "base/time/time.h" 27#include "chromeos/chromeos_switches.h" 28#include "chromeos/network/device_state.h" 29#include "chromeos/network/network_configuration_handler.h" 30#include "chromeos/network/network_state.h" 31#include "chromeos/network/network_state_handler.h" 32#include "grit/ash_resources.h" 33#include "grit/ash_strings.h" 34#include "grit/ui_chromeos_strings.h" 35#include "third_party/cros_system_api/dbus/service_constants.h" 36#include "ui/aura/window.h" 37#include "ui/base/l10n/l10n_util.h" 38#include "ui/base/resource/resource_bundle.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 48using chromeos::DeviceState; 49using chromeos::NetworkHandler; 50using chromeos::NetworkState; 51using chromeos::NetworkStateHandler; 52using chromeos::NetworkTypePattern; 53using ui::NetworkInfo; 54 55namespace ash { 56namespace tray { 57namespace { 58 59// Delay between scan requests. 60const int kRequestScanDelaySeconds = 10; 61 62// Create a label with the font size and color used in the network info bubble. 63views::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. 72views::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. 89class 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 119NetworkStateListDetailedView::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 139NetworkStateListDetailedView::~NetworkStateListDetailedView() { 140 if (info_bubble_) 141 info_bubble_->GetWidget()->CloseNow(); 142} 143 144void NetworkStateListDetailedView::ManagerChanged() { 145 UpdateNetworkList(); 146 UpdateHeaderButtons(); 147 UpdateNetworkExtra(); 148 Layout(); 149} 150 151void NetworkStateListDetailedView::NetworkListChanged() { 152 UpdateNetworkList(); 153 UpdateHeaderButtons(); 154 UpdateNetworkExtra(); 155 Layout(); 156} 157 158void NetworkStateListDetailedView::NetworkServiceChanged( 159 const NetworkState* network) { 160 UpdateNetworkList(); 161 Layout(); 162} 163 164// Overridden from NetworkDetailedView: 165 166void 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 189NetworkDetailedView::DetailedViewType 190NetworkStateListDetailedView::GetViewType() const { 191 return STATE_LIST_VIEW; 192} 193 194// Views overrides 195 196void 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 244void 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 ash::network_connect::ConnectToNetwork(service_path); 275 } 276} 277 278// Create UI components. 279 280void NetworkStateListDetailedView::CreateHeaderEntry() { 281 CreateSpecialRow(IDS_ASH_STATUS_TRAY_NETWORK, this); 282} 283 284void 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 325void 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 376void 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 389void 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 415void NetworkStateListDetailedView::UpdateNetworkList() { 416 network_list_view_.UpdateNetworkList(); 417} 418 419bool 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 427void 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 482void 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 503void 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 512bool NetworkStateListDetailedView::ResetInfoBubble() { 513 if (!info_bubble_) 514 return false; 515 info_bubble_->GetWidget()->Close(); 516 info_bubble_ = NULL; 517 return true; 518} 519 520void NetworkStateListDetailedView::OnInfoBubbleDestroyed() { 521 info_bubble_ = NULL; 522} 523 524views::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 576void 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 586void NetworkStateListDetailedView::ToggleMobile() { 587 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 588 bool enabled = 589 handler->IsTechnologyEnabled(NetworkTypePattern::Mobile()); 590 ash::network_connect::SetTechnologyEnabled(NetworkTypePattern::Mobile(), 591 !enabled); 592} 593 594views::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 605bool NetworkStateListDetailedView::IsViewHovered(views::View* view) { 606 return static_cast<HoverHighlightView*>(view)->hover(); 607} 608 609NetworkTypePattern NetworkStateListDetailedView::GetNetworkTypePattern() const { 610 return list_type_ == LIST_TYPE_VPN ? NetworkTypePattern::VPN() 611 : NetworkTypePattern::NonVirtual(); 612} 613 614void 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 623views::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 635void NetworkStateListDetailedView::RelayoutScrollList() { 636 scroller()->Layout(); 637} 638 639} // namespace tray 640} // namespace ash 641