Home | History | Annotate | Download | only in status
      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