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