Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(317)

Unified Diff: athena/main/debug/network_selector.cc

Issue 425783003: athena: Add a network-selector widget. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « athena/main/debug/network_selector.h ('k') | athena/resources/athena_resources.gyp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: athena/main/debug/network_selector.cc
diff --git a/athena/main/debug/network_selector.cc b/athena/main/debug/network_selector.cc
new file mode 100644
index 0000000000000000000000000000000000000000..caf76de1b3a499c8379798bbda645fb614bff49f
--- /dev/null
+++ b/athena/main/debug/network_selector.cc
@@ -0,0 +1,465 @@
+// Copyright 2014 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 "athena/main/debug/network_selector.h"
+
+#include "base/memory/weak_ptr.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chromeos/network/network_configuration_handler.h"
+#include "chromeos/network/network_connection_handler.h"
+#include "chromeos/network/network_handler.h"
+#include "chromeos/network/network_profile_handler.h"
+#include "chromeos/network/network_state.h"
+#include "chromeos/network/network_state_handler.h"
+#include "chromeos/network/network_state_handler_observer.h"
+#include "chromeos/network/network_type_pattern.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+#include "ui/aura/window.h"
+#include "ui/chromeos/network/network_icon.h"
+#include "ui/chromeos/network/network_info.h"
+#include "ui/chromeos/network/network_list.h"
+#include "ui/chromeos/network/network_list_delegate.h"
+#include "ui/compositor/layer.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/text_constants.h"
+#include "ui/views/background.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/button/blue_button.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/image_view.h"
+#include "ui/views/controls/label.h"
+#include "ui/views/controls/scroll_view.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/widget/widget.h"
+
+using chromeos::NetworkConfigurationHandler;
+using chromeos::NetworkConnectionHandler;
+using chromeos::NetworkHandler;
+using chromeos::NetworkProfileHandler;
+using chromeos::NetworkState;
+
+namespace {
+
+const int kBackgroundColor = SkColorSetARGB(0x7f, 0, 0, 0);
+const int kBackgroundColorLighter = SkColorSetARGB(0x2f, 0, 0, 0);
+
+// The View for the user to enter the password for connceting to a network. This
+// view also shows an error message if the network connection fails.
+class PasswordView : public views::View, public views::ButtonListener {
+ public:
+ PasswordView(const ui::NetworkInfo& network,
+ const base::Callback<void(bool)>& callback,
+ views::View* parent_container)
+ : network_(network),
+ callback_(callback),
+ parent_container_(parent_container),
+ connect_(NULL),
+ cancel_(NULL),
+ textfield_(NULL),
+ error_msg_(NULL),
+ weak_ptr_(this) {
+ const int kHorizontal = 5;
+ const int kVertical = 0;
+ const int kPadding = 0;
+
+ views::BoxLayout* layout = new views::BoxLayout(
+ views::BoxLayout::kVertical, kHorizontal, kVertical, kPadding);
+ layout->set_main_axis_alignment(
+ views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+ layout->set_cross_axis_alignment(
+ views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
+ SetLayoutManager(layout);
+
+ views::View* container = new views::View;
+ layout = new views::BoxLayout(
+ views::BoxLayout::kHorizontal, kHorizontal, kVertical, kPadding);
+ layout->set_main_axis_alignment(
+ views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
+ container->SetLayoutManager(layout);
+
+ textfield_ = new views::Textfield();
+ textfield_->set_placeholder_text(base::ASCIIToUTF16("Password"));
+ textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
+ textfield_->set_default_width_in_chars(35);
+ container->AddChildView(textfield_);
+
+ connect_ = new views::BlueButton(this, base::ASCIIToUTF16("Connect"));
oshima 2014/07/28 17:49:28 I just learned about this button :)
+ container->AddChildView(connect_);
+
+ cancel_ = new views::LabelButton(this, base::ASCIIToUTF16("Cancel"));
+ cancel_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ container->AddChildView(cancel_);
+
+ AddChildView(container);
+ }
+
+ virtual ~PasswordView() {}
+
+ private:
+ void Close(bool successful) { callback_.Run(successful); }
+
+ void OnKnownError(const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ std::string message;
+ if (!error_data->GetString(chromeos::network_handler::kDbusErrorMessage,
+ &message))
+ message = error_name;
+ if (message.empty())
+ message = std::string("Unknown error.");
+ if (!error_msg_) {
+ error_msg_ = new views::Label();
+ error_msg_->SetFontList(
+ error_msg_->font_list().Derive(0, gfx::Font::BOLD));
+ error_msg_->SetEnabledColor(SK_ColorRED);
+ }
+ error_msg_->SetText(base::UTF8ToUTF16(message));
+ if (!error_msg_->parent()) {
+ AddChildView(error_msg_);
+ // It is unfortunately necessary to have all the views upto the container
+ // do a layout because of the change in height of the view because of the
+ // error message.
+ for (views::View* v = this; v != parent_container_; v = v->parent())
+ v->Layout();
oshima 2014/07/28 17:49:29 Can't you just call InvalidateLayout and layout on
sadrul 2014/07/29 04:13:27 You are totally right. I forgot about this one. Fi
+ parent_container_->Layout();
+ }
+ connect_->SetEnabled(true);
+ }
+
+ void OnSetProfileSucceed(const base::string16& password) {
+ base::DictionaryValue properties;
+ properties.SetStringWithoutPathExpansion(shill::kPassphraseProperty,
+ textfield_->text());
+ NetworkHandler::Get()->network_configuration_handler()->SetProperties(
+ network_.service_path,
+ properties,
+ base::Bind(&PasswordView::OnSetPropertiesSucceed,
+ weak_ptr_.GetWeakPtr()),
+ base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()));
+ }
+
+ void OnSetPropertiesSucceed() {
+ const bool check_error_state = false;
+ NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+ network_.service_path,
+ base::Bind(&PasswordView::OnConnectionSucceed, weak_ptr_.GetWeakPtr()),
+ base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()),
+ check_error_state);
+ }
+
+ void OnConnectionSucceed() { Close(true); }
+
+ // views::ButtonListener:
+ virtual void ButtonPressed(views::Button* sender,
+ const ui::Event& event) OVERRIDE {
+ if (sender == connect_) {
+ if (error_msg_) {
+ RemoveChildView(error_msg_);
+ delete error_msg_;
+ error_msg_ = NULL;
+ }
+ connect_->SetEnabled(false);
+ NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
+ network_.service_path,
+ NetworkProfileHandler::GetSharedProfilePath(),
+ base::Bind(&PasswordView::OnSetProfileSucceed,
+ weak_ptr_.GetWeakPtr(),
+ textfield_->text()),
+ base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()));
+ } else if (sender == cancel_) {
+ views::View* parent_view = parent();
+ Close(false);
+ parent_view->Layout();
+ } else {
+ NOTREACHED();
+ }
+ }
+
+ ui::NetworkInfo network_;
+ base::Callback<void(bool)> callback_;
+ views::View* parent_container_;
+
+ views::BlueButton* connect_;
+ views::LabelButton* cancel_;
+ views::Textfield* textfield_;
+ views::Label* error_msg_;
+ base::WeakPtrFactory<PasswordView> weak_ptr_;
+
+ DISALLOW_COPY_AND_ASSIGN(PasswordView);
+};
+
+// A View that represents a single row in the network list. This row also
+// contains the View for taking password for password-protected networks.
+class NetworkRow : public views::View {
+ public:
+ NetworkRow(const ui::NetworkInfo& network, views::View* container)
+ : network_(network), container_(container), weak_ptr_(this) {
+ SetBorder(views::Border::CreateEmptyBorder(10, 5, 10, 5));
+ SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 10));
+ Update(network);
+ }
+
+ virtual ~NetworkRow() {}
+
+ void Update(const ui::NetworkInfo& network) {
+ network_ = network;
+ views::ImageView* icon = new views::ImageView();
+ icon->SetImage(network.image);
+ icon->SetBounds(0, 0, network.image.width(), network.image.height());
+
+ views::Label* label = new views::Label(network.label);
+ if (network.highlight)
+ label->SetFontList(label->font_list().Derive(0, gfx::Font::BOLD));
+ AddChildView(icon);
+ AddChildView(label);
+ if (password_view_)
+ AddChildView(password_view_.get());
+ }
+
+ private:
+ void OnPasswordComplete(bool successful) {
+ password_view_.reset();
+ Layout();
+ parent()->Layout();
+ container_->Layout();
+ }
+
+ void ShowPasswordView(const std::string& service_path) {
+ const NetworkState* network =
+ NetworkHandler::Get()->network_state_handler()->GetNetworkState(
+ service_path);
+ if (!network)
+ return;
+
+ // If this is not a wifi network that needs a password, then ignore.
+ if (network->type() != shill::kTypeWifi ||
+ network->security() == shill::kSecurityNone) {
+ return;
+ }
+
+ password_view_.reset(new PasswordView(
+ network_,
+ base::Bind(&NetworkRow::OnPasswordComplete, weak_ptr_.GetWeakPtr()),
+ container_));
+ password_view_->set_owned_by_client();
+ AddChildView(password_view_.get());
+ PreferredSizeChanged();
+ Layout();
+ parent()->Layout();
+ container_->Layout();
oshima 2014/07/28 17:49:28 same here.
sadrul 2014/07/29 04:13:27 Done.
+ }
+
+ void OnNetworkConnectionError(const std::string& service_path,
+ const std::string& error_name,
+ scoped_ptr<base::DictionaryValue> error_data) {
+ if (error_name == NetworkConnectionHandler::kErrorConnectCanceled)
+ return;
+ if (error_name == shill::kErrorBadPassphrase ||
+ error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
+ error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
+ error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
+ ShowPasswordView(service_path);
+ }
+ }
+
+ void Activate() {
oshima 2014/07/28 17:49:29 would you mind renaming this to ActivateNetwork ?
sadrul 2014/07/29 04:13:27 Done.
+ const chromeos::NetworkState* network =
+ NetworkHandler::Get()->network_state_handler()->GetNetworkState(
+ network_.service_path);
+ if (!network)
+ return;
+ if (network->IsConnectedState()) {
+ NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
+ network_.service_path,
+ base::Closure(),
+ chromeos::network_handler::ErrorCallback());
+ } else if (!network->IsConnectingState()) {
+ // |network| is not connected, and not already trying to connect.
+ NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
+ network_.service_path,
+ base::Closure(),
+ base::Bind(&NetworkRow::OnNetworkConnectionError,
+ weak_ptr_.GetWeakPtr(),
+ network_.service_path),
+ false);
+ }
+ }
+
+ // views::View:
+ virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
+ if (event->type() != ui::ET_MOUSE_PRESSED)
+ return;
+ Activate();
+ event->SetHandled();
+ }
+
+ virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
+ if (gesture->type() != ui::ET_GESTURE_TAP)
+ return;
+ Activate();
+ gesture->SetHandled();
+ }
+
+ ui::NetworkInfo network_;
+ views::View* container_;
+ base::WeakPtrFactory<NetworkRow> weak_ptr_;
+ scoped_ptr<views::View> password_view_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkRow);
+};
+
+class NetworkSelector : public ui::NetworkListDelegate,
+ public chromeos::NetworkStateHandlerObserver,
+ public ui::EventHandler {
+ public:
+ explicit NetworkSelector(aura::Window* container)
+ : background_view_(NULL),
+ scroll_content_(NULL),
+ scroller_(NULL),
+ network_list_(this) {
+ CreateWidget(container);
+ CreateNetworkList();
+
+ NetworkHandler::Get()->network_state_handler()->RequestScan();
+ NetworkHandler::Get()->network_state_handler()->AddObserver(this,
+ FROM_HERE);
+ }
+
+ virtual ~NetworkSelector() {
+ NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
+ FROM_HERE);
+ }
+
+ private:
+ void CreateWidget(aura::Window* container) {
+ views::Widget::InitParams params;
+ params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
+ params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
+ params.activatable = views::Widget::InitParams::ACTIVATABLE_DEFAULT;
+ params.accept_events = true;
+ params.bounds = gfx::Rect(container->bounds().size());
+ params.parent = container;
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget_.reset(new views::Widget());
+ widget_->Init(params);
+ widget_->Show();
+
+ background_view_ = new views::View;
+ background_view_->set_background(
+ views::Background::CreateSolidBackground(kBackgroundColor));
+ background_view_->SetBorder(
+ views::Border::CreateEmptyBorder(100, 300, 100, 300));
+ background_view_->SetLayoutManager(new views::FillLayout());
+ background_view_->set_target_handler(this);
+
+ widget_->SetContentsView(background_view_);
+ }
+
+ void CreateNetworkList() {
+ const int kListHeight = 500;
+ scroller_ = new views::ScrollView();
+ scroller_->set_background(
+ views::Background::CreateSolidBackground(SK_ColorWHITE));
+ scroller_->SetBounds(0, 0, 400, kListHeight);
+
+ scroll_content_ = new views::View;
+ scroll_content_->SetLayoutManager(
+ new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
+ scroller_->SetContents(scroll_content_);
+
+ scroller_->ClipHeightTo(kListHeight, kListHeight);
+ background_view_->AddChildView(scroller_);
+
+ background_view_->Layout();
+ scroller_->Layout();
+ scroll_content_->Layout();
+
+ network_list_.set_content_view(scroll_content_);
+ }
+
+ void UpdateNetworkList() { network_list_.UpdateNetworkList(); }
+
+ void Close() { delete this; }
+
+ // ui::NetworkListDelegate:
+ virtual views::View* CreateViewForNetwork(
+ const ui::NetworkInfo& info) OVERRIDE {
+ return new NetworkRow(info, background_view_);
+ }
+
+ virtual bool IsViewHovered(views::View* view) OVERRIDE { return false; }
+
+ virtual chromeos::NetworkTypePattern GetNetworkTypePattern() const OVERRIDE {
+ return chromeos::NetworkTypePattern::NonVirtual();
+ }
+
+ virtual void UpdateViewForNetwork(views::View* view,
+ const ui::NetworkInfo& info) OVERRIDE {
+ static_cast<NetworkRow*>(view)->Update(info);
+ }
+
+ virtual views::Label* CreateInfoLabel() OVERRIDE {
+ views::Label* label = new views::Label();
+ return label;
+ }
+
+ virtual void RelayoutScrollList() OVERRIDE { scroller_->Layout(); }
+
+ // chromeos::NetworkStateHandlerObserver:
+ virtual void NetworkListChanged() OVERRIDE { UpdateNetworkList(); }
+
+ virtual void DeviceListChanged() OVERRIDE {}
+
+ virtual void DefaultNetworkChanged(
+ const chromeos::NetworkState* network) OVERRIDE {}
+
+ virtual void NetworkConnectionStateChanged(
+ const chromeos::NetworkState* network) OVERRIDE {}
+
+ virtual void NetworkPropertiesUpdated(
+ const chromeos::NetworkState* network) OVERRIDE {}
+
+ // ui::EventHandler:
+ virtual void OnMouseEvent(ui::MouseEvent* mouse) OVERRIDE {
+ CHECK_EQ(background_view_, mouse->target());
+ if (mouse->type() == ui::ET_MOUSE_PRESSED && !mouse->handled()) {
+ Close();
+ mouse->SetHandled();
+ }
+ }
+
+ virtual void OnGestureEvent(ui::GestureEvent* gesture) OVERRIDE {
+ CHECK_EQ(background_view_, gesture->target());
+ if (gesture->type() == ui::ET_GESTURE_TAP && !gesture->handled()) {
+ Close();
+ gesture->SetHandled();
+ }
+ }
+
+ scoped_ptr<views::Widget> widget_;
+ views::View* background_view_;
+ views::View* scroll_content_;
+ views::ScrollView* scroller_;
+
+ views::View* connect_;
+
+ ui::NetworkListView network_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(NetworkSelector);
+};
+
+} // namespace
+
+namespace debug {
+
+void CreateNetworkSelector(aura::Window* container) {
+ new NetworkSelector(container);
+}
+
+} // namespace debug
« no previous file with comments | « athena/main/debug/network_selector.h ('k') | athena/resources/athena_resources.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698