• 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/strings/grit/ash_strings.h"
12 #include "ash/system/chromeos/network/network_connect.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/mobile_config.h"
18 #include "chrome/browser/chromeos/options/network_config_view.h"
19 #include "chrome/browser/chromeos/sim_dialog_delegate.h"
20 #include "chrome/browser/chromeos/ui/choose_mobile_network_dialog.h"
21 #include "chrome/browser/defaults.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/common/url_constants.h"
24 #include "chrome/grit/generated_resources.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 "third_party/cros_system_api/dbus/service_constants.h"
29 #include "ui/base/l10n/l10n_util.h"
30 #include "ui/base/models/menu_model.h"
31 #include "ui/base/resource/resource_bundle.h"
32 #include "ui/chromeos/network/network_icon.h"
33 #include "ui/chromeos/strings/grit/ui_chromeos_strings.h"
34 #include "ui/gfx/image/image_skia.h"
35 
36 namespace chromeos {
37 
38 namespace {
39 
40 // Offsets for views menu ids (main menu and submenu ids use the same
41 // namespace).
42 const int kMainIndexMask = 0x1000;
43 const int kMoreIndexMask = 0x4000;
44 
45 // Replace '&' in a string with "&&" to allow it to be a menu item label.
EscapeAmpersands(const std::string & input)46 std::string EscapeAmpersands(const std::string& input) {
47   std::string str = input;
48   size_t found = str.find('&');
49   while (found != std::string::npos) {
50     str.replace(found, 1, "&&");
51     found = str.find('&', found + 2);
52   }
53   return str;
54 }
55 
56 // Highlight any connected or connecting networks in the UI.
ShouldHighlightNetwork(const NetworkState * network)57 bool ShouldHighlightNetwork(const NetworkState* network) {
58   return network->IsConnectedState() || network->IsConnectingState();
59 }
60 
ToggleTechnology(const NetworkTypePattern & technology)61 void ToggleTechnology(const NetworkTypePattern& technology) {
62   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
63   bool is_enabled = handler->IsTechnologyEnabled(technology);
64   ash::network_connect::SetTechnologyEnabled(technology, !is_enabled);
65 }
66 
67 }  // namespace
68 
69 class NetworkMenuModel : public ui::MenuModel {
70  public:
71   struct MenuItem {
MenuItemchromeos::NetworkMenuModel::MenuItem72     MenuItem()
73         : type(ui::MenuModel::TYPE_SEPARATOR),
74           sub_menu_model(NULL),
75           flags(0) {
76     }
MenuItemchromeos::NetworkMenuModel::MenuItem77     MenuItem(ui::MenuModel::ItemType type,
78              base::string16 label,
79              gfx::ImageSkia icon,
80              const std::string& service_path,
81              int flags)
82         : type(type),
83           label(label),
84           icon(icon),
85           service_path(service_path),
86           sub_menu_model(NULL),
87           flags(flags) {
88     }
MenuItemchromeos::NetworkMenuModel::MenuItem89     MenuItem(ui::MenuModel::ItemType type,
90              base::string16 label,
91              gfx::ImageSkia icon,
92              NetworkMenuModel* sub_menu_model,
93              int flags)
94         : type(type),
95           label(label),
96           icon(icon),
97           sub_menu_model(sub_menu_model),
98           flags(flags) {
99     }
100 
101     ui::MenuModel::ItemType type;
102     base::string16 label;
103     gfx::ImageSkia icon;
104     std::string service_path;
105     NetworkMenuModel* sub_menu_model;  // Weak ptr.
106     int flags;
107   };
108   typedef std::vector<MenuItem> MenuItemVector;
109 
NetworkMenuModel(const base::WeakPtr<NetworkMenu> & owner)110   explicit NetworkMenuModel(const base::WeakPtr<NetworkMenu>& owner)
111     : owner_(owner) {}
~NetworkMenuModel()112   virtual ~NetworkMenuModel() {}
113 
114   // Connect or reconnect to the network at |index|.
115   void ConnectToNetworkAt(int index);
116 
117   // Called by NetworkMenu::UpdateMenu to initialize menu items.
118   virtual void InitMenuItems(bool should_open_button_options) = 0;
119 
120   // Menu item field accessors.
menu_items() const121   const MenuItemVector& menu_items() const { return menu_items_; }
122 
123   // ui::MenuModel implementation
124   // GetCommandIdAt() must be implemented by subclasses.
125   virtual bool HasIcons() const OVERRIDE;
126   virtual int GetItemCount() const OVERRIDE;
127   virtual ui::MenuModel::ItemType GetTypeAt(int index) const OVERRIDE;
128   virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE;
129   virtual base::string16 GetLabelAt(int index) const OVERRIDE;
130   virtual bool IsItemDynamicAt(int index) const OVERRIDE;
131   virtual const gfx::FontList* GetLabelFontListAt(int index) const OVERRIDE;
132   virtual bool GetAcceleratorAt(int index,
133                                 ui::Accelerator* accelerator) const OVERRIDE;
134   virtual bool IsItemCheckedAt(int index) const OVERRIDE;
135   virtual int GetGroupIdAt(int index) const OVERRIDE;
136   virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE;
137   virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
138       int index) const OVERRIDE;
139   virtual bool IsEnabledAt(int index) const OVERRIDE;
140   virtual bool IsVisibleAt(int index) const OVERRIDE;
141   virtual ui::MenuModel* GetSubmenuModelAt(int index) const OVERRIDE;
142   virtual void HighlightChangedTo(int index) OVERRIDE;
143   virtual void ActivatedAt(int index) OVERRIDE;
144   virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) OVERRIDE;
145   virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE;
146 
147  protected:
148   enum MenuItemFlags {
149     FLAG_NONE              = 0,
150     FLAG_DISABLED          = 1 << 0,
151     FLAG_TOGGLE_WIFI       = 1 << 2,
152     FLAG_TOGGLE_MOBILE     = 1 << 3,
153     FLAG_ASSOCIATED        = 1 << 5,
154     FLAG_ETHERNET          = 1 << 6,
155     FLAG_WIFI              = 1 << 7,
156     FLAG_WIMAX             = 1 << 8,
157     FLAG_CELLULAR          = 1 << 9,
158     FLAG_OPTIONS           = 1 << 10,
159     FLAG_ADD_WIFI          = 1 << 11,
160     FLAG_ADD_CELLULAR      = 1 << 12,
161   };
162 
163   // Our menu items.
164   MenuItemVector menu_items_;
165 
166   // Weak pointer to NetworkMenu that owns this MenuModel.
167   base::WeakPtr<NetworkMenu> owner_;
168 
169  private:
170   // Open a dialog to set up and connect to a network.
171   void ShowOther(const std::string& type) const;
172 
173   DISALLOW_COPY_AND_ASSIGN(NetworkMenuModel);
174 };
175 
176 class MoreMenuModel : public NetworkMenuModel {
177  public:
MoreMenuModel(const base::WeakPtr<NetworkMenu> owner)178   explicit MoreMenuModel(const base::WeakPtr<NetworkMenu> owner)
179     : NetworkMenuModel(owner) {}
~MoreMenuModel()180   virtual ~MoreMenuModel() {}
181 
182   // NetworkMenuModel implementation.
183   virtual void InitMenuItems(bool should_open_button_options) OVERRIDE;
184 
185   // ui::MenuModel implementation
186   virtual int GetCommandIdAt(int index) const OVERRIDE;
187 
188  private:
189   DISALLOW_COPY_AND_ASSIGN(MoreMenuModel);
190 };
191 
192 class MainMenuModel : public NetworkMenuModel {
193  public:
MainMenuModel(const base::WeakPtr<NetworkMenu> & owner)194   explicit MainMenuModel(const base::WeakPtr<NetworkMenu>& owner)
195       : NetworkMenuModel(owner),
196         more_menu_model_(new MoreMenuModel(owner)) {
197   }
~MainMenuModel()198   virtual ~MainMenuModel() {}
199 
200   // NetworkMenuModel implementation.
201   virtual void InitMenuItems(bool should_open_button_options) OVERRIDE;
202 
203   // ui::MenuModel implementation
204   virtual int GetCommandIdAt(int index) const OVERRIDE;
205 
206  private:
207   void AddWirelessNetworkMenuItem(const NetworkState* wifi_network, int flag);
208   void AddMessageItem(const base::string16& msg);
209 
210   scoped_ptr<MoreMenuModel> more_menu_model_;
211 
212   DISALLOW_COPY_AND_ASSIGN(MainMenuModel);
213 };
214 
215 ////////////////////////////////////////////////////////////////////////////////
216 // NetworkMenuModel, public methods:
217 
ConnectToNetworkAt(int index)218 void NetworkMenuModel::ConnectToNetworkAt(int index) {
219   const std::string& service_path = menu_items_[index].service_path;
220   ash::network_connect::ConnectToNetwork(service_path);
221 }
222 
223 ////////////////////////////////////////////////////////////////////////////////
224 // NetworkMenuModel, ui::MenuModel implementation:
225 
HasIcons() const226 bool NetworkMenuModel::HasIcons() const {
227   return true;
228 }
229 
GetItemCount() const230 int NetworkMenuModel::GetItemCount() const {
231   return static_cast<int>(menu_items_.size());
232 }
233 
GetTypeAt(int index) const234 ui::MenuModel::ItemType NetworkMenuModel::GetTypeAt(int index) const {
235   return menu_items_[index].type;
236 }
237 
GetSeparatorTypeAt(int index) const238 ui::MenuSeparatorType NetworkMenuModel::GetSeparatorTypeAt(int index) const {
239   return ui::NORMAL_SEPARATOR;
240 }
241 
GetLabelAt(int index) const242 base::string16 NetworkMenuModel::GetLabelAt(int index) const {
243   return menu_items_[index].label;
244 }
245 
IsItemDynamicAt(int index) const246 bool NetworkMenuModel::IsItemDynamicAt(int index) const {
247   return false;
248 }
249 
GetLabelFontListAt(int index) const250 const gfx::FontList* NetworkMenuModel::GetLabelFontListAt(int index) const {
251   const gfx::FontList* font_list = NULL;
252   if (menu_items_[index].flags & FLAG_ASSOCIATED) {
253     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
254     font_list = &rb.GetFontList(browser_defaults::kAssociatedNetworkFontStyle);
255   }
256 
257   return font_list;
258 }
259 
GetAcceleratorAt(int index,ui::Accelerator * accelerator) const260 bool NetworkMenuModel::GetAcceleratorAt(int index,
261                                         ui::Accelerator* accelerator) const {
262   return false;
263 }
264 
IsItemCheckedAt(int index) const265 bool NetworkMenuModel::IsItemCheckedAt(int index) const {
266   // All ui::MenuModel::TYPE_CHECK menu items are checked.
267   return true;
268 }
269 
GetGroupIdAt(int index) const270 int NetworkMenuModel::GetGroupIdAt(int index) const {
271   return 0;
272 }
273 
GetIconAt(int index,gfx::Image * icon)274 bool NetworkMenuModel::GetIconAt(int index, gfx::Image* icon) {
275   if (!menu_items_[index].icon.isNull()) {
276     *icon = gfx::Image(menu_items_[index].icon);
277     return true;
278   }
279   return false;
280 }
281 
GetButtonMenuItemAt(int index) const282 ui::ButtonMenuItemModel* NetworkMenuModel::GetButtonMenuItemAt(
283     int index) const {
284   return NULL;
285 }
286 
IsEnabledAt(int index) const287 bool NetworkMenuModel::IsEnabledAt(int index) const {
288   return !(menu_items_[index].flags & FLAG_DISABLED);
289 }
290 
IsVisibleAt(int index) const291 bool NetworkMenuModel::IsVisibleAt(int index) const {
292   return true;
293 }
294 
GetSubmenuModelAt(int index) const295 ui::MenuModel* NetworkMenuModel::GetSubmenuModelAt(int index) const {
296   return menu_items_[index].sub_menu_model;
297 }
298 
HighlightChangedTo(int index)299 void NetworkMenuModel::HighlightChangedTo(int index) {
300 }
301 
ActivatedAt(int index)302 void NetworkMenuModel::ActivatedAt(int index) {
303   // When we are refreshing the menu, ignore menu item activation.
304   if (owner_->refreshing_menu_)
305     return;
306 
307   int flags = menu_items_[index].flags;
308   if (flags & FLAG_OPTIONS) {
309     owner_->delegate()->OpenButtonOptions();
310   } else if (flags & FLAG_TOGGLE_WIFI) {
311     ToggleTechnology(NetworkTypePattern::WiFi());
312   } else if (flags & FLAG_TOGGLE_MOBILE) {
313     ToggleTechnology(NetworkTypePattern::Mobile());
314   } else if (flags & FLAG_ETHERNET) {
315     owner_->delegate()->OnConnectToNetworkRequested();
316   } else if (flags & (FLAG_WIFI | FLAG_WIMAX | FLAG_CELLULAR)) {
317     ConnectToNetworkAt(index);
318     owner_->delegate()->OnConnectToNetworkRequested();
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 
SetMenuModelDelegate(ui::MenuModelDelegate * delegate)326 void NetworkMenuModel::SetMenuModelDelegate(ui::MenuModelDelegate* delegate) {
327 }
328 
GetMenuModelDelegate() const329 ui::MenuModelDelegate* NetworkMenuModel::GetMenuModelDelegate() const {
330   return NULL;
331 }
332 
333 ////////////////////////////////////////////////////////////////////////////////
334 // NetworkMenuModel, private methods:
335 
ShowOther(const std::string & type) const336 void 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 
AddWirelessNetworkMenuItem(const NetworkState * network,int flag)347 void 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         base::UTF8ToUTF16(wifi_name),
357         l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
358   } else {
359     label = base::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 = ui::network_icon::GetImageForNetwork(
369       network, ui::network_icon::ICON_TYPE_LIST);
370   menu_items_.push_back(
371       MenuItem(ui::MenuModel::TYPE_COMMAND,
372                label, icon, network->path(), flag));
373 }
374 
AddMessageItem(const base::string16 & msg)375 void 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 
InitMenuItems(bool should_open_button_options)381 void 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 = ui::network_icon::GetImageForNetwork(
409         ethernet_network, ui::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->GetVisibleNetworkList(&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             base::UTF8ToUTF16(network_name),
440             l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
441       } else {
442         label = base::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 = ui::network_icon::GetImageForNetwork(
450           network, ui::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           ui::network_icon::GetImageForDisconnectedNetwork(
462               ui::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         ui::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 = ui::network_icon::GetImageForConnectedNetwork(
511         ui::network_icon::ICON_TYPE_LIST, shill::kTypeWifi);
512     menu_items_.push_back(MenuItem(
513         ui::MenuModel::TYPE_COMMAND,
514         l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS),
515         icon, std::string(), FLAG_ADD_WIFI));
516   }
517 
518   if (menu_items_.empty()) {
519     // No networks available (and not initializing cellular or wifi scanning)
520     AddMessageItem(l10n_util::GetStringFUTF16(
521         IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT,
522         l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE)));
523   }
524 
525   // Enable / Disable Technology
526   NetworkStateHandler::TechnologyState wifi_state =
527       handler->GetTechnologyState(NetworkTypePattern::WiFi());
528   bool wifi_available =
529       wifi_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE;
530   bool wifi_enabled = wifi_state == NetworkStateHandler::TECHNOLOGY_ENABLED;
531 
532   NetworkStateHandler::TechnologyState mobile_state =
533       handler->GetTechnologyState(NetworkTypePattern::Mobile());
534   bool mobile_available =
535       mobile_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE;
536   bool mobile_enabled = mobile_state == NetworkStateHandler::TECHNOLOGY_ENABLED;
537 
538   // Do not show disable wifi or cellular during oobe.
539   bool show_toggle_wifi = wifi_available &&
540       (should_open_button_options || !wifi_enabled);
541   bool show_toggle_mobile = mobile_available &&
542       (should_open_button_options || !mobile_enabled);
543 
544   if (show_toggle_wifi || show_toggle_mobile) {
545     menu_items_.push_back(MenuItem());  // Separator
546 
547     if (show_toggle_wifi) {
548       int id = wifi_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
549                               IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
550       label = l10n_util::GetStringFUTF16(id,
551           l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
552       int flag = FLAG_TOGGLE_WIFI;
553       if (wifi_state == NetworkStateHandler::TECHNOLOGY_ENABLING)
554         flag |= FLAG_DISABLED;
555       menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
556           gfx::ImageSkia(), std::string(), flag));
557     }
558 
559     if (show_toggle_mobile) {
560       const DeviceState* mobile_device =
561           handler->GetDeviceStateByType(NetworkTypePattern::Mobile());
562       bool is_locked = mobile_device && !mobile_device->sim_lock_type().empty();
563       int id = (mobile_enabled && !is_locked)
564           ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE
565           : IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
566       label = l10n_util::GetStringFUTF16(id,
567           l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR));
568       gfx::ImageSkia icon;
569       int flag = FLAG_TOGGLE_MOBILE;
570       if (mobile_state == NetworkStateHandler::TECHNOLOGY_ENABLING)
571         flag |= FLAG_DISABLED;
572       menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
573           icon, std::string(), flag));
574     }
575   }
576 
577   // Additional links like:
578   // * IP Address on active interface;
579   // * Hardware addresses for wifi and ethernet.
580   more_menu_model_->InitMenuItems(should_open_button_options);
581   if (!more_menu_model_->menu_items().empty()) {
582     menu_items_.push_back(MenuItem());  // Separator
583     menu_items_.push_back(MenuItem(
584         ui::MenuModel::TYPE_SUBMENU,
585         l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_MORE),
586         gfx::ImageSkia(), more_menu_model_.get(), FLAG_NONE));
587   }
588 }
589 
GetCommandIdAt(int index) const590 int MainMenuModel::GetCommandIdAt(int index) const {
591   return index + kMainIndexMask;
592 }
593 
594 ////////////////////////////////////////////////////////////////////////////////
595 // MoreMenuModel
596 
InitMenuItems(bool should_open_button_options)597 void MoreMenuModel::InitMenuItems(bool should_open_button_options) {
598   menu_items_.clear();
599   MenuItemVector link_items;
600   MenuItemVector address_items;
601 
602   NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
603   const NetworkState* default_network = handler->DefaultNetwork();
604 
605   int message_id = -1;
606   if (default_network)
607     message_id = IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG;
608   if (message_id != -1) {
609     link_items.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND,
610                                   l10n_util::GetStringUTF16(message_id),
611                                   gfx::ImageSkia(),
612                                   std::string(),
613                                   FLAG_OPTIONS));
614   }
615 
616   if (default_network) {
617     std::string ip_address = default_network->ip_address();
618     if (!ip_address.empty()) {
619       address_items.push_back(MenuItem(
620           ui::MenuModel::TYPE_COMMAND, base::ASCIIToUTF16(ip_address),
621           gfx::ImageSkia(), std::string(), FLAG_DISABLED));
622     }
623   }
624 
625   std::string ethernet_address =
626       handler->FormattedHardwareAddressForType(NetworkTypePattern::Ethernet());
627   if (!ethernet_address.empty()) {
628     std::string label = l10n_util::GetStringUTF8(
629         IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET) + " " + ethernet_address;
630     address_items.push_back(MenuItem(
631         ui::MenuModel::TYPE_COMMAND, base::UTF8ToUTF16(label),
632         gfx::ImageSkia(), std::string(), FLAG_DISABLED));
633   }
634 
635   std::string wifi_address =
636       handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi());
637   if (!wifi_address.empty()) {
638     std::string label = l10n_util::GetStringUTF8(
639         IDS_STATUSBAR_NETWORK_DEVICE_WIFI) + " " + wifi_address;
640     address_items.push_back(MenuItem(
641         ui::MenuModel::TYPE_COMMAND, base::UTF8ToUTF16(label),
642         gfx::ImageSkia(), std::string(), FLAG_DISABLED));
643   }
644 
645   menu_items_ = link_items;
646   if (!menu_items_.empty() && address_items.size() > 1)
647     menu_items_.push_back(MenuItem());  // Separator
648   menu_items_.insert(menu_items_.end(),
649       address_items.begin(), address_items.end());
650 }
651 
GetCommandIdAt(int index) const652 int MoreMenuModel::GetCommandIdAt(int index) const {
653   return index + kMoreIndexMask;
654 }
655 
656 ////////////////////////////////////////////////////////////////////////////////
657 // NetworkMenu
658 
~Delegate()659 NetworkMenu::Delegate::~Delegate() {
660 }
661 
NetworkMenu(Delegate * delegate)662 NetworkMenu::NetworkMenu(Delegate* delegate)
663     : delegate_(delegate),
664       refreshing_menu_(false),
665       weak_pointer_factory_(this) {
666   main_menu_model_.reset(new MainMenuModel(weak_pointer_factory_.GetWeakPtr()));
667 }
668 
~NetworkMenu()669 NetworkMenu::~NetworkMenu() {
670 }
671 
GetMenuModel()672 ui::MenuModel* NetworkMenu::GetMenuModel() {
673   return main_menu_model_.get();
674 }
675 
UpdateMenu()676 void NetworkMenu::UpdateMenu() {
677   refreshing_menu_ = true;
678   main_menu_model_->InitMenuItems(delegate_->ShouldOpenButtonOptions());
679   refreshing_menu_ = false;
680 }
681 
682 }  // namespace chromeos
683