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