network_menu.cc revision 3f50c38dc070f4bb515c1b64450dae14f316474e
1// Copyright (c) 2010 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 "app/l10n_util.h"
10#include "app/resource_bundle.h"
11#include "base/command_line.h"
12#include "base/stringprintf.h"
13#include "base/utf_string_conversions.h"
14#include "chrome/browser/chromeos/cros/cros_library.h"
15#include "chrome/browser/chromeos/dom_ui/network_menu_ui.h"
16#include "chrome/browser/ui/browser.h"
17#include "chrome/browser/ui/browser_list.h"
18#include "chrome/common/chrome_switches.h"
19#include "chrome/common/url_constants.h"
20#include "chrome/browser/views/window.h"
21#include "gfx/canvas_skia.h"
22#include "gfx/skbitmap_operations.h"
23#include "grit/generated_resources.h"
24#include "grit/theme_resources.h"
25#include "net/base/escape.h"
26#include "views/controls/menu/menu_2.h"
27#include "views/window/window.h"
28
29namespace {
30// Constants passed to Javascript:
31static const char* kNetworkTypeEthernet = "ethernet";
32static const char* kNetworkTypeWifi = "wifi";
33static const char* kNetworkTypeCellular = "cellular";
34static const char* kNetworkTypeOther = "other";
35
36static const char* kNetworkStatusConnected = "connected";
37static const char* kNetworkStatusConnecting = "connecting";
38static const char* kNetworkStatusDisconnected = "disconnected";
39static const char* kNetworkStatusError = "error";
40}
41
42namespace chromeos {
43
44////////////////////////////////////////////////////////////////////////////////
45// NetworkMenu
46
47// static
48const int NetworkMenu::kNumBarsImages = 4;
49
50// NOTE: Use an array rather than just calculating a resource number to avoid
51// creating implicit ordering dependencies on the resource values.
52// static
53const int NetworkMenu::kBarsImages[kNumBarsImages] = {
54  IDR_STATUSBAR_NETWORK_BARS1,
55  IDR_STATUSBAR_NETWORK_BARS2,
56  IDR_STATUSBAR_NETWORK_BARS3,
57  IDR_STATUSBAR_NETWORK_BARS4,
58};
59// static
60const int NetworkMenu::kBarsImagesBlack[kNumBarsImages] = {
61  IDR_STATUSBAR_NETWORK_BARS1_BLACK,
62  IDR_STATUSBAR_NETWORK_BARS2_BLACK,
63  IDR_STATUSBAR_NETWORK_BARS3_BLACK,
64  IDR_STATUSBAR_NETWORK_BARS4_BLACK,
65};
66/*
67// static
68const int NetworkMenu::kBarsImagesLowData[kNumBarsImages] = {
69  IDR_STATUSBAR_NETWORK_BARS1_ORANGE,
70  IDR_STATUSBAR_NETWORK_BARS2_ORANGE,
71  IDR_STATUSBAR_NETWORK_BARS3_ORANGE,
72  IDR_STATUSBAR_NETWORK_BARS4_ORANGE,
73};
74// static
75const int NetworkMenu::kBarsImagesVLowData[kNumBarsImages] = {
76  IDR_STATUSBAR_NETWORK_BARS1_RED,
77  IDR_STATUSBAR_NETWORK_BARS2_RED,
78  IDR_STATUSBAR_NETWORK_BARS3_RED,
79  IDR_STATUSBAR_NETWORK_BARS4_RED,
80};
81*/
82
83NetworkMenu::NetworkMenu()
84    : min_width_(-1) {
85  use_settings_ui_ = !CommandLine::ForCurrentProcess()->HasSwitch(
86      switches::kDisableTabbedOptions);
87  network_menu_.reset(NetworkMenuUI::CreateMenu2(this));
88}
89
90NetworkMenu::~NetworkMenu() {
91}
92
93bool NetworkMenu::GetNetworkAt(int index, NetworkInfo* info) const {
94  DCHECK(info);
95  bool res = true;  // True unless a network doesn't exist.
96  int flags = menu_items_[index].flags;
97  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
98  if (flags & FLAG_ETHERNET) {
99    info->network_type = kNetworkTypeEthernet;
100    if (cros->ethernet_connected()) {
101      info->status = kNetworkStatusConnected;
102      info->ip_address = cros->ethernet_network() ?
103          cros->ethernet_network()->ip_address() : std::string();
104    }
105    info->need_passphrase = false;
106    info->remembered = true;
107  } else if (flags & FLAG_WIFI) {
108    WifiNetwork* wifi = cros->FindWifiNetworkByPath(
109        menu_items_[index].wireless_path);
110    if (wifi) {
111      info->network_type = kNetworkTypeWifi;
112      if (cros->wifi_network() &&
113          wifi->service_path() == cros->wifi_network()->service_path()) {
114        if (cros->wifi_connected()) {
115          info->status = kNetworkStatusConnected;
116          info->message = l10n_util::GetStringUTF8(
117              IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED);
118        } else if (cros->wifi_connecting()) {
119          info->status = kNetworkStatusConnecting;
120          info->message = l10n_util::GetStringUTF8(
121              IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING);
122        } else if (wifi->state() == STATE_FAILURE) {
123          info->status = kNetworkStatusError;
124          info->message = wifi->GetErrorString();
125        } else {
126          info->status = kNetworkStatusDisconnected;
127          info->message = l10n_util::GetStringUTF8(
128              IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED);
129        }
130      } else {
131        info->status = kNetworkStatusDisconnected;
132        info->message = l10n_util::GetStringUTF8(
133            IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED);
134      }
135      info->need_passphrase = wifi->IsPassphraseRequired();
136      info->ip_address = wifi->ip_address();
137      info->remembered = wifi->favorite();
138      info->auto_connect = wifi->auto_connect();
139    } else {
140      res = false;  // Network not found, hide entry.
141    }
142  } else if (flags & FLAG_CELLULAR) {
143    CellularNetwork* cellular = cros->FindCellularNetworkByPath(
144        menu_items_[index].wireless_path);
145    if (cellular) {
146      info->network_type = kNetworkTypeCellular;
147      if (cros->cellular_network() && cellular->service_path() ==
148          cros->cellular_network()->service_path()) {
149        if (cros->cellular_connected()) {
150          info->status = kNetworkStatusConnected;
151          info->message = l10n_util::GetStringUTF8(
152              IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED);
153        } else if (cros->cellular_connecting()) {
154          // TODO(stevenjb): Eliminate status message, or localize properly.
155          info->status = kNetworkStatusConnecting;
156          info->message = l10n_util::GetStringUTF8(
157              IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING)
158              + ": " + cellular->GetStateString();
159        } else if (cellular->state() == STATE_FAILURE) {
160          info->status = kNetworkStatusError;
161          info->message = cellular->GetErrorString();
162        } else {
163          info->status = kNetworkStatusDisconnected;
164          info->message = l10n_util::GetStringUTF8(
165              IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED);
166        }
167      } else {
168        info->status = kNetworkStatusDisconnected;
169        info->message = l10n_util::GetStringUTF8(
170            IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED);
171      }
172      info->ip_address = cellular->ip_address();
173      info->need_passphrase = false;
174      info->remembered = true;
175    } else {
176      res = false;  // Network not found, hide entry.
177    }
178  } else if (flags & FLAG_OTHER_NETWORK) {
179    info->status = kNetworkStatusDisconnected;
180    info->message = l10n_util::GetStringUTF8(
181        IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED);
182    info->network_type = kNetworkTypeOther;
183    info->need_passphrase = true;
184    info->remembered = true;
185  } else {
186    // Not a network, e.g options, separator.
187  }
188  return res;
189}
190
191bool NetworkMenu::ConnectToNetworkAt(int index,
192                                     const std::string& passphrase,
193                                     const std::string& ssid,
194                                     int auto_connect) const {
195  int flags = menu_items_[index].flags;
196  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
197  if (flags & FLAG_WIFI) {
198    WifiNetwork* wifi = cros->FindWifiNetworkByPath(
199        menu_items_[index].wireless_path);
200    if (wifi) {
201      // Connect or reconnect.
202      if (auto_connect >= 0)
203        wifi->set_auto_connect(auto_connect ? true : false);
204      if (wifi->connecting_or_connected()) {
205        // Show the config settings for the active network.
206        ShowTabbedNetworkSettings(wifi);
207        return true;
208      }
209      bool connected = false;
210      if (wifi->IsPassphraseRequired()) {
211        // Show the connection UI if we require a passphrase.
212        ShowNetworkConfigView(new NetworkConfigView(wifi));
213        return true;
214      } else {
215        connected = cros->ConnectToWifiNetwork(
216            wifi, passphrase, std::string(), std::string());
217      }
218      if (!connected) {
219        if (!MenuUI::IsEnabled()) {
220          // Show the wifi dialog on a failed attempt for non DOM UI menus.
221          ShowNetworkConfigView(new NetworkConfigView(wifi));
222          return true;
223        } else {
224          // If the connection attempt failed immediately (e.g. short password)
225          // keep the menu open so that a retry can be attempted.
226          return false;
227        }
228      }
229    } else {
230      // If we are attempting to connect to a network that no longer exists,
231      // display a notification.
232      // TODO(stevenjb): Show notification.
233    }
234  } else if (flags & FLAG_CELLULAR) {
235    CellularNetwork* cellular = cros->FindCellularNetworkByPath(
236        menu_items_[index].wireless_path);
237    if (cellular) {
238      if ((cellular->activation_state() != ACTIVATION_STATE_ACTIVATED &&
239           cellular->activation_state() != ACTIVATION_STATE_UNKNOWN) ||
240          cellular->needs_new_plan()) {
241        ActivateCellular(cellular);
242        return true;
243      } else if (cellular->connecting_or_connected()) {
244        // Cellular network is connecting or connected,
245        // so we show the config settings for the cellular network.
246        ShowTabbedNetworkSettings(cellular);
247        return true;
248      }
249      // Clicked on a disconnected cellular network, so connect to it.
250      cros->ConnectToCellularNetwork(cellular);
251    } else {
252      // If we are attempting to connect to a network that no longer exists,
253      // display a notification.
254      // TODO(stevenjb): Show notification.
255    }
256  } else if (flags & FLAG_OTHER_NETWORK) {
257    bool connected = false;
258    if (MenuUI::IsEnabled()) {
259      // default is true
260      bool auto_connect_bool = auto_connect == 0 ? false : true;
261      connected = cros->ConnectToWifiNetwork(
262          passphrase.empty() ? SECURITY_NONE : SECURITY_UNKNOWN,
263          ssid, passphrase, std::string(), std::string(), auto_connect_bool);
264    }
265    if (!connected) {
266      ShowOther();
267    }
268  }
269  return true;
270}
271
272////////////////////////////////////////////////////////////////////////////////
273// NetworkMenu, menus::MenuModel implementation:
274
275int NetworkMenu::GetItemCount() const {
276  return static_cast<int>(menu_items_.size());
277}
278
279menus::MenuModel::ItemType NetworkMenu::GetTypeAt(int index) const {
280  return menu_items_[index].type;
281}
282
283string16 NetworkMenu::GetLabelAt(int index) const {
284  return menu_items_[index].label;
285}
286
287const gfx::Font* NetworkMenu::GetLabelFontAt(int index) const {
288  return (menu_items_[index].flags & FLAG_ASSOCIATED) ?
289      &ResourceBundle::GetSharedInstance().GetFont(ResourceBundle::BoldFont) :
290      NULL;
291}
292
293bool NetworkMenu::IsItemCheckedAt(int index) const {
294  // All menus::MenuModel::TYPE_CHECK menu items are checked.
295  return true;
296}
297
298bool NetworkMenu::GetIconAt(int index, SkBitmap* icon) const {
299  if (!menu_items_[index].icon.empty()) {
300    *icon = menu_items_[index].icon;
301    return true;
302  }
303  return false;
304}
305
306bool NetworkMenu::IsEnabledAt(int index) const {
307  return !(menu_items_[index].flags & FLAG_DISABLED);
308}
309
310void NetworkMenu::ActivatedAt(int index) {
311  // When we are refreshing the menu, ignore menu item activation.
312  if (refreshing_menu_)
313    return;
314
315  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
316  int flags = menu_items_[index].flags;
317  if (flags & FLAG_OPTIONS) {
318    OpenButtonOptions();
319  } else if (flags & FLAG_TOGGLE_ETHERNET) {
320    cros->EnableEthernetNetworkDevice(!cros->ethernet_enabled());
321  } else if (flags & FLAG_TOGGLE_WIFI) {
322    cros->EnableWifiNetworkDevice(!cros->wifi_enabled());
323  } else if (flags & FLAG_TOGGLE_CELLULAR) {
324    cros->EnableCellularNetworkDevice(!cros->cellular_enabled());
325  } else if (flags & FLAG_TOGGLE_OFFLINE) {
326    cros->EnableOfflineMode(!cros->offline_mode());
327  } else if (flags & FLAG_ETHERNET) {
328    if (cros->ethernet_connected()) {
329      ShowTabbedNetworkSettings(cros->ethernet_network());
330    }
331  } else if (flags & FLAG_WIFI) {
332    ConnectToNetworkAt(index, std::string(), std::string(), -1);
333  } else if (flags & FLAG_OTHER_NETWORK) {
334    ConnectToNetworkAt(index, std::string(), std::string(), -1);
335  } else if (flags & FLAG_CELLULAR) {
336    ConnectToNetworkAt(index, std::string(), std::string(), -1);
337  }
338}
339
340void NetworkMenu::SetFirstLevelMenuWidth(int width) {
341  min_width_ = width;
342  // This actually has no effect since menu is rebuilt before showing.
343  network_menu_->SetMinimumWidth(width);
344}
345
346void NetworkMenu::CancelMenu() {
347  network_menu_->CancelMenu();
348}
349
350void NetworkMenu::UpdateMenu() {
351  refreshing_menu_ = true;
352  InitMenuItems();
353  network_menu_->Rebuild();
354  refreshing_menu_ = false;
355}
356
357// static
358SkBitmap NetworkMenu::IconForNetworkStrength(const WifiNetwork* wifi,
359                                             bool black) {
360  DCHECK(wifi);
361  // Compose wifi icon by superimposing various icons.
362  int index = static_cast<int>(wifi->strength() / 100.0 *
363      nextafter(static_cast<float>(kNumBarsImages), 0));
364  index = std::max(std::min(index, kNumBarsImages - 1), 0);
365  const int* images = black ? kBarsImagesBlack : kBarsImages;
366  return *ResourceBundle::GetSharedInstance().GetBitmapNamed(images[index]);
367}
368
369// static
370SkBitmap NetworkMenu::IconForNetworkStrength(const CellularNetwork* cellular,
371                                             bool black) {
372  DCHECK(cellular);
373  // If no data, then we show 0 bars.
374  if (cellular->GetDataLeft() == CellularNetwork::DATA_NONE) {
375    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
376        black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
377                IDR_STATUSBAR_NETWORK_BARS0);
378  }
379  // Compose cellular icon by superimposing various icons.
380  int index = static_cast<int>(cellular->strength() / 100.0 *
381      nextafter(static_cast<float>(kNumBarsImages), 0));
382  index = std::max(std::min(index, kNumBarsImages - 1), 0);
383  const int* images = black ? kBarsImagesBlack : kBarsImages;
384  return *ResourceBundle::GetSharedInstance().GetBitmapNamed(images[index]);
385}
386
387// static
388SkBitmap NetworkMenu::IconForNetworkConnecting(double animation_value,
389                                               bool black) {
390  // Draw animation of bars icon fading in and out.
391  // We are fading between 0 bars and a third of the opacity of 4 bars.
392  // Use the current value of the animation to calculate the alpha value
393  // of how transparent the icon is.
394  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
395  return SkBitmapOperations::CreateBlendedBitmap(
396      *rb.GetBitmapNamed(black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
397                                 IDR_STATUSBAR_NETWORK_BARS0),
398      *rb.GetBitmapNamed(black ? IDR_STATUSBAR_NETWORK_BARS4_BLACK :
399                                 IDR_STATUSBAR_NETWORK_BARS4),
400      animation_value / 3);
401}
402
403// static
404// TODO(ers) update for GSM when we have the necessary images
405SkBitmap NetworkMenu::BadgeForNetworkTechnology(
406    const CellularNetwork* cellular) {
407  if (!cellular)
408    return SkBitmap();
409
410  int id = -1;
411  if (cellular->network_technology() == NETWORK_TECHNOLOGY_EVDO) {
412    switch (cellular->GetDataLeft()) {
413      case CellularNetwork::DATA_NONE:
414        id = IDR_STATUSBAR_NETWORK_3G_ERROR;
415        break;
416      case CellularNetwork::DATA_VERY_LOW:
417      case CellularNetwork::DATA_LOW:
418      case CellularNetwork::DATA_NORMAL:
419        id = IDR_STATUSBAR_NETWORK_3G;
420        break;
421    }
422  } else if (cellular->network_technology() == NETWORK_TECHNOLOGY_1XRTT) {
423    switch (cellular->GetDataLeft()) {
424      case CellularNetwork::DATA_NONE:
425        id = IDR_STATUSBAR_NETWORK_1X_ERROR;
426        break;
427      case CellularNetwork::DATA_VERY_LOW:
428      case CellularNetwork::DATA_LOW:
429      case CellularNetwork::DATA_NORMAL:
430        id = IDR_STATUSBAR_NETWORK_1X;
431        break;
432    }
433  }
434  if (id == -1)
435    return SkBitmap();
436  else
437    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(id);
438}
439
440// static
441SkBitmap NetworkMenu::IconForDisplay(SkBitmap icon, SkBitmap badge) {
442  // Draw badge at (14,14).
443  static const int kBadgeX = 14;
444  static const int kBadgeY = 14;
445
446  gfx::CanvasSkia canvas(icon.width(), icon.height(), false);
447  canvas.DrawBitmapInt(icon, 0, 0);
448  if (!badge.empty())
449    canvas.DrawBitmapInt(badge, kBadgeX, kBadgeY);
450  return canvas.ExtractBitmap();
451}
452
453////////////////////////////////////////////////////////////////////////////////
454// NetworkMenu, views::ViewMenuDelegate implementation:
455
456void NetworkMenu::RunMenu(views::View* source, const gfx::Point& pt) {
457  refreshing_menu_ = true;
458  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
459  cros->RequestWifiScan();
460
461  // Build initial menu items. They will be updated when UpdateMenu is
462  // called from NetworkChanged.
463  InitMenuItems();
464  network_menu_->Rebuild();
465
466  // Restore menu width, if it was set up.
467  // NOTE: width isn't checked for correctness here since all width-related
468  // logic implemented inside |network_menu_|.
469  if (min_width_ != -1)
470    network_menu_->SetMinimumWidth(min_width_);
471  refreshing_menu_ = false;
472  network_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
473}
474
475void NetworkMenu::InitMenuItems() {
476  // This gets called on initialization, so any changes should be reflected
477  // in CrosMock::SetNetworkLibraryStatusAreaExpectations().
478
479  menu_items_.clear();
480  // Populate our MenuItems with the current list of wifi networks.
481  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
482  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
483
484  string16 label;
485
486  // Ethernet
487  bool ethernet_available = cros->ethernet_available();
488  bool ethernet_enabled = cros->ethernet_enabled();
489  if (ethernet_available && ethernet_enabled) {
490    bool ethernet_connected = cros->ethernet_connected();
491    bool ethernet_connecting = cros->ethernet_connecting();
492
493    if (ethernet_connecting) {
494      label = l10n_util::GetStringFUTF16(
495          IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
496          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET),
497          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
498    } else {
499      label = l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
500    }
501    SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_WIRED_BLACK);
502    SkBitmap badge = ethernet_connecting || ethernet_connected ?
503        SkBitmap() : *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED);
504    int flag = FLAG_ETHERNET;
505    if (ethernet_connecting || ethernet_connected)
506      flag |= FLAG_ASSOCIATED;
507    menu_items_.push_back(
508        MenuItem(menus::MenuModel::TYPE_COMMAND, label,
509                 IconForDisplay(icon, badge), std::string(), flag));
510  }
511
512  // Wifi Networks
513  bool wifi_available = cros->wifi_available();
514  bool wifi_enabled = cros->wifi_enabled();
515  if (wifi_available && wifi_enabled) {
516    const WifiNetworkVector& wifi_networks = cros->wifi_networks();
517    const WifiNetwork* active_wifi = cros->wifi_network();
518
519    bool separator_added = false;
520    // List Wifi networks.
521    for (size_t i = 0; i < wifi_networks.size(); ++i) {
522      if (wifi_networks[i]->connecting()) {
523        label = l10n_util::GetStringFUTF16(
524            IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
525            ASCIIToUTF16(wifi_networks[i]->name()),
526            l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
527      } else {
528        label = ASCIIToUTF16(wifi_networks[i]->name());
529      }
530
531      // First add a separator if necessary.
532      if (!separator_added) {
533        separator_added = true;
534        if (!menu_items_.empty()) {  // Don't add if first menu item.
535          menu_items_.push_back(MenuItem());  // Separator
536        }
537      }
538
539      SkBitmap icon = IconForNetworkStrength(wifi_networks[i], true);
540      SkBitmap badge = wifi_networks[i]->encrypted() ?
541          *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE) : SkBitmap();
542      int flag = FLAG_WIFI;
543      if (!wifi_networks[i]->connectable())
544        flag |= FLAG_DISABLED;
545      if (active_wifi
546          && wifi_networks[i]->service_path() == active_wifi->service_path())
547        flag |= FLAG_ASSOCIATED;
548      menu_items_.push_back(
549          MenuItem(menus::MenuModel::TYPE_COMMAND, label,
550                   IconForDisplay(icon, badge),
551                   wifi_networks[i]->service_path(), flag));
552    }
553  }
554
555  // Cellular Networks
556  bool cellular_available = cros->cellular_available();
557  bool cellular_enabled = cros->cellular_enabled();
558  if (cellular_available && cellular_enabled) {
559    const CellularNetworkVector& cell_networks = cros->cellular_networks();
560    const CellularNetwork* active_cellular = cros->cellular_network();
561
562    bool separator_added = false;
563    // List Cellular networks.
564    for (size_t i = 0; i < cell_networks.size(); ++i) {
565      chromeos::ActivationState activation_state =
566          cell_networks[i]->activation_state();
567
568      // If we are on the OOBE/login screen, do not show activating 3G option.
569      if (!IsBrowserMode() && activation_state != ACTIVATION_STATE_ACTIVATED)
570        continue;
571
572      if (activation_state == ACTIVATION_STATE_NOT_ACTIVATED ||
573          activation_state == ACTIVATION_STATE_PARTIALLY_ACTIVATED) {
574        label = l10n_util::GetStringFUTF16(
575            IDS_STATUSBAR_NETWORK_DEVICE_ACTIVATE,
576            ASCIIToUTF16(cell_networks[i]->name()));
577      } else if (activation_state == ACTIVATION_STATE_ACTIVATING) {
578        label = l10n_util::GetStringFUTF16(
579            IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
580            ASCIIToUTF16(cell_networks[i]->name()),
581            l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ACTIVATING));
582      } else if (cell_networks[i]->connecting()) {
583        label = l10n_util::GetStringFUTF16(
584            IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
585            ASCIIToUTF16(cell_networks[i]->name()),
586            l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
587      } else {
588        label = ASCIIToUTF16(cell_networks[i]->name());
589      }
590
591      // First add a separator if necessary.
592      if (!separator_added) {
593        separator_added = true;
594        if (!menu_items_.empty()) {  // Don't add if first menu item.
595          menu_items_.push_back(MenuItem());  // Separator
596        }
597      }
598
599      SkBitmap icon = IconForNetworkStrength(cell_networks[i], true);
600      SkBitmap badge = BadgeForNetworkTechnology(cell_networks[i]);
601      int flag = FLAG_CELLULAR;
602      if (!cell_networks[i]->connectable())
603        flag |= FLAG_DISABLED;
604      bool isActive = active_cellular &&
605          cell_networks[i]->service_path() == active_cellular->service_path() &&
606          (cell_networks[i]->connecting() || cell_networks[i]->connected());
607      if (isActive)
608        flag |= FLAG_ASSOCIATED;
609      menu_items_.push_back(
610          MenuItem(menus::MenuModel::TYPE_COMMAND, label,
611                   IconForDisplay(icon, badge),
612                   cell_networks[i]->service_path(), flag));
613      if (isActive) {
614        label.clear();
615        if (active_cellular->needs_new_plan()) {
616          label = l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_NO_PLAN_LABEL);
617        } else {
618          const chromeos::CellularDataPlan* plan =
619              active_cellular->GetSignificantDataPlan();
620          if (plan)
621            label = plan->GetUsageInfo();
622        }
623        if (label.length()) {
624          menu_items_.push_back(
625              MenuItem(menus::MenuModel::TYPE_COMMAND,
626                       label, SkBitmap(),
627                       std::string(), FLAG_DISABLED));
628        }
629      }
630    }
631  }
632
633  // No networks available message.
634  if (menu_items_.empty()) {
635    label = l10n_util::GetStringFUTF16(IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT,
636                l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE));
637    menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
638        SkBitmap(), std::string(), FLAG_DISABLED));
639  }
640
641  // Add network.
642  if (wifi_available && wifi_enabled) {
643    menu_items_.push_back(MenuItem());  // Separator
644    menu_items_.push_back(MenuItem(
645        menus::MenuModel::TYPE_COMMAND,
646        l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_NETWORKS),
647        IconForDisplay(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0_BLACK),
648                       SkBitmap()),
649        std::string(), FLAG_OTHER_NETWORK));
650  }
651
652  // Enable / disable wireless.
653  if (wifi_available || cellular_available) {
654    menu_items_.push_back(MenuItem());  // Separator
655
656    if (wifi_available) {
657      // Add 'Scanning...'
658      if (cros->wifi_scanning()) {
659        label = l10n_util::GetStringUTF16(IDS_STATUSBAR_WIFI_SCANNING_MESSAGE);
660        menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
661            SkBitmap(), std::string(), FLAG_DISABLED));
662      }
663
664      int id = wifi_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
665                              IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
666      label = l10n_util::GetStringFUTF16(id,
667          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
668      menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
669          SkBitmap(), std::string(), FLAG_TOGGLE_WIFI));
670    }
671
672    if (cellular_available) {
673      int id = cellular_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
674                                  IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
675      label = l10n_util::GetStringFUTF16(id,
676          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR));
677      menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
678          SkBitmap(), std::string(), FLAG_TOGGLE_CELLULAR));
679    }
680  }
681
682  // Offline mode.
683  // TODO(chocobo): Uncomment once we figure out how to do offline mode.
684  // menu_items_.push_back(MenuItem(cros->offline_mode() ?
685  //     menus::MenuModel::TYPE_CHECK : menus::MenuModel::TYPE_COMMAND,
686  //     l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_OFFLINE_MODE),
687  //     SkBitmap(), std::string(), FLAG_TOGGLE_OFFLINE));
688
689  bool connected = cros->Connected();  // always call for test expectations.
690  bool oobe = !ShouldOpenButtonOptions();  // we don't show options for OOBE.
691  // Network settings. (And IP Address)
692  if (!oobe) {
693    menu_items_.push_back(MenuItem());  // Separator
694
695    if (!MenuUI::IsEnabled() && connected) {
696      std::string ip_address = cros->IPAddress();
697      if (!ip_address.empty()) {
698        menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND,
699            ASCIIToUTF16(cros->IPAddress()), SkBitmap(), std::string(),
700                         FLAG_DISABLED));
701      }
702    }
703
704    label = l10n_util::GetStringUTF16(IsBrowserMode() ?
705        IDS_STATUSBAR_NETWORK_OPEN_OPTIONS_DIALOG :
706        IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG);
707    menu_items_.push_back(MenuItem(menus::MenuModel::TYPE_COMMAND, label,
708                                   SkBitmap(), std::string(), FLAG_OPTIONS));
709  }
710}
711
712void NetworkMenu::ShowTabbedNetworkSettings(const Network* network) const {
713  DCHECK(network);
714  Browser* browser = BrowserList::GetLastActive();
715  if (!browser)
716    return;
717  std::string page = StringPrintf("%s?servicePath=%s&networkType=%d",
718      chrome::kInternetOptionsSubPage,
719      EscapeUrlEncodedData(network->service_path()).c_str(),
720      network->type());
721  browser->ShowOptionsTab(page);
722}
723
724// TODO(stevenjb): deprecate this once we've committed to tabbed settings
725// and the embedded menu UI (and fully deprecated NetworkConfigView).
726// Meanwhile, if MenuUI::IsEnabled() is true, always show the settings UI,
727// otherwise show NetworkConfigView only to get passwords when not connected.
728void NetworkMenu::ShowNetworkConfigView(NetworkConfigView* view) const {
729  view->set_browser_mode(IsBrowserMode());
730  views::Window* window = browser::CreateViewsWindow(
731      GetNativeWindow(), gfx::Rect(), view);
732  window->SetIsAlwaysOnTop(true);
733  window->Show();
734}
735
736void NetworkMenu::ActivateCellular(const CellularNetwork* cellular) const {
737  DCHECK(cellular);
738  Browser* browser = BrowserList::GetLastActive();
739  if (!browser)
740    return;
741  browser->OpenMobilePlanTabAndActivate();
742}
743
744void NetworkMenu::ShowOther() const {
745  if (use_settings_ui_ && MenuUI::IsEnabled()) {
746    Browser* browser = BrowserList::GetLastActive();
747    if (browser) {
748      std::string page = StringPrintf("%s?networkType=%d",
749                                      chrome::kInternetOptionsSubPage,
750                                      chromeos::TYPE_WIFI);
751      browser->ShowOptionsTab(page);
752    }
753  } else {
754    ShowNetworkConfigView(new NetworkConfigView());
755  }
756}
757
758}  // namespace chromeos
759