• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
EscapeAmpersands(const std::string & input)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.
ShouldHighlightNetwork(const NetworkState * network)58 bool ShouldHighlightNetwork(const NetworkState* network) {
59   return network->IsConnectedState() || network->IsConnectingState();
60 }
61 
ToggleTechnology(const NetworkTypePattern & technology)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 {
MenuItemchromeos::NetworkMenuModel::MenuItem73     MenuItem()
74         : type(ui::MenuModel::TYPE_SEPARATOR),
75           sub_menu_model(NULL),
76           flags(0) {
77     }
MenuItemchromeos::NetworkMenuModel::MenuItem78     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     }
MenuItemchromeos::NetworkMenuModel::MenuItem87     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 
NetworkMenuModel(const base::WeakPtr<NetworkMenu> & owner)105   explicit NetworkMenuModel(const base::WeakPtr<NetworkMenu>& owner)
106     : owner_(owner) {}
~NetworkMenuModel()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.
menu_items() const116   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:
MoreMenuModel(const base::WeakPtr<NetworkMenu> owner)173   explicit MoreMenuModel(const base::WeakPtr<NetworkMenu> owner)
174     : NetworkMenuModel(owner) {}
~MoreMenuModel()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:
MainMenuModel(const base::WeakPtr<NetworkMenu> & owner)189   explicit MainMenuModel(const base::WeakPtr<NetworkMenu>& owner)
190       : NetworkMenuModel(owner),
191         more_menu_model_(new MoreMenuModel(owner)) {
192   }
~MainMenuModel()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 
ConnectToNetworkAt(int index)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 
HasIcons() const222 bool NetworkMenuModel::HasIcons() const {
223   return true;
224 }
225 
GetItemCount() const226 int NetworkMenuModel::GetItemCount() const {
227   return static_cast<int>(menu_items_.size());
228 }
229 
GetTypeAt(int index) const230 ui::MenuModel::ItemType NetworkMenuModel::GetTypeAt(int index) const {
231   return menu_items_[index].type;
232 }
233 
GetSeparatorTypeAt(int index) const234 ui::MenuSeparatorType NetworkMenuModel::GetSeparatorTypeAt(int index) const {
235   return ui::NORMAL_SEPARATOR;
236 }
237 
GetLabelAt(int index) const238 base::string16 NetworkMenuModel::GetLabelAt(int index) const {
239   return menu_items_[index].label;
240 }
241 
IsItemDynamicAt(int index) const242 bool NetworkMenuModel::IsItemDynamicAt(int index) const {
243   return false;
244 }
245 
GetLabelFontListAt(int index) const246 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 
GetAcceleratorAt(int index,ui::Accelerator * accelerator) const256 bool NetworkMenuModel::GetAcceleratorAt(int index,
257                                         ui::Accelerator* accelerator) const {
258   return false;
259 }
260 
IsItemCheckedAt(int index) const261 bool NetworkMenuModel::IsItemCheckedAt(int index) const {
262   // All ui::MenuModel::TYPE_CHECK menu items are checked.
263   return true;
264 }
265 
GetGroupIdAt(int index) const266 int NetworkMenuModel::GetGroupIdAt(int index) const {
267   return 0;
268 }
269 
GetIconAt(int index,gfx::Image * icon)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 
GetButtonMenuItemAt(int index) const278 ui::ButtonMenuItemModel* NetworkMenuModel::GetButtonMenuItemAt(
279     int index) const {
280   return NULL;
281 }
282 
IsEnabledAt(int index) const283 bool NetworkMenuModel::IsEnabledAt(int index) const {
284   return !(menu_items_[index].flags & FLAG_DISABLED);
285 }
286 
IsVisibleAt(int index) const287 bool NetworkMenuModel::IsVisibleAt(int index) const {
288   return true;
289 }
290 
GetSubmenuModelAt(int index) const291 ui::MenuModel* NetworkMenuModel::GetSubmenuModelAt(int index) const {
292   return menu_items_[index].sub_menu_model;
293 }
294 
HighlightChangedTo(int index)295 void NetworkMenuModel::HighlightChangedTo(int index) {
296 }
297 
ActivatedAt(int index)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 
SetMenuModelDelegate(ui::MenuModelDelegate * delegate)324 void NetworkMenuModel::SetMenuModelDelegate(ui::MenuModelDelegate* delegate) {
325 }
326 
GetMenuModelDelegate() const327 ui::MenuModelDelegate* NetworkMenuModel::GetMenuModelDelegate() const {
328   return NULL;
329 }
330 
331 ////////////////////////////////////////////////////////////////////////////////
332 // NetworkMenuModel, private methods:
333 
ShowOther(const std::string & type) const334 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 
AddWirelessNetworkMenuItem(const NetworkState * network,int flag)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 
AddMessageItem(const base::string16 & msg)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 
InitMenuItems(bool should_open_button_options)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 
GetCommandIdAt(int index) const589 int MainMenuModel::GetCommandIdAt(int index) const {
590   return index + kMainIndexMask;
591 }
592 
593 ////////////////////////////////////////////////////////////////////////////////
594 // MoreMenuModel
595 
InitMenuItems(bool should_open_button_options)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 
GetCommandIdAt(int index) const651 int MoreMenuModel::GetCommandIdAt(int index) const {
652   return index + kMoreIndexMask;
653 }
654 
655 ////////////////////////////////////////////////////////////////////////////////
656 // NetworkMenu
657 
~Delegate()658 NetworkMenu::Delegate::~Delegate() {
659 }
660 
NetworkMenu(Delegate * delegate)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 
~NetworkMenu()668 NetworkMenu::~NetworkMenu() {
669 }
670 
GetMenuModel()671 ui::MenuModel* NetworkMenu::GetMenuModel() {
672   return main_menu_model_.get();
673 }
674 
UpdateMenu()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