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