network_menu.cc revision 72a454cd3513ac24fbdd0e0cb9ad70b86a99b801
1// Copyright (c) 2011 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 "base/command_line.h"
10#include "base/stringprintf.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/chromeos/cros/cros_library.h"
13#include "chrome/browser/chromeos/dom_ui/network_menu_ui.h"
14#include "chrome/browser/ui/browser.h"
15#include "chrome/browser/ui/browser_list.h"
16#include "chrome/common/chrome_switches.h"
17#include "chrome/common/url_constants.h"
18#include "chrome/browser/ui/views/window.h"
19#include "grit/generated_resources.h"
20#include "grit/theme_resources.h"
21#include "net/base/escape.h"
22#include "ui/base/l10n/l10n_util.h"
23#include "ui/base/resource/resource_bundle.h"
24#include "ui/gfx/canvas_skia.h"
25#include "ui/gfx/skbitmap_operations.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 Web 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, ui::MenuModel implementation:
274
275int NetworkMenu::GetItemCount() const {
276  return static_cast<int>(menu_items_.size());
277}
278
279ui::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 ui::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  if (wifi->strength() == 0) {
362    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
363        black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
364                IDR_STATUSBAR_NETWORK_BARS0);
365  }
366  int index = static_cast<int>(wifi->strength() / 100.0 *
367      nextafter(static_cast<float>(kNumBarsImages), 0));
368  index = std::max(std::min(index, kNumBarsImages - 1), 0);
369  const int* images = black ? kBarsImagesBlack : kBarsImages;
370  return *ResourceBundle::GetSharedInstance().GetBitmapNamed(images[index]);
371}
372
373// static
374SkBitmap NetworkMenu::IconForNetworkStrength(const CellularNetwork* cellular,
375                                             bool black) {
376  DCHECK(cellular);
377  // If no data, then we show 0 bars.
378  if (cellular->strength() == 0 ||
379      cellular->GetDataLeft() == CellularNetwork::DATA_NONE) {
380    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(
381        black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
382                IDR_STATUSBAR_NETWORK_BARS0);
383  }
384  int index = static_cast<int>(cellular->strength() / 100.0 *
385      nextafter(static_cast<float>(kNumBarsImages), 0));
386  index = std::max(std::min(index, kNumBarsImages - 1), 0);
387  const int* images = black ? kBarsImagesBlack : kBarsImages;
388  return *ResourceBundle::GetSharedInstance().GetBitmapNamed(images[index]);
389}
390
391// static
392SkBitmap NetworkMenu::IconForNetworkConnecting(double animation_value,
393                                               bool black) {
394  // Draw animation of bars icon fading in and out.
395  // We are fading between 0 bars and a third of the opacity of 4 bars.
396  // Use the current value of the animation to calculate the alpha value
397  // of how transparent the icon is.
398  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
399  return SkBitmapOperations::CreateBlendedBitmap(
400      *rb.GetBitmapNamed(black ? IDR_STATUSBAR_NETWORK_BARS0_BLACK :
401                                 IDR_STATUSBAR_NETWORK_BARS0),
402      *rb.GetBitmapNamed(black ? IDR_STATUSBAR_NETWORK_BARS4_BLACK :
403                                 IDR_STATUSBAR_NETWORK_BARS4),
404      animation_value / 3);
405}
406
407// static
408// TODO(ers) update for GSM when we have the necessary images
409SkBitmap NetworkMenu::BadgeForNetworkTechnology(
410    const CellularNetwork* cellular) {
411  if (!cellular)
412    return SkBitmap();
413
414  int id = -1;
415  if (cellular->network_technology() == NETWORK_TECHNOLOGY_EVDO) {
416    switch (cellular->GetDataLeft()) {
417      case CellularNetwork::DATA_NONE:
418        id = IDR_STATUSBAR_NETWORK_3G_ERROR;
419        break;
420      case CellularNetwork::DATA_VERY_LOW:
421      case CellularNetwork::DATA_LOW:
422      case CellularNetwork::DATA_NORMAL:
423        id = IDR_STATUSBAR_NETWORK_3G;
424        break;
425      case CellularNetwork::DATA_UNKNOWN:
426        id = IDR_STATUSBAR_NETWORK_3G_UNKNOWN;
427        break;
428    }
429  } else if (cellular->network_technology() == NETWORK_TECHNOLOGY_1XRTT) {
430    switch (cellular->GetDataLeft()) {
431      case CellularNetwork::DATA_NONE:
432        id = IDR_STATUSBAR_NETWORK_1X_ERROR;
433        break;
434      case CellularNetwork::DATA_VERY_LOW:
435      case CellularNetwork::DATA_LOW:
436      case CellularNetwork::DATA_NORMAL:
437        id = IDR_STATUSBAR_NETWORK_1X;
438        break;
439      case CellularNetwork::DATA_UNKNOWN:
440        id = IDR_STATUSBAR_NETWORK_1X_UNKNOWN;
441        break;
442    }
443  }
444  if (id == -1)
445    return SkBitmap();
446  else
447    return *ResourceBundle::GetSharedInstance().GetBitmapNamed(id);
448}
449
450// static
451SkBitmap NetworkMenu::IconForDisplay(SkBitmap icon, SkBitmap badge) {
452  // Draw badge at (14,14).
453  static const int kBadgeX = 14;
454  static const int kBadgeY = 14;
455
456  gfx::CanvasSkia canvas(icon.width(), icon.height(), false);
457  canvas.DrawBitmapInt(icon, 0, 0);
458  if (!badge.empty())
459    canvas.DrawBitmapInt(badge, kBadgeX, kBadgeY);
460  return canvas.ExtractBitmap();
461}
462
463////////////////////////////////////////////////////////////////////////////////
464// NetworkMenu, views::ViewMenuDelegate implementation:
465
466void NetworkMenu::RunMenu(views::View* source, const gfx::Point& pt) {
467  refreshing_menu_ = true;
468  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
469  cros->RequestWifiScan();
470
471  // Build initial menu items. They will be updated when UpdateMenu is
472  // called from NetworkChanged.
473  InitMenuItems();
474  network_menu_->Rebuild();
475
476  // Restore menu width, if it was set up.
477  // NOTE: width isn't checked for correctness here since all width-related
478  // logic implemented inside |network_menu_|.
479  if (min_width_ != -1)
480    network_menu_->SetMinimumWidth(min_width_);
481  refreshing_menu_ = false;
482  network_menu_->RunMenuAt(pt, views::Menu2::ALIGN_TOPRIGHT);
483}
484
485void NetworkMenu::InitMenuItems() {
486  // This gets called on initialization, so any changes should be reflected
487  // in CrosMock::SetNetworkLibraryStatusAreaExpectations().
488
489  menu_items_.clear();
490  // Populate our MenuItems with the current list of wifi networks.
491  NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary();
492  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
493
494  string16 label;
495
496  if (cros->IsLocked()) {
497    label = l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_LOCKED);
498    menu_items_.push_back(
499        MenuItem(ui::MenuModel::TYPE_COMMAND,
500                 label, SkBitmap(),
501                 std::string(), FLAG_DISABLED));
502    return;
503  }
504
505  // Ethernet
506  bool ethernet_available = cros->ethernet_available();
507  bool ethernet_enabled = cros->ethernet_enabled();
508  if (ethernet_available && ethernet_enabled) {
509    bool ethernet_connected = cros->ethernet_connected();
510    bool ethernet_connecting = cros->ethernet_connecting();
511
512    if (ethernet_connecting) {
513      label = l10n_util::GetStringFUTF16(
514          IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
515          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET),
516          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
517    } else {
518      label = l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
519    }
520    SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_WIRED_BLACK);
521    SkBitmap badge = ethernet_connecting || ethernet_connected ?
522        SkBitmap() : *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED);
523    int flag = FLAG_ETHERNET;
524    if (ethernet_connecting || ethernet_connected)
525      flag |= FLAG_ASSOCIATED;
526    menu_items_.push_back(
527        MenuItem(ui::MenuModel::TYPE_COMMAND, label,
528                 IconForDisplay(icon, badge), std::string(), flag));
529  }
530
531  // Wifi Networks
532  bool wifi_available = cros->wifi_available();
533  bool wifi_enabled = cros->wifi_enabled();
534  if (wifi_available && wifi_enabled) {
535    const WifiNetworkVector& wifi_networks = cros->wifi_networks();
536    const WifiNetwork* active_wifi = cros->wifi_network();
537
538    bool separator_added = false;
539    // List Wifi networks.
540    for (size_t i = 0; i < wifi_networks.size(); ++i) {
541      if (wifi_networks[i]->connecting()) {
542        label = l10n_util::GetStringFUTF16(
543            IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
544            ASCIIToUTF16(wifi_networks[i]->name()),
545            l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
546      } else {
547        label = ASCIIToUTF16(wifi_networks[i]->name());
548      }
549
550      // First add a separator if necessary.
551      if (!separator_added) {
552        separator_added = true;
553        if (!menu_items_.empty()) {  // Don't add if first menu item.
554          menu_items_.push_back(MenuItem());  // Separator
555        }
556      }
557
558      SkBitmap icon = IconForNetworkStrength(wifi_networks[i], true);
559      SkBitmap badge = wifi_networks[i]->encrypted() ?
560          *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE) : SkBitmap();
561      int flag = FLAG_WIFI;
562      if (!wifi_networks[i]->connectable())
563        flag |= FLAG_DISABLED;
564      if (active_wifi
565          && wifi_networks[i]->service_path() == active_wifi->service_path())
566        flag |= FLAG_ASSOCIATED;
567      menu_items_.push_back(
568          MenuItem(ui::MenuModel::TYPE_COMMAND, label,
569                   IconForDisplay(icon, badge),
570                   wifi_networks[i]->service_path(), flag));
571    }
572  }
573
574  // Cellular Networks
575  bool cellular_available = cros->cellular_available();
576  bool cellular_enabled = cros->cellular_enabled();
577  if (cellular_available && cellular_enabled) {
578    const CellularNetworkVector& cell_networks = cros->cellular_networks();
579    const CellularNetwork* active_cellular = cros->cellular_network();
580
581    bool separator_added = false;
582    // List Cellular networks.
583    for (size_t i = 0; i < cell_networks.size(); ++i) {
584      chromeos::ActivationState activation_state =
585          cell_networks[i]->activation_state();
586
587      // If we are on the OOBE/login screen, do not show activating 3G option.
588      if (!IsBrowserMode() && activation_state != ACTIVATION_STATE_ACTIVATED)
589        continue;
590
591      if (activation_state == ACTIVATION_STATE_NOT_ACTIVATED ||
592          activation_state == ACTIVATION_STATE_PARTIALLY_ACTIVATED) {
593        label = l10n_util::GetStringFUTF16(
594            IDS_STATUSBAR_NETWORK_DEVICE_ACTIVATE,
595            ASCIIToUTF16(cell_networks[i]->name()));
596      } else if (activation_state == ACTIVATION_STATE_ACTIVATING) {
597        label = l10n_util::GetStringFUTF16(
598            IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
599            ASCIIToUTF16(cell_networks[i]->name()),
600            l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ACTIVATING));
601      } else if (cell_networks[i]->connecting()) {
602        label = l10n_util::GetStringFUTF16(
603            IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
604            ASCIIToUTF16(cell_networks[i]->name()),
605            l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
606      } else {
607        label = ASCIIToUTF16(cell_networks[i]->name());
608      }
609
610      // First add a separator if necessary.
611      if (!separator_added) {
612        separator_added = true;
613        if (!menu_items_.empty()) {  // Don't add if first menu item.
614          menu_items_.push_back(MenuItem());  // Separator
615        }
616      }
617
618      SkBitmap icon = IconForNetworkStrength(cell_networks[i], true);
619      SkBitmap badge = BadgeForNetworkTechnology(cell_networks[i]);
620      int flag = FLAG_CELLULAR;
621      if (!cell_networks[i]->connectable())
622        flag |= FLAG_DISABLED;
623      bool isActive = active_cellular &&
624          cell_networks[i]->service_path() == active_cellular->service_path() &&
625          (cell_networks[i]->connecting() || cell_networks[i]->connected());
626      if (isActive)
627        flag |= FLAG_ASSOCIATED;
628      menu_items_.push_back(
629          MenuItem(ui::MenuModel::TYPE_COMMAND, label,
630                   IconForDisplay(icon, badge),
631                   cell_networks[i]->service_path(), flag));
632      if (isActive) {
633        label.clear();
634        if (active_cellular->needs_new_plan()) {
635          label = l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_NO_PLAN_LABEL);
636        } else {
637          const chromeos::CellularDataPlan* plan =
638              active_cellular->GetSignificantDataPlan();
639          if (plan)
640            label = plan->GetUsageInfo();
641        }
642        if (label.length()) {
643          menu_items_.push_back(
644              MenuItem(ui::MenuModel::TYPE_COMMAND,
645                       label, SkBitmap(),
646                       std::string(), FLAG_DISABLED));
647        }
648      }
649    }
650  }
651
652  // No networks available message.
653  if (menu_items_.empty()) {
654    label = l10n_util::GetStringFUTF16(IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT,
655                l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE));
656    menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
657        SkBitmap(), std::string(), FLAG_DISABLED));
658  }
659
660  // Add network.
661  if (wifi_available && wifi_enabled) {
662    menu_items_.push_back(MenuItem());  // Separator
663    menu_items_.push_back(MenuItem(
664        ui::MenuModel::TYPE_COMMAND,
665        l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_NETWORKS),
666        IconForDisplay(*rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0_BLACK),
667                       SkBitmap()),
668        std::string(), FLAG_OTHER_NETWORK));
669  }
670
671  // Enable / disable wireless.
672  if (wifi_available || cellular_available) {
673    menu_items_.push_back(MenuItem());  // Separator
674
675    if (wifi_available) {
676      // Add 'Scanning...'
677      if (cros->wifi_scanning()) {
678        label = l10n_util::GetStringUTF16(IDS_STATUSBAR_WIFI_SCANNING_MESSAGE);
679        menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
680            SkBitmap(), std::string(), FLAG_DISABLED));
681      }
682
683      int id = wifi_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
684                              IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
685      label = l10n_util::GetStringFUTF16(id,
686          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
687      menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
688          SkBitmap(), std::string(), FLAG_TOGGLE_WIFI));
689    }
690
691    if (cellular_available) {
692      int id = cellular_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
693                                  IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
694      label = l10n_util::GetStringFUTF16(id,
695          l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR));
696      menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
697          SkBitmap(), std::string(), FLAG_TOGGLE_CELLULAR));
698    }
699  }
700
701  // Offline mode.
702  // TODO(chocobo): Uncomment once we figure out how to do offline mode.
703  // menu_items_.push_back(MenuItem(cros->offline_mode() ?
704  //     ui::MenuModel::TYPE_CHECK : ui::MenuModel::TYPE_COMMAND,
705  //     l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_OFFLINE_MODE),
706  //     SkBitmap(), std::string(), FLAG_TOGGLE_OFFLINE));
707
708  bool connected = cros->Connected();  // always call for test expectations.
709  bool oobe = !ShouldOpenButtonOptions();  // we don't show options for OOBE.
710  // Network settings. (And IP Address)
711  if (!oobe) {
712    menu_items_.push_back(MenuItem());  // Separator
713
714    if (!MenuUI::IsEnabled() && connected) {
715      std::string ip_address = cros->IPAddress();
716      if (!ip_address.empty()) {
717        menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND,
718            ASCIIToUTF16(cros->IPAddress()), SkBitmap(), std::string(),
719                         FLAG_DISABLED));
720      }
721    }
722
723    label = l10n_util::GetStringUTF16(IsBrowserMode() ?
724        IDS_STATUSBAR_NETWORK_OPEN_OPTIONS_DIALOG :
725        IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG);
726    menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
727                                   SkBitmap(), std::string(), FLAG_OPTIONS));
728  }
729}
730
731void NetworkMenu::ShowTabbedNetworkSettings(const Network* network) const {
732  DCHECK(network);
733  Browser* browser = BrowserList::GetLastActive();
734  if (!browser)
735    return;
736  std::string page = StringPrintf("%s?servicePath=%s&networkType=%d",
737      chrome::kInternetOptionsSubPage,
738      EscapeUrlEncodedData(network->service_path()).c_str(),
739      network->type());
740  browser->ShowOptionsTab(page);
741}
742
743// TODO(stevenjb): deprecate this once we've committed to tabbed settings
744// and the embedded menu UI (and fully deprecated NetworkConfigView).
745// Meanwhile, if MenuUI::IsEnabled() is true, always show the settings UI,
746// otherwise show NetworkConfigView only to get passwords when not connected.
747void NetworkMenu::ShowNetworkConfigView(NetworkConfigView* view) const {
748  view->set_browser_mode(IsBrowserMode());
749  views::Window* window = browser::CreateViewsWindow(
750      GetNativeWindow(), gfx::Rect(), view);
751  window->SetIsAlwaysOnTop(true);
752  window->Show();
753}
754
755void NetworkMenu::ActivateCellular(const CellularNetwork* cellular) const {
756  DCHECK(cellular);
757  Browser* browser = BrowserList::GetLastActive();
758  if (!browser)
759    return;
760  browser->OpenMobilePlanTabAndActivate();
761}
762
763void NetworkMenu::ShowOther() const {
764  if (use_settings_ui_ && MenuUI::IsEnabled()) {
765    Browser* browser = BrowserList::GetLastActive();
766    if (browser) {
767      std::string page = StringPrintf("%s?networkType=%d",
768                                      chrome::kInternetOptionsSubPage,
769                                      chromeos::TYPE_WIFI);
770      browser->ShowOptionsTab(page);
771    }
772  } else {
773    ShowNetworkConfigView(new NetworkConfigView());
774  }
775}
776
777}  // namespace chromeos
778