This source file includes following definitions.
- EscapeAmpersands
- ShouldHighlightNetwork
- ToggleTechnology
- menu_items
- more_menu_model_
- ConnectToNetworkAt
- HasIcons
- GetItemCount
- GetTypeAt
- GetSeparatorTypeAt
- GetLabelAt
- IsItemDynamicAt
- GetLabelFontListAt
- GetAcceleratorAt
- IsItemCheckedAt
- GetGroupIdAt
- GetIconAt
- GetButtonMenuItemAt
- IsEnabledAt
- IsVisibleAt
- GetSubmenuModelAt
- HighlightChangedTo
- ActivatedAt
- SetMenuModelDelegate
- GetMenuModelDelegate
- ShowOther
- AddWirelessNetworkMenuItem
- AddMessageItem
- InitMenuItems
- GetCommandIdAt
- InitMenuItems
- GetCommandIdAt
- weak_pointer_factory_
- GetMenuModel
- UpdateMenu
#include "chrome/browser/chromeos/status/network_menu.h"
#include <algorithm>
#include "ash/shell.h"
#include "ash/shell_delegate.h"
#include "ash/system/chromeos/network/network_connect.h"
#include "ash/system/chromeos/network/network_icon.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/chromeos/choose_mobile_network_dialog.h"
#include "chrome/browser/chromeos/login/user_manager.h"
#include "chrome/browser/chromeos/mobile_config.h"
#include "chrome/browser/chromeos/options/network_config_view.h"
#include "chrome/browser/chromeos/sim_dialog_delegate.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/common/url_constants.h"
#include "chromeos/network/device_state.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/shill_property_util.h"
#include "grit/ash_resources.h"
#include "grit/ash_strings.h"
#include "grit/generated_resources.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/menu_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia.h"
namespace chromeos {
namespace {
const int kMainIndexMask = 0x1000;
const int kMoreIndexMask = 0x4000;
std::string EscapeAmpersands(const std::string& input) {
std::string str = input;
size_t found = str.find('&');
while (found != std::string::npos) {
str.replace(found, 1, "&&");
found = str.find('&', found + 2);
}
return str;
}
bool ShouldHighlightNetwork(const NetworkState* network) {
return network->IsConnectedState() || network->IsConnectingState();
}
void ToggleTechnology(const NetworkTypePattern& technology) {
NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
bool is_enabled = handler->IsTechnologyEnabled(technology);
ash::network_connect::SetTechnologyEnabled(technology, !is_enabled);
}
}
class NetworkMenuModel : public ui::MenuModel {
public:
struct MenuItem {
MenuItem()
: type(ui::MenuModel::TYPE_SEPARATOR),
sub_menu_model(NULL),
flags(0) {
}
MenuItem(ui::MenuModel::ItemType type, base::string16 label, gfx::ImageSkia icon,
const std::string& service_path, int flags)
: type(type),
label(label),
icon(icon),
service_path(service_path),
sub_menu_model(NULL),
flags(flags) {
}
MenuItem(ui::MenuModel::ItemType type, base::string16 label, gfx::ImageSkia icon,
NetworkMenuModel* sub_menu_model, int flags)
: type(type),
label(label),
icon(icon),
sub_menu_model(sub_menu_model),
flags(flags) {
}
ui::MenuModel::ItemType type;
base::string16 label;
gfx::ImageSkia icon;
std::string service_path;
NetworkMenuModel* sub_menu_model;
int flags;
};
typedef std::vector<MenuItem> MenuItemVector;
explicit NetworkMenuModel(const base::WeakPtr<NetworkMenu>& owner)
: owner_(owner) {}
virtual ~NetworkMenuModel() {}
void ConnectToNetworkAt(int index);
virtual void InitMenuItems(bool should_open_button_options) = 0;
const MenuItemVector& menu_items() const { return menu_items_; }
virtual bool HasIcons() const OVERRIDE;
virtual int GetItemCount() const OVERRIDE;
virtual ui::MenuModel::ItemType GetTypeAt(int index) const OVERRIDE;
virtual ui::MenuSeparatorType GetSeparatorTypeAt(int index) const OVERRIDE;
virtual base::string16 GetLabelAt(int index) const OVERRIDE;
virtual bool IsItemDynamicAt(int index) const OVERRIDE;
virtual const gfx::FontList* GetLabelFontListAt(int index) const OVERRIDE;
virtual bool GetAcceleratorAt(int index,
ui::Accelerator* accelerator) const OVERRIDE;
virtual bool IsItemCheckedAt(int index) const OVERRIDE;
virtual int GetGroupIdAt(int index) const OVERRIDE;
virtual bool GetIconAt(int index, gfx::Image* icon) OVERRIDE;
virtual ui::ButtonMenuItemModel* GetButtonMenuItemAt(
int index) const OVERRIDE;
virtual bool IsEnabledAt(int index) const OVERRIDE;
virtual bool IsVisibleAt(int index) const OVERRIDE;
virtual ui::MenuModel* GetSubmenuModelAt(int index) const OVERRIDE;
virtual void HighlightChangedTo(int index) OVERRIDE;
virtual void ActivatedAt(int index) OVERRIDE;
virtual void SetMenuModelDelegate(ui::MenuModelDelegate* delegate) OVERRIDE;
virtual ui::MenuModelDelegate* GetMenuModelDelegate() const OVERRIDE;
protected:
enum MenuItemFlags {
FLAG_NONE = 0,
FLAG_DISABLED = 1 << 0,
FLAG_TOGGLE_WIFI = 1 << 2,
FLAG_TOGGLE_MOBILE = 1 << 3,
FLAG_ASSOCIATED = 1 << 5,
FLAG_ETHERNET = 1 << 6,
FLAG_WIFI = 1 << 7,
FLAG_WIMAX = 1 << 8,
FLAG_CELLULAR = 1 << 9,
FLAG_OPTIONS = 1 << 10,
FLAG_ADD_WIFI = 1 << 11,
FLAG_ADD_CELLULAR = 1 << 12,
};
MenuItemVector menu_items_;
base::WeakPtr<NetworkMenu> owner_;
private:
void ShowOther(const std::string& type) const;
DISALLOW_COPY_AND_ASSIGN(NetworkMenuModel);
};
class MoreMenuModel : public NetworkMenuModel {
public:
explicit MoreMenuModel(const base::WeakPtr<NetworkMenu> owner)
: NetworkMenuModel(owner) {}
virtual ~MoreMenuModel() {}
virtual void InitMenuItems(bool should_open_button_options) OVERRIDE;
virtual int GetCommandIdAt(int index) const OVERRIDE;
private:
DISALLOW_COPY_AND_ASSIGN(MoreMenuModel);
};
class MainMenuModel : public NetworkMenuModel {
public:
explicit MainMenuModel(const base::WeakPtr<NetworkMenu>& owner)
: NetworkMenuModel(owner),
more_menu_model_(new MoreMenuModel(owner)) {
}
virtual ~MainMenuModel() {}
virtual void InitMenuItems(bool should_open_button_options) OVERRIDE;
virtual int GetCommandIdAt(int index) const OVERRIDE;
private:
void AddWirelessNetworkMenuItem(const NetworkState* wifi_network, int flag);
void AddMessageItem(const base::string16& msg);
scoped_ptr<MoreMenuModel> more_menu_model_;
DISALLOW_COPY_AND_ASSIGN(MainMenuModel);
};
void NetworkMenuModel::ConnectToNetworkAt(int index) {
const std::string& service_path = menu_items_[index].service_path;
gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow();
ash::network_connect::ConnectToNetwork(service_path, native_window);
}
bool NetworkMenuModel::HasIcons() const {
return true;
}
int NetworkMenuModel::GetItemCount() const {
return static_cast<int>(menu_items_.size());
}
ui::MenuModel::ItemType NetworkMenuModel::GetTypeAt(int index) const {
return menu_items_[index].type;
}
ui::MenuSeparatorType NetworkMenuModel::GetSeparatorTypeAt(int index) const {
return ui::NORMAL_SEPARATOR;
}
base::string16 NetworkMenuModel::GetLabelAt(int index) const {
return menu_items_[index].label;
}
bool NetworkMenuModel::IsItemDynamicAt(int index) const {
return false;
}
const gfx::FontList* NetworkMenuModel::GetLabelFontListAt(int index) const {
const gfx::FontList* font_list = NULL;
if (menu_items_[index].flags & FLAG_ASSOCIATED) {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
font_list = &rb.GetFontList(browser_defaults::kAssociatedNetworkFontStyle);
}
return font_list;
}
bool NetworkMenuModel::GetAcceleratorAt(int index,
ui::Accelerator* accelerator) const {
return false;
}
bool NetworkMenuModel::IsItemCheckedAt(int index) const {
return true;
}
int NetworkMenuModel::GetGroupIdAt(int index) const {
return 0;
}
bool NetworkMenuModel::GetIconAt(int index, gfx::Image* icon) {
if (!menu_items_[index].icon.isNull()) {
*icon = gfx::Image(menu_items_[index].icon);
return true;
}
return false;
}
ui::ButtonMenuItemModel* NetworkMenuModel::GetButtonMenuItemAt(
int index) const {
return NULL;
}
bool NetworkMenuModel::IsEnabledAt(int index) const {
return !(menu_items_[index].flags & FLAG_DISABLED);
}
bool NetworkMenuModel::IsVisibleAt(int index) const {
return true;
}
ui::MenuModel* NetworkMenuModel::GetSubmenuModelAt(int index) const {
return menu_items_[index].sub_menu_model;
}
void NetworkMenuModel::HighlightChangedTo(int index) {
}
void NetworkMenuModel::ActivatedAt(int index) {
if (owner_->refreshing_menu_)
return;
int flags = menu_items_[index].flags;
if (flags & FLAG_OPTIONS) {
owner_->delegate()->OpenButtonOptions();
} else if (flags & FLAG_TOGGLE_WIFI) {
ToggleTechnology(NetworkTypePattern::WiFi());
} else if (flags & FLAG_TOGGLE_MOBILE) {
ToggleTechnology(NetworkTypePattern::Mobile());
} else if (flags & FLAG_ETHERNET) {
owner_->delegate()->OnConnectToNetworkRequested(
menu_items_[index].service_path);
} else if (flags & (FLAG_WIFI | FLAG_WIMAX | FLAG_CELLULAR)) {
ConnectToNetworkAt(index);
owner_->delegate()->OnConnectToNetworkRequested(
menu_items_[index].service_path);
} else if (flags & FLAG_ADD_WIFI) {
ShowOther(shill::kTypeWifi);
} else if (flags & FLAG_ADD_CELLULAR) {
ShowOther(shill::kTypeCellular);
}
}
void NetworkMenuModel::SetMenuModelDelegate(ui::MenuModelDelegate* delegate) {
}
ui::MenuModelDelegate* NetworkMenuModel::GetMenuModelDelegate() const {
return NULL;
}
void NetworkMenuModel::ShowOther(const std::string& type) const {
gfx::NativeWindow native_window = owner_->delegate()->GetNativeWindow();
if (type == shill::kTypeCellular)
ChooseMobileNetworkDialog::ShowDialog(native_window);
else
NetworkConfigView::ShowForType(shill::kTypeWifi, native_window);
}
void MainMenuModel::AddWirelessNetworkMenuItem(const NetworkState* network,
int flag) {
base::string16 label;
std::string wifi_name = EscapeAmpersands(network->name());
if (network->IsConnectingState()) {
label = l10n_util::GetStringFUTF16(
IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
base::UTF8ToUTF16(wifi_name),
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
} else {
label = base::UTF8ToUTF16(wifi_name);
}
if (ShouldHighlightNetwork(network))
flag |= FLAG_ASSOCIATED;
const gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork(
network, ash::network_icon::ICON_TYPE_LIST);
menu_items_.push_back(
MenuItem(ui::MenuModel::TYPE_COMMAND,
label, icon, network->path(), flag));
}
void MainMenuModel::AddMessageItem(const base::string16& msg) {
menu_items_.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND, msg,
gfx::ImageSkia(), std::string(), FLAG_DISABLED));
}
void MainMenuModel::InitMenuItems(bool should_open_button_options) {
menu_items_.clear();
NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
base::string16 label;
bool ethernet_enabled =
handler->IsTechnologyEnabled(NetworkTypePattern::Ethernet());
const NetworkState* ethernet_network =
handler->FirstNetworkByType(NetworkTypePattern::Ethernet());
if (ethernet_enabled && ethernet_network) {
bool ethernet_connecting = ethernet_network->IsConnectingState();
if (ethernet_connecting) {
label = l10n_util::GetStringFUTF16(
IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET),
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
} else {
label = l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET);
}
int flag = FLAG_ETHERNET;
if (ShouldHighlightNetwork(ethernet_network))
flag |= FLAG_ASSOCIATED;
const gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork(
ethernet_network, ash::network_icon::ICON_TYPE_LIST);
menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND,
label, icon, std::string(), flag));
}
NetworkStateHandler::NetworkStateList network_list;
handler->GetNetworkList(&network_list);
if (handler->IsTechnologyEnabled(NetworkTypePattern::Cellular())) {
for (NetworkStateHandler::NetworkStateList::const_iterator iter =
network_list.begin(); iter != network_list.end(); ++iter) {
const NetworkState* network = *iter;
if (network->type() != shill::kTypeCellular)
continue;
std::string activation_state = network->activation_state();
if (activation_state != shill::kActivationStateActivated)
continue;
std::string network_name = EscapeAmpersands(network->name());
if (network->IsConnectingState()) {
label = l10n_util::GetStringFUTF16(
IDS_STATUSBAR_NETWORK_DEVICE_STATUS,
base::UTF8ToUTF16(network_name),
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING));
} else {
label = base::UTF8ToUTF16(network_name);
}
int flag = FLAG_CELLULAR;
bool isActive = ShouldHighlightNetwork(network);
if (isActive)
flag |= FLAG_ASSOCIATED;
const gfx::ImageSkia icon = ash::network_icon::GetImageForNetwork(
network, ash::network_icon::ICON_TYPE_LIST);
menu_items_.push_back(
MenuItem(ui::MenuModel::TYPE_COMMAND,
label, icon, network->path(), flag));
}
const DeviceState* cellular_device =
handler->GetDeviceStateByType(NetworkTypePattern::Cellular());
if (cellular_device && cellular_device->support_network_scan()) {
const gfx::ImageSkia icon =
ash::network_icon::GetImageForDisconnectedNetwork(
ash::network_icon::ICON_TYPE_LIST, shill::kTypeCellular);
menu_items_.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND,
l10n_util::GetStringUTF16(
IDS_OPTIONS_SETTINGS_OTHER_CELLULAR_NETWORKS),
icon, std::string(), FLAG_ADD_CELLULAR));
}
} else {
int initializing_message_id =
ash::network_icon::GetCellularUninitializedMsg();
if (initializing_message_id) {
AddMessageItem(l10n_util::GetStringUTF16(initializing_message_id));
}
}
if (handler->IsTechnologyEnabled(NetworkTypePattern::Wimax())) {
for (NetworkStateHandler::NetworkStateList::const_iterator iter =
network_list.begin(); iter != network_list.end(); ++iter) {
const NetworkState* network = *iter;
if (network->type() != shill::kTypeWimax)
continue;
AddWirelessNetworkMenuItem(network, FLAG_WIMAX);
}
}
if (handler->IsTechnologyEnabled(NetworkTypePattern::WiFi())) {
int scanning_msg = handler->GetScanningByType(NetworkTypePattern::WiFi())
? IDS_ASH_STATUS_TRAY_WIFI_SCANNING_MESSAGE
: 0;
for (NetworkStateHandler::NetworkStateList::const_iterator iter =
network_list.begin(); iter != network_list.end(); ++iter) {
const NetworkState* network = *iter;
if (network->type() != shill::kTypeWifi)
continue;
if (scanning_msg && !network->IsConnectedState()) {
AddMessageItem(l10n_util::GetStringUTF16(scanning_msg));
scanning_msg = 0;
}
AddWirelessNetworkMenuItem(network, FLAG_WIFI);
}
if (scanning_msg)
AddMessageItem(l10n_util::GetStringUTF16(scanning_msg));
const gfx::ImageSkia icon =
ash::network_icon::GetImageForConnectedNetwork(
ash::network_icon::ICON_TYPE_LIST, shill::kTypeWifi);
menu_items_.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND,
l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_OTHER_WIFI_NETWORKS),
icon, std::string(), FLAG_ADD_WIFI));
}
if (menu_items_.empty()) {
AddMessageItem(l10n_util::GetStringFUTF16(
IDS_STATUSBAR_NETWORK_MENU_ITEM_INDENT,
l10n_util::GetStringUTF16(IDS_STATUSBAR_NO_NETWORKS_MESSAGE)));
}
NetworkStateHandler::TechnologyState wifi_state =
handler->GetTechnologyState(NetworkTypePattern::WiFi());
bool wifi_available =
wifi_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE;
bool wifi_enabled = wifi_state == NetworkStateHandler::TECHNOLOGY_ENABLED;
NetworkStateHandler::TechnologyState mobile_state =
handler->GetTechnologyState(NetworkTypePattern::Mobile());
bool mobile_available =
mobile_state != NetworkStateHandler::TECHNOLOGY_UNAVAILABLE;
bool mobile_enabled = mobile_state == NetworkStateHandler::TECHNOLOGY_ENABLED;
bool show_toggle_wifi = wifi_available &&
(should_open_button_options || !wifi_enabled);
bool show_toggle_mobile = mobile_available &&
(should_open_button_options || !mobile_enabled);
if (show_toggle_wifi || show_toggle_mobile) {
menu_items_.push_back(MenuItem());
if (show_toggle_wifi) {
int id = wifi_enabled ? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE :
IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
label = l10n_util::GetStringFUTF16(id,
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_WIFI));
int flag = FLAG_TOGGLE_WIFI;
if (wifi_state == NetworkStateHandler::TECHNOLOGY_ENABLING)
flag |= FLAG_DISABLED;
menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
gfx::ImageSkia(), std::string(), flag));
}
if (show_toggle_mobile) {
const DeviceState* mobile_device =
handler->GetDeviceStateByType(NetworkTypePattern::Mobile());
bool is_locked = mobile_device && !mobile_device->sim_lock_type().empty();
int id = (mobile_enabled && !is_locked)
? IDS_STATUSBAR_NETWORK_DEVICE_DISABLE
: IDS_STATUSBAR_NETWORK_DEVICE_ENABLE;
label = l10n_util::GetStringFUTF16(id,
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_DEVICE_CELLULAR));
gfx::ImageSkia icon;
int flag = FLAG_TOGGLE_MOBILE;
if (mobile_state == NetworkStateHandler::TECHNOLOGY_ENABLING)
flag |= FLAG_DISABLED;
menu_items_.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND, label,
icon, std::string(), flag));
}
}
more_menu_model_->InitMenuItems(should_open_button_options);
if (!more_menu_model_->menu_items().empty()) {
menu_items_.push_back(MenuItem());
menu_items_.push_back(MenuItem(
ui::MenuModel::TYPE_SUBMENU,
l10n_util::GetStringUTF16(IDS_STATUSBAR_NETWORK_MORE),
gfx::ImageSkia(), more_menu_model_.get(), FLAG_NONE));
}
}
int MainMenuModel::GetCommandIdAt(int index) const {
return index + kMainIndexMask;
}
void MoreMenuModel::InitMenuItems(bool should_open_button_options) {
menu_items_.clear();
MenuItemVector link_items;
MenuItemVector address_items;
NetworkStateHandler* handler = NetworkHandler::Get()->network_state_handler();
const NetworkState* default_network = handler->DefaultNetwork();
int message_id = -1;
if (default_network)
message_id = IDS_STATUSBAR_NETWORK_OPEN_PROXY_SETTINGS_DIALOG;
if (message_id != -1) {
link_items.push_back(MenuItem(ui::MenuModel::TYPE_COMMAND,
l10n_util::GetStringUTF16(message_id),
gfx::ImageSkia(),
std::string(),
FLAG_OPTIONS));
}
if (default_network) {
std::string ip_address = default_network->ip_address();
if (!ip_address.empty()) {
address_items.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND, base::ASCIIToUTF16(ip_address),
gfx::ImageSkia(), std::string(), FLAG_DISABLED));
}
}
std::string ethernet_address =
handler->FormattedHardwareAddressForType(NetworkTypePattern::Ethernet());
if (!ethernet_address.empty()) {
std::string label = l10n_util::GetStringUTF8(
IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET) + " " + ethernet_address;
address_items.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND, base::UTF8ToUTF16(label),
gfx::ImageSkia(), std::string(), FLAG_DISABLED));
}
std::string wifi_address =
handler->FormattedHardwareAddressForType(NetworkTypePattern::WiFi());
if (!wifi_address.empty()) {
std::string label = l10n_util::GetStringUTF8(
IDS_STATUSBAR_NETWORK_DEVICE_WIFI) + " " + wifi_address;
address_items.push_back(MenuItem(
ui::MenuModel::TYPE_COMMAND, base::UTF8ToUTF16(label),
gfx::ImageSkia(), std::string(), FLAG_DISABLED));
}
menu_items_ = link_items;
if (!menu_items_.empty() && address_items.size() > 1)
menu_items_.push_back(MenuItem());
menu_items_.insert(menu_items_.end(),
address_items.begin(), address_items.end());
}
int MoreMenuModel::GetCommandIdAt(int index) const {
return index + kMoreIndexMask;
}
NetworkMenu::Delegate::~Delegate() {
}
NetworkMenu::NetworkMenu(Delegate* delegate)
: delegate_(delegate),
refreshing_menu_(false),
weak_pointer_factory_(this) {
main_menu_model_.reset(new MainMenuModel(weak_pointer_factory_.GetWeakPtr()));
}
NetworkMenu::~NetworkMenu() {
}
ui::MenuModel* NetworkMenu::GetMenuModel() {
return main_menu_model_.get();
}
void NetworkMenu::UpdateMenu() {
refreshing_menu_ = true;
main_menu_model_->InitMenuItems(delegate_->ShouldOpenButtonOptions());
refreshing_menu_ = false;
}
}