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 "chrome/browser/chromeos/status/network_menu.h" 6 7#include <algorithm> 8 9#include "ash/shell.h" 10#include "ash/shell_delegate.h" 11#include "ash/system/chromeos/network/network_connect.h" 12#include "ash/system/chromeos/network/network_icon.h" 13#include "base/bind.h" 14#include "base/logging.h" 15#include "base/strings/stringprintf.h" 16#include "base/strings/utf_string_conversions.h" 17#include "chrome/browser/chromeos/choose_mobile_network_dialog.h" 18#include "chrome/browser/chromeos/login/user_manager.h" 19#include "chrome/browser/chromeos/mobile_config.h" 20#include "chrome/browser/chromeos/options/network_config_view.h" 21#include "chrome/browser/chromeos/sim_dialog_delegate.h" 22#include "chrome/browser/defaults.h" 23#include "chrome/browser/profiles/profile_manager.h" 24#include "chrome/common/url_constants.h" 25#include "chromeos/network/device_state.h" 26#include "chromeos/network/network_state.h" 27#include "chromeos/network/network_state_handler.h" 28#include "chromeos/network/shill_property_util.h" 29#include "grit/ash_resources.h" 30#include "grit/ash_strings.h" 31#include "grit/generated_resources.h" 32#include "third_party/cros_system_api/dbus/service_constants.h" 33#include "ui/base/l10n/l10n_util.h" 34#include "ui/base/models/menu_model.h" 35#include "ui/base/resource/resource_bundle.h" 36#include "ui/gfx/image/image_skia.h" 37 38namespace chromeos { 39 40namespace { 41 42// Offsets for views menu ids (main menu and submenu ids use the same 43// namespace). 44const int kMainIndexMask = 0x1000; 45const int kMoreIndexMask = 0x4000; 46 47// Replace '&' in a string with "&&" to allow it to be a menu item label. 48std::string EscapeAmpersands(const std::string& input) { 49 std::string str = input; 50 size_t found = str.find('&'); 51 while (found != std::string::npos) { 52 str.replace(found, 1, "&&"); 53 found = str.find('&', found + 2); 54 } 55 return str; 56} 57 58// Highlight any connected or connecting networks in the UI. 59bool ShouldHighlightNetwork(const NetworkState* network) { 60 return network->IsConnectedState() || network->IsConnectingState(); 61} 62 63void ToggleTechnology(const NetworkTypePattern& technology) { 64 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 65 bool is_enabled = handler->IsTechnologyEnabled(technology); 66 ash::network_connect::SetTechnologyEnabled(technology, !is_enabled); 67} 68 69} // namespace 70 71class NetworkMenuModel : public ui::MenuModel { 72 public: 73 struct MenuItem { 74 MenuItem() 75 : type(ui::MenuModel::TYPE_SEPARATOR), 76 sub_menu_model(NULL), 77 flags(0) { 78 } 79 MenuItem(ui::MenuModel::ItemType type, base::string16 label, gfx::ImageSkia icon, 80 const std::string& service_path, int flags) 81 : type(type), 82 label(label), 83 icon(icon), 84 service_path(service_path), 85 sub_menu_model(NULL), 86 flags(flags) { 87 } 88 MenuItem(ui::MenuModel::ItemType type, base::string16 label, gfx::ImageSkia icon, 89 NetworkMenuModel* sub_menu_model, int flags) 90 : type(type), 91 label(label), 92 icon(icon), 93 sub_menu_model(sub_menu_model), 94 flags(flags) { 95 } 96 97 ui::MenuModel::ItemType type; 98 base::string16 label; 99 gfx::ImageSkia icon; 100 std::string service_path; 101 NetworkMenuModel* sub_menu_model; // Weak ptr. 102 int flags; 103 }; 104 typedef std::vector<MenuItem> MenuItemVector; 105 106 explicit NetworkMenuModel(const base::WeakPtr<NetworkMenu>& owner) 107 : owner_(owner) {} 108 virtual ~NetworkMenuModel() {} 109 110 // Connect or reconnect to the network at |index|. 111 void ConnectToNetworkAt(int index); 112 113 // Called by NetworkMenu::UpdateMenu to initialize menu items. 114 virtual void InitMenuItems(bool should_open_button_options) = 0; 115 116 // Menu item field accessors. 117 const MenuItemVector& menu_items() const { return menu_items_; } 118 119 // ui::MenuModel implementation 120 // GetCommandIdAt() must be implemented by subclasses. 121 virtual bool HasIcons() const OVERRIDE; 122 virtual int GetItemCount() const OVERRIDE; 123 virtual ui::MenuModel::ItemType GetTypeAt(int index) const OVERRIDE; 124 virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE; 125 virtual base::string16 GetLabelAt(int index) const OVERRIDE; 126 virtual bool IsItemDynamicAt(int index) const OVERRIDE; 127 virtual const gfx::Font* GetLabelFontAt(int index) const OVERRIDE; 128 virtual bool GetAcceleratorAt(int index, 129 ui::Accelerator* accelerator) const OVERRIDE; 130 virtual bool IsItemCheckedAt(int index) const OVERRIDE; 131 virtual int GetGroupIdAt(int index) const OVERRIDE; 132 virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE; 133 virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt( 134 int index) const OVERRIDE; 135 virtual bool IsEnabledAt(int index) const OVERRIDE; 136 virtual bool IsVisibleAt(int index) const OVERRIDE; 137 virtual ui::MenuModel* GetSubmenuModelAt(int index) const OVERRIDE; 138 virtual void HighlightChangedTo(int index) OVERRIDE; 139 virtual void ActivatedAt(int index) OVERRIDE; 140 virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) OVERRIDE; 141 virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE; 142 143 protected: 144 enum MenuItemFlags { 145 FLAG_NONE = 0, 146 FLAG_DISABLED = 1 << 0, 147 FLAG_TOGGLE_WIFI = 1 << 2, 148 FLAG_TOGGLE_MOBILE = 1 << 3, 149 FLAG_ASSOCIATED = 1 << 5, 150 FLAG_ETHERNET = 1 << 6, 151 FLAG_WIFI = 1 << 7, 152 FLAG_WIMAX = 1 << 8, 153 FLAG_CELLULAR = 1 << 9, 154 FLAG_OPTIONS = 1 << 10, 155 FLAG_ADD_WIFI = 1 << 11, 156 FLAG_ADD_CELLULAR = 1 << 12, 157 }; 158 159 // Our menu items. 160 MenuItemVector menu_items_; 161 162 // Weak pointer to NetworkMenu that owns this MenuModel. 163 base::WeakPtr<NetworkMenu> owner_; 164 165 private: 166 // Open a dialog to set up and connect to a network. 167 void ShowOther(const std::string& type) const; 168 169 DISALLOW_COPY_AND_ASSIGN(NetworkMenuModel); 170}; 171 172class MoreMenuModel : public NetworkMenuModel { 173 public: 174 explicit MoreMenuModel(const base::WeakPtr<NetworkMenu> owner) 175 : NetworkMenuModel(owner) {} 176 virtual ~MoreMenuModel() {} 177 178 // NetworkMenuModel implementation. 179 virtual void InitMenuItems(bool should_open_button_options) OVERRIDE; 180 181 // ui::MenuModel implementation 182 virtual int GetCommandIdAt(int index) const OVERRIDE; 183 184 private: 185 DISALLOW_COPY_AND_ASSIGN(MoreMenuModel); 186}; 187 188class MainMenuModel : public NetworkMenuModel { 189 public: 190 explicit MainMenuModel(const base::WeakPtr<NetworkMenu>& owner) 191 : NetworkMenuModel(owner), 192 more_menu_model_(new MoreMenuModel(owner)) { 193 } 194 virtual ~MainMenuModel() {} 195 196 // NetworkMenuModel implementation. 197 virtual void InitMenuItems(bool should_open_button_options) OVERRIDE; 198 199 // ui::MenuModel implementation 200 virtual int GetCommandIdAt(int index) const OVERRIDE; 201 202 private: 203 void AddWirelessNetworkMenuItem(const NetworkState* wifi_network, int flag); 204 void AddMessageItem(const base::string16& msg); 205 206 scoped_ptr<MoreMenuModel> more_menu_model_; 207 208 DISALLOW_COPY_AND_ASSIGN(MainMenuModel); 209}; 210 211//////////////////////////////////////////////////////////////////////////////// 212// NetworkMenuModel, public methods: 213 214void NetworkMenuModel::ConnectToNetworkAt(int index) { 215 const std::string& service_path = menu_items_[index].service_path; 216 gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow(); 217 ash::network_connect::ConnectToNetwork(service_path, native_window); 218} 219 220//////////////////////////////////////////////////////////////////////////////// 221// NetworkMenuModel, ui::MenuModel implementation: 222 223bool NetworkMenuModel::HasIcons() const { 224 return true; 225} 226 227int NetworkMenuModel::GetItemCount() const { 228 return static_cast<int>(menu_items_.size()); 229} 230 231ui::MenuModel::ItemType NetworkMenuModel::GetTypeAt(int index) const { 232 return menu_items_[index].type; 233} 234 235ui::MenuSeparatorType NetworkMenuModel::GetSeparatorTypeAt(int index) const { 236 return ui::NORMAL_SEPARATOR; 237} 238 239base::string16 NetworkMenuModel::GetLabelAt(int index) const { 240 return menu_items_[index].label; 241} 242 243bool NetworkMenuModel::IsItemDynamicAt(int index) const { 244 return false; 245} 246 247const gfx::Font* NetworkMenuModel::GetLabelFontAt(int index) const { 248 const gfx::Font* font = NULL; 249 if (menu_items_[index].flags & FLAG_ASSOCIATED) { 250 ResourceBundle& resource_bundle = ResourceBundle::GetSharedInstance(); 251 font = &resource_bundle.GetFont( 252 browser_defaults::kAssociatedNetworkFontStyle); 253 } 254 255 return font; 256} 257 258bool NetworkMenuModel::GetAcceleratorAt(int index, 259 ui::Accelerator* accelerator) const { 260 return false; 261} 262 263bool NetworkMenuModel::IsItemCheckedAt(int index) const { 264 // All ui::MenuModel::TYPE_CHECK menu items are checked. 265 return true; 266} 267 268int NetworkMenuModel::GetGroupIdAt(int index) const { 269 return 0; 270} 271 272bool NetworkMenuModel::GetIconAt(int index, gfx::Image* icon) { 273 if (!menu_items_[index].icon.isNull()) { 274 *icon = gfx::Image(menu_items_[index].icon); 275 return true; 276 } 277 return false; 278} 279 280ui::ButtonMenuItemModel* NetworkMenuModel::GetButtonMenuItemAt( 281 int index) const { 282 return NULL; 283} 284 285bool NetworkMenuModel::IsEnabledAt(int index) const { 286 return !(menu_items_[index].flags & FLAG_DISABLED); 287} 288 289bool NetworkMenuModel::IsVisibleAt(int index) const { 290 return true; 291} 292 293ui::MenuModel* NetworkMenuModel::GetSubmenuModelAt(int index) const { 294 return menu_items_[index].sub_menu_model; 295} 296 297void NetworkMenuModel::HighlightChangedTo(int index) { 298} 299 300void NetworkMenuModel::ActivatedAt(int index) { 301 // When we are refreshing the menu, ignore menu item activation. 302 if (owner_->refreshing_menu_) 303 return; 304 305 int flags = menu_items_[index].flags; 306 if (flags & FLAG_OPTIONS) { 307 owner_->delegate()->OpenButtonOptions(); 308 } else if (flags & FLAG_TOGGLE_WIFI) { 309 ToggleTechnology(NetworkTypePattern::WiFi()); 310 } else if (flags & FLAG_TOGGLE_MOBILE) { 311 ToggleTechnology(NetworkTypePattern::Mobile()); 312 } else if (flags & FLAG_ETHERNET) { 313 owner_->delegate()->OnConnectToNetworkRequested( 314 menu_items_[index].service_path); 315 } else if (flags & (FLAG_WIFI | FLAG_WIMAX | FLAG_CELLULAR)) { 316 ConnectToNetworkAt(index); 317 owner_->delegate()->OnConnectToNetworkRequested( 318 menu_items_[index].service_path); 319 } else if (flags & FLAG_ADD_WIFI) { 320 ShowOther(shill::kTypeWifi); 321 } else if (flags & FLAG_ADD_CELLULAR) { 322 ShowOther(shill::kTypeCellular); 323 } 324} 325 326void NetworkMenuModel::SetMenuModelDelegate(ui::MenuModelDelegate* delegate) { 327} 328 329ui::MenuModelDelegate* NetworkMenuModel::GetMenuModelDelegate() const { 330 return NULL; 331} 332 333//////////////////////////////////////////////////////////////////////////////// 334// NetworkMenuModel, private methods: 335 336void NetworkMenuModel::ShowOther(const std::string& type) const { 337 gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow(); 338 if (type == shill::kTypeCellular) 339 ChooseMobileNetworkDialog::ShowDialog(native_window); 340 else 341 NetworkConfigView::ShowForType(shill::kTypeWifi, native_window); 342} 343 344//////////////////////////////////////////////////////////////////////////////// 345// MainMenuModel 346 347void MainMenuModel::AddWirelessNetworkMenuItem(const NetworkState* network, 348 int flag) { 349 base::string16 label; 350 // Ampersand is a valid character in an SSID, but menu2 uses it to mark 351 // "mnemonics" for keyboard shortcuts. 352 std::string wifi_name = EscapeAmpersands(network->name()); 353 if (network->IsConnectingState()) { 354 label = l10n_util::GetStringFUTF16( 355 IDS_STATUSBAR_NETWORK_DEVICE_STATUS, 356 UTF8ToUTF16(wifi_name), 357 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING)); 358 } else { 359 label = UTF8ToUTF16(wifi_name); 360 } 361 362 // We do not have convenient access to whether or not it might be possible 363 // to connect to a wireless network (e.g. whether certs are required), so all 364 // entries are enabled. 365 366 if (ShouldHighlightNetwork(network)) 367 flag |= FLAG_ASSOCIATED; 368 const gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork( 369 network, ash::network_icon::ICON_TYPE_LIST); 370 menu_items_.push_back( 371 MenuItem(ui::MenuModel::TYPE_COMMAND, 372 label, icon, network->path(), flag)); 373} 374 375void MainMenuModel::AddMessageItem(const base::string16& msg) { 376 menu_items_.push_back(MenuItem( 377 ui::MenuModel::TYPE_COMMAND, msg, 378 gfx::ImageSkia(), std::string(), FLAG_DISABLED)); 379} 380 381void MainMenuModel::InitMenuItems(bool should_open_button_options) { 382 menu_items_.clear(); 383 384 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 385 386 // Populate our MenuItems with the current list of networks. 387 base::string16 label; 388 389 // Ethernet 390 // Only display an ethernet icon if enabled, and an ethernet network exists. 391 bool ethernet_enabled = 392 handler->IsTechnologyEnabled(NetworkTypePattern::Ethernet()); 393 const NetworkState* ethernet_network = 394 handler->FirstNetworkByType(NetworkTypePattern::Ethernet()); 395 if (ethernet_enabled && ethernet_network) { 396 bool ethernet_connecting = ethernet_network->IsConnectingState(); 397 if (ethernet_connecting) { 398 label = l10n_util::GetStringFUTF16( 399 IDS_STATUSBAR_NETWORK_DEVICE_STATUS, 400 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET), 401 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING)); 402 } else { 403 label = l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); 404 } 405 int flag = FLAG_ETHERNET; 406 if (ShouldHighlightNetwork(ethernet_network)) 407 flag |= FLAG_ASSOCIATED; 408 const gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork( 409 ethernet_network, ash::network_icon::ICON_TYPE_LIST); 410 menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, 411 label, icon, std::string(), flag)); 412 } 413 414 // Get the list of all networks. 415 NetworkStateHandler::NetworkStateList network_list; 416 handler->GetNetworkList(&network_list); 417 418 // Cellular Networks 419 if (handler->IsTechnologyEnabled(NetworkTypePattern::Cellular())) { 420 // List Cellular networks. 421 for (NetworkStateHandler::NetworkStateList::const_iterator iter = 422 network_list.begin(); iter != network_list.end(); ++iter) { 423 const NetworkState* network = *iter; 424 if (network->type() != shill::kTypeCellular) 425 continue; 426 std::string activation_state = network->activation_state(); 427 428 // This is only used in the login screen; do not show unactivated 429 // networks. 430 if (activation_state != shill::kActivationStateActivated) 431 continue; 432 433 // Ampersand is a valid character in a network name, but menu2 uses it 434 // to mark "mnemonics" for keyboard shortcuts. http://crosbug.com/14697 435 std::string network_name = EscapeAmpersands(network->name()); 436 if (network->IsConnectingState()) { 437 label = l10n_util::GetStringFUTF16( 438 IDS_STATUSBAR_NETWORK_DEVICE_STATUS, 439 UTF8ToUTF16(network_name), 440 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING)); 441 } else { 442 label = UTF8ToUTF16(network_name); 443 } 444 445 int flag = FLAG_CELLULAR; 446 bool isActive = ShouldHighlightNetwork(network); 447 if (isActive) 448 flag |= FLAG_ASSOCIATED; 449 const gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork( 450 network, ash::network_icon::ICON_TYPE_LIST); 451 menu_items_.push_back( 452 MenuItem(ui::MenuModel::TYPE_COMMAND, 453 label, icon, network->path(), flag)); 454 } 455 456 // For GSM add cellular network scan. 457 const DeviceState* cellular_device = 458 handler->GetDeviceStateByType(NetworkTypePattern::Cellular()); 459 if (cellular_device && cellular_device->support_network_scan()) { 460 const gfx::ImageSkia icon = 461 ash::network_icon::GetImageForDisconnectedNetwork( 462 ash::network_icon::ICON_TYPE_LIST, shill::kTypeCellular); 463 menu_items_.push_back(MenuItem( 464 ui::MenuModel::TYPE_COMMAND, 465 l10n_util::GetStringUTF16( 466 IDS_OPTIONS_SETTINGS_OTHER_CELLULAR_NETWORKS), 467 icon, std::string(), FLAG_ADD_CELLULAR)); 468 } 469 } else { 470 int initializing_message_id = 471 ash::network_icon::GetCellularUninitializedMsg(); 472 if (initializing_message_id) { 473 // Initializing cellular modem... 474 AddMessageItem(l10n_util::GetStringUTF16(initializing_message_id)); 475 } 476 } 477 478 // Wimax Networks 479 if (handler->IsTechnologyEnabled(NetworkTypePattern::Wimax())) { 480 // List Wimax networks. 481 for (NetworkStateHandler::NetworkStateList::const_iterator iter = 482 network_list.begin(); iter != network_list.end(); ++iter) { 483 const NetworkState* network = *iter; 484 if (network->type() != shill::kTypeWimax) 485 continue; 486 AddWirelessNetworkMenuItem(network, FLAG_WIMAX); 487 } 488 } 489 490 // Wifi Networks 491 if (handler->IsTechnologyEnabled(NetworkTypePattern::WiFi())) { 492 // List Wifi networks. 493 int scanning_msg = handler->GetScanningByType(NetworkTypePattern::WiFi()) 494 ? IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE 495 : 0; 496 for (NetworkStateHandler::NetworkStateList::const_iterator iter = 497 network_list.begin(); iter != network_list.end(); ++iter) { 498 const NetworkState* network = *iter; 499 if (network->type() != shill::kTypeWifi) 500 continue; 501 // Add 'Searching for Wi-Fi networks...' after connected networks. 502 if (scanning_msg && !network->IsConnectedState()) { 503 AddMessageItem(l10n_util::GetStringUTF16(scanning_msg)); 504 scanning_msg = 0; 505 } 506 AddWirelessNetworkMenuItem(network, FLAG_WIFI); 507 } 508 if (scanning_msg) 509 AddMessageItem(l10n_util::GetStringUTF16(scanning_msg)); 510 const gfx::ImageSkia icon = 511 ash::network_icon::GetImageForConnectedNetwork( 512 ash::network_icon::ICON_TYPE_LIST, shill::kTypeWifi); 513 menu_items_.push_back(MenuItem( 514 ui::MenuModel::TYPE_COMMAND, 515 l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS), 516 icon, std::string(), FLAG_ADD_WIFI)); 517 } 518 519 if (menu_items_.empty()) { 520 // No networks available (and not initializing cellular or wifi scanning) 521 AddMessageItem(l10n_util::GetStringFUTF16( 522 IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT, 523 l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE))); 524 } 525 526 // Enable / Disable Technology 527 NetworkStateHandler::TechnologyState wifi_state = 528 handler->GetTechnologyState(NetworkTypePattern::WiFi()); 529 bool wifi_available = 530 wifi_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE; 531 bool wifi_enabled = wifi_state == NetworkStateHandler::TECHNOLOGY_ENABLED; 532 533 NetworkStateHandler::TechnologyState mobile_state = 534 handler->GetTechnologyState(NetworkTypePattern::Mobile()); 535 bool mobile_available = 536 mobile_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE; 537 bool mobile_enabled = mobile_state == NetworkStateHandler::TECHNOLOGY_ENABLED; 538 539 // Do not show disable wifi or cellular during oobe. 540 bool show_toggle_wifi = wifi_available && 541 (should_open_button_options || !wifi_enabled); 542 bool show_toggle_mobile = mobile_available && 543 (should_open_button_options || !mobile_enabled); 544 545 if (show_toggle_wifi || show_toggle_mobile) { 546 menu_items_.push_back(MenuItem()); // Separator 547 548 if (show_toggle_wifi) { 549 int id = wifi_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE : 550 IDS_STATUSBAR_NETWORK_DEVICE_ENABLE; 551 label = l10n_util::GetStringFUTF16(id, 552 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI)); 553 int flag = FLAG_TOGGLE_WIFI; 554 if (wifi_state == NetworkStateHandler::TECHNOLOGY_ENABLING) 555 flag |= FLAG_DISABLED; 556 menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label, 557 gfx::ImageSkia(), std::string(), flag)); 558 } 559 560 if (show_toggle_mobile) { 561 const DeviceState* mobile_device = 562 handler->GetDeviceStateByType(NetworkTypePattern::Mobile()); 563 bool is_locked = mobile_device && !mobile_device->sim_lock_type().empty(); 564 int id = (mobile_enabled && !is_locked) 565 ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE 566 : IDS_STATUSBAR_NETWORK_DEVICE_ENABLE; 567 label = l10n_util::GetStringFUTF16(id, 568 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR)); 569 gfx::ImageSkia icon; 570 int flag = FLAG_TOGGLE_MOBILE; 571 if (mobile_state == NetworkStateHandler::TECHNOLOGY_ENABLING) 572 flag |= FLAG_DISABLED; 573 menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label, 574 icon, std::string(), flag)); 575 } 576 } 577 578 // Additional links like: 579 // * IP Address on active interface; 580 // * Hardware addresses for wifi and ethernet. 581 more_menu_model_->InitMenuItems(should_open_button_options); 582 if (!more_menu_model_->menu_items().empty()) { 583 menu_items_.push_back(MenuItem()); // Separator 584 menu_items_.push_back(MenuItem( 585 ui::MenuModel::TYPE_SUBMENU, 586 l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_MORE), 587 gfx::ImageSkia(), more_menu_model_.get(), FLAG_NONE)); 588 } 589} 590 591int MainMenuModel::GetCommandIdAt(int index) const { 592 return index + kMainIndexMask; 593} 594 595//////////////////////////////////////////////////////////////////////////////// 596// MoreMenuModel 597 598void MoreMenuModel::InitMenuItems(bool should_open_button_options) { 599 menu_items_.clear(); 600 MenuItemVector link_items; 601 MenuItemVector address_items; 602 603 NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler(); 604 const NetworkState* default_network = handler->DefaultNetwork(); 605 606 int message_id = -1; 607 if (default_network) 608 message_id = IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG; 609 if (message_id != -1) { 610 link_items.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, 611 l10n_util::GetStringUTF16(message_id), 612 gfx::ImageSkia(), 613 std::string(), 614 FLAG_OPTIONS)); 615 } 616 617 if (default_network) { 618 std::string ip_address = default_network->ip_address(); 619 if (!ip_address.empty()) { 620 address_items.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, 621 ASCIIToUTF16(ip_address), gfx::ImageSkia(), std::string(), 622 FLAG_DISABLED)); 623 } 624 } 625 626 std::string ethernet_address = 627 handler->FormattedHardwareAddressForType(NetworkTypePattern::Ethernet()); 628 if (!ethernet_address.empty()) { 629 std::string label = l10n_util::GetStringUTF8( 630 IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET) + " " + ethernet_address; 631 address_items.push_back(MenuItem( 632 ui::MenuModel::TYPE_COMMAND, 633 UTF8ToUTF16(label), gfx::ImageSkia(), std::string(), FLAG_DISABLED)); 634 } 635 636 std::string wifi_address = 637 handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi()); 638 if (!wifi_address.empty()) { 639 std::string label = l10n_util::GetStringUTF8( 640 IDS_STATUSBAR_NETWORK_DEVICE_WIFI) + " " + wifi_address; 641 address_items.push_back(MenuItem( 642 ui::MenuModel::TYPE_COMMAND, 643 UTF8ToUTF16(label), gfx::ImageSkia(), std::string(), FLAG_DISABLED)); 644 } 645 646 menu_items_ = link_items; 647 if (!menu_items_.empty() && address_items.size() > 1) 648 menu_items_.push_back(MenuItem()); // Separator 649 menu_items_.insert(menu_items_.end(), 650 address_items.begin(), address_items.end()); 651} 652 653int MoreMenuModel::GetCommandIdAt(int index) const { 654 return index + kMoreIndexMask; 655} 656 657//////////////////////////////////////////////////////////////////////////////// 658// NetworkMenu 659 660NetworkMenu::Delegate::~Delegate() { 661} 662 663NetworkMenu::NetworkMenu(Delegate* delegate) 664 : delegate_(delegate), 665 refreshing_menu_(false), 666 weak_pointer_factory_(this) { 667 main_menu_model_.reset(new MainMenuModel(weak_pointer_factory_.GetWeakPtr())); 668} 669 670NetworkMenu::~NetworkMenu() { 671} 672 673ui::MenuModel* NetworkMenu::GetMenuModel() { 674 return main_menu_model_.get(); 675} 676 677void NetworkMenu::UpdateMenu() { 678 refreshing_menu_ = true; 679 main_menu_model_->InitMenuItems(delegate_->ShouldOpenButtonOptions()); 680 refreshing_menu_ = false; 681} 682 683} // namespace chromeos 684