// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chrome/browser/chromeos/options/internet_page_view.h" #include #include "app/combobox_model.h" #include "chrome/browser/chromeos/cros/cros_library.h" #include "chrome/browser/chromeos/options/network_config_view.h" #include "chrome/browser/chromeos/options/options_window_view.h" #include "chrome/browser/chromeos/status/network_menu_button.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" #include "views/controls/button/native_button.h" #include "views/controls/combobox/combobox.h" #include "views/controls/image_view.h" #include "views/widget/widget.h" #include "views/window/window.h" namespace chromeos { //////////////////////////////////////////////////////////////////////////////// // NetworkSection class NetworkSection : public SettingsPageSection, public views::ButtonListener { public: NetworkSection(InternetPageView* parent, Profile* profile, int title_msg_id); virtual ~NetworkSection() {} // Overriden from views::Button::ButtonListener: virtual void ButtonPressed(views::Button* sender, const views::Event& event); protected: enum ButtonFlags { OPTIONS_BUTTON = 1 << 0, CONNECT_BUTTON = 1 << 1, DISCONNECT_BUTTON = 1 << 2, FORGET_BUTTON = 1 << 3, }; // SettingsPageSection overrides: virtual void InitContents(GridLayout* layout); // Subclasses will initialize themselves in this method. virtual void InitSection() = 0; // This adds a row for a network. // |id| is passed back in the ButtonClicked method. // |icon|, |name|, |bold_name|, and |status| are displayed in the row. // |button_flags| is an OR of ButtonFlags that should be displayed. void AddNetwork(int id, const SkBitmap& icon, const std::wstring& name, bool bold_name, const std::wstring& status, int button_flags, int connection_type); // Creates a modal popup with |view|. void CreateModalPopup(views::WindowDelegate* view); // This method is called when the user click on the |button| for |id|. virtual void ButtonClicked(int button, int connection_type, int id) = 0; private: // This constant determines the button tag offset for the different buttons. // The ButtonFlag is multiplied by this offset to determine the button tag. // For example, for disconnect buttons (DISCONNECT_BUTTON = 4), the button tag // will be offset by 4000. static const int kButtonIdOffset = 1000; // This constant determines the button tag offset for the connection types. // The ConnectionType is multiplied by this to determine the button tag. // For example, for wifi buttons (TYPE_WIFI = 2), the button tag // will be offset by 200. static const int kConnectionTypeOffset = 100; InternetPageView* parent_; int quad_column_view_set_id_; GridLayout* layout_; DISALLOW_COPY_AND_ASSIGN(NetworkSection); }; NetworkSection::NetworkSection(InternetPageView* parent, Profile* profile, int title_msg_id) : SettingsPageSection(profile, title_msg_id), parent_(parent), quad_column_view_set_id_(1) { } void NetworkSection::ButtonPressed(views::Button* sender, const views::Event& event) { int id = sender->tag(); // Determine the button from the id (div by kButtonIdOffset). int button = id / kButtonIdOffset; id %= kButtonIdOffset; // Determine the connection type from the id (div by kConnectionTypeOffset). int connection_type = id / kConnectionTypeOffset; id %= kConnectionTypeOffset; ButtonClicked(button, connection_type, id); } void NetworkSection::InitContents(GridLayout* layout) { layout_ = layout; ColumnSet* column_set = layout_->AddColumnSet(quad_column_view_set_id_); // icon column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); // network name column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); // fill padding column_set->AddPaddingColumn(10, 0); // first button column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); // padding column_set->AddPaddingColumn(0, 10); // second button column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); InitSection(); } void NetworkSection::AddNetwork(int id, const SkBitmap& icon, const std::wstring& name, bool bold_name, const std::wstring& status, int button_flags, int connection_type) { ResourceBundle& rb = ResourceBundle::GetSharedInstance(); // Offset id by connection type. id += kConnectionTypeOffset * connection_type; layout_->StartRow(0, quad_column_view_set_id_); views::ImageView* icon_view = new views::ImageView(); icon_view->SetImage(icon); layout_->AddView(icon_view, 1, 2); views::Label* name_view = new views::Label(name); if (bold_name) name_view->SetFont(rb.GetFont(ResourceBundle::BoldFont)); name_view->SetHorizontalAlignment(views::Label::ALIGN_LEFT); layout_->AddView(name_view); int num_buttons = 0; if (button_flags & OPTIONS_BUTTON) num_buttons++; if (button_flags & CONNECT_BUTTON) num_buttons++; if (button_flags & DISCONNECT_BUTTON) num_buttons++; if (button_flags & FORGET_BUTTON) num_buttons++; if (num_buttons > 0) { // We only support 2 buttons. DCHECK_LE(num_buttons, 2); if (num_buttons == 1) layout_->SkipColumns(1); if (button_flags & FORGET_BUTTON) { views::NativeButton* button = new views::NativeButton(this, l10n_util::GetString(IDS_OPTIONS_SETTINGS_FORGET)); button->set_tag(id + kButtonIdOffset * FORGET_BUTTON); layout_->AddView(button, 1, 2); } if (button_flags & DISCONNECT_BUTTON) { views::NativeButton* button = new views::NativeButton(this, l10n_util::GetString(IDS_OPTIONS_SETTINGS_DISCONNECT)); button->set_tag(id + kButtonIdOffset * DISCONNECT_BUTTON); layout_->AddView(button, 1, 2); } if (button_flags & CONNECT_BUTTON) { views::NativeButton* button = new views::NativeButton(this, l10n_util::GetString(IDS_OPTIONS_SETTINGS_CONNECT)); button->set_tag(id + kButtonIdOffset * CONNECT_BUTTON); layout_->AddView(button, 1, 2); } if (button_flags & OPTIONS_BUTTON) { views::NativeButton* button = new views::NativeButton(this, l10n_util::GetString(IDS_OPTIONS_SETTINGS_OPTIONS)); button->set_tag(id + kButtonIdOffset * OPTIONS_BUTTON); layout_->AddView(button, 1, 2); } } layout_->StartRow(0, quad_column_view_set_id_); layout_->SkipColumns(1); views::Label* status_label = new views::Label(status); status_label->SetFont(rb.GetFont(ResourceBundle::SmallFont)); status_label->SetColor(SK_ColorLTGRAY); status_label->SetHorizontalAlignment(views::Label::ALIGN_LEFT); layout_->AddView(status_label); layout_->AddPaddingRow(0, kRelatedControlVerticalSpacing); } void NetworkSection::CreateModalPopup(views::WindowDelegate* view) { views::Window* window = views::Window::CreateChromeWindow( GetOptionsViewParent(), gfx::Rect(), view); window->SetIsAlwaysOnTop(true); window->Show(); } //////////////////////////////////////////////////////////////////////////////// // WiredSection class WiredSection : public NetworkSection { public: WiredSection(InternetPageView* parent, Profile* profile); virtual ~WiredSection() {} protected: // NetworkSection overrides: virtual void InitSection(); virtual void ButtonClicked(int button, int connection_type, int id); DISALLOW_COPY_AND_ASSIGN(WiredSection); }; WiredSection::WiredSection(InternetPageView* parent, Profile* profile) : NetworkSection(parent, profile, IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIRED_NETWORK) { } void WiredSection::InitSection() { NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_WIRED_BLACK); if (!cros->ethernet_connecting() && !cros->ethernet_connected()) { icon = NetworkMenuButton::IconForDisplay(icon, *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_DISCONNECTED)); } std::wstring name = l10n_util::GetString(IDS_STATUSBAR_NETWORK_DEVICE_ETHERNET); int s = IDS_STATUSBAR_NETWORK_DEVICE_DISABLED; if (cros->ethernet_connecting()) s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING; else if (cros->ethernet_connected()) s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED; else if (cros->ethernet_enabled()) s = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED; std::wstring status = l10n_util::GetString(s); int flags = cros->ethernet_connected() ? OPTIONS_BUTTON : 0; bool bold = cros->ethernet_connected() ? true : false; AddNetwork(0, icon, name, bold, status, flags, TYPE_ETHERNET); } void WiredSection::ButtonClicked(int button, int connection_type, int id) { CreateModalPopup(new NetworkConfigView( CrosLibrary::Get()->GetNetworkLibrary()->ethernet_network())); } //////////////////////////////////////////////////////////////////////////////// // WirelessSection class WirelessSection : public NetworkSection { public: WirelessSection(InternetPageView* parent, Profile* profile); virtual ~WirelessSection() {} protected: // NetworkSection overrides: virtual void InitSection(); virtual void ButtonClicked(int button, int connection_type, int id); private: // This calls NetworkSection::AddNetwork . // For |connecting| or |connected| networks, the name is bold. // The status is "Connecting" if |connecting|, "Connected" if |connected|, // or "Disconnected". // For connected networks, we show the disconnect and options buttons. // For !connected and !connecting networks, we show the connect button. void AddWirelessNetwork(int id, const SkBitmap& icon, const std::wstring& name, bool connecting, bool connected, int connection_type); WifiNetworkVector wifi_networks_; CellularNetworkVector celluar_networks_; DISALLOW_COPY_AND_ASSIGN(WirelessSection); }; WirelessSection::WirelessSection(InternetPageView* parent, Profile* profile) : NetworkSection(parent, profile, IDS_OPTIONS_SETTINGS_SECTION_TITLE_WIRELESS_NETWORK) { } void WirelessSection::InitSection() { NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); // Wifi wifi_networks_ = cros->wifi_networks(); for (size_t i = 0; i < wifi_networks_.size(); ++i) { std::wstring name = ASCIIToWide(wifi_networks_[i].name()); SkBitmap icon = NetworkMenuButton::IconForNetworkStrength( wifi_networks_[i].strength(), true); if (wifi_networks_[i].encrypted()) { icon = NetworkMenuButton::IconForDisplay(icon, *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE)); } bool connecting = wifi_networks_[i].connecting(); bool connected = wifi_networks_[i].connected(); AddWirelessNetwork(i, icon, name, connecting, connected, TYPE_WIFI); } // Cellular celluar_networks_ = cros->cellular_networks(); // Cellular networks ssids. for (size_t i = 0; i < celluar_networks_.size(); ++i) { std::wstring name = ASCIIToWide(celluar_networks_[i].name()); SkBitmap icon = NetworkMenuButton::IconForNetworkStrength( celluar_networks_[i].strength(), true); // TODO(chocobo): Check cellular network 3g/edge. SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G); // SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_EDGE); icon = NetworkMenuButton::IconForDisplay(icon, badge); bool connecting = celluar_networks_[i].connecting(); bool connected = celluar_networks_[i].connected(); AddWirelessNetwork(i, icon, name, connecting, connected, TYPE_CELLULAR); } } void WirelessSection::ButtonClicked(int button, int connection_type, int id) { if (connection_type == TYPE_CELLULAR) { if (static_cast(celluar_networks_.size()) > id) { if (button == CONNECT_BUTTON) { // Connect to cellular network. CrosLibrary::Get()->GetNetworkLibrary()->ConnectToCellularNetwork( celluar_networks_[id]); } else if (button == DISCONNECT_BUTTON) { CrosLibrary::Get()->GetNetworkLibrary()->DisconnectFromWirelessNetwork( celluar_networks_[id]); } else { CreateModalPopup(new NetworkConfigView(celluar_networks_[id])); } } } else if (connection_type == TYPE_WIFI) { if (static_cast(wifi_networks_.size()) > id) { if (button == CONNECT_BUTTON) { // Connect to wifi here. Open password page if appropriate. if (wifi_networks_[id].encrypted()) { NetworkConfigView* view = new NetworkConfigView(wifi_networks_[id], true); CreateModalPopup(view); view->SetLoginTextfieldFocus(); } else { CrosLibrary::Get()->GetNetworkLibrary()->ConnectToWifiNetwork( wifi_networks_[id], string16(), string16(), string16()); } } else if (button == DISCONNECT_BUTTON) { CrosLibrary::Get()->GetNetworkLibrary()->DisconnectFromWirelessNetwork( wifi_networks_[id]); } else { CreateModalPopup(new NetworkConfigView(wifi_networks_[id], false)); } } } else { NOTREACHED(); } } void WirelessSection::AddWirelessNetwork(int id, const SkBitmap& icon, const std::wstring& name, bool connecting, bool connected, int connection_type) { bool bold = connecting || connected; int s = IDS_STATUSBAR_NETWORK_DEVICE_DISCONNECTED; if (connecting) s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTING; else if (connected) s = IDS_STATUSBAR_NETWORK_DEVICE_CONNECTED; std::wstring status = l10n_util::GetString(s); int flags = 0; if (connected) { flags |= DISCONNECT_BUTTON | OPTIONS_BUTTON; } else if (!connecting) { flags |= CONNECT_BUTTON; } AddNetwork(id, icon, name, bold, status, flags, connection_type); } //////////////////////////////////////////////////////////////////////////////// // RememberedSection class RememberedSection : public NetworkSection { public: RememberedSection(InternetPageView* parent, Profile* profile); virtual ~RememberedSection() {} protected: // NetworkSection overrides: virtual void InitSection(); virtual void ButtonClicked(int button, int connection_type, int id); private: WifiNetworkVector wifi_networks_; CellularNetworkVector celluar_networks_; DISALLOW_COPY_AND_ASSIGN(RememberedSection); }; RememberedSection::RememberedSection(InternetPageView* parent, Profile* profile) : NetworkSection(parent, profile, IDS_OPTIONS_SETTINGS_SECTION_TITLE_REMEMBERED_NETWORK) { } void RememberedSection::InitSection() { NetworkLibrary* cros = CrosLibrary::Get()->GetNetworkLibrary(); ResourceBundle& rb = ResourceBundle::GetSharedInstance(); // Wifi wifi_networks_ = cros->remembered_wifi_networks(); for (size_t i = 0; i < wifi_networks_.size(); ++i) { std::wstring name = ASCIIToWide(wifi_networks_[i].name()); SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0); if (wifi_networks_[i].encrypted()) { icon = NetworkMenuButton::IconForDisplay(icon, *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_SECURE)); } AddNetwork(i, icon, name, false, std::wstring(), FORGET_BUTTON, TYPE_WIFI); } // Cellular celluar_networks_ = cros->remembered_cellular_networks(); // Cellular networks ssids. for (size_t i = 0; i < celluar_networks_.size(); ++i) { std::wstring name = ASCIIToWide(celluar_networks_[i].name()); SkBitmap icon = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_BARS0); // TODO(chocobo): Check cellular network 3g/edge. SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_3G); // SkBitmap badge = *rb.GetBitmapNamed(IDR_STATUSBAR_NETWORK_EDGE); icon = NetworkMenuButton::IconForDisplay(icon, badge); AddNetwork(i, icon, name, false, std::wstring(), FORGET_BUTTON, TYPE_CELLULAR); } } void RememberedSection::ButtonClicked(int button, int connection_type, int id) { if (connection_type == TYPE_CELLULAR) { if (static_cast(celluar_networks_.size()) > id) { CrosLibrary::Get()->GetNetworkLibrary()->ForgetWirelessNetwork( celluar_networks_[id]); } } else if (connection_type == TYPE_WIFI) { if (static_cast(wifi_networks_.size()) > id) { CrosLibrary::Get()->GetNetworkLibrary()->ForgetWirelessNetwork( wifi_networks_[id]); } } else { NOTREACHED(); } } //////////////////////////////////////////////////////////////////////////////// // InternetPageView //////////////////////////////////////////////////////////////////////////////// // InternetPageView, SettingsPageView implementation: InternetPageView::InternetPageView(Profile* profile) : SettingsPageView(profile) { CrosLibrary::Get()->GetNetworkLibrary()->AddObserver(this); } InternetPageView::~InternetPageView() { CrosLibrary::Get()->GetNetworkLibrary()->RemoveObserver(this); } void InternetPageView::NetworkChanged(NetworkLibrary* obj) { InitControlLayout(); } void InternetPageView::InitControlLayout() { RemoveAllChildViews(true); GridLayout* layout = CreatePanelGridLayout(this); SetLayoutManager(layout); int single_column_view_set_id = 0; ColumnSet* column_set = layout->AddColumnSet(single_column_view_set_id); column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0); layout->StartRow(0, single_column_view_set_id); layout->AddView(new WiredSection(this, profile())); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, single_column_view_set_id); layout->AddView(new WirelessSection(this, profile())); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); layout->StartRow(0, single_column_view_set_id); layout->AddView(new RememberedSection(this, profile())); layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); Layout(); } } // namespace chromeos