Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / athena / system / network_selector.cc
1 // Copyright 2014 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 "athena/system/network_selector.h"
6
7 #include "athena/screen/public/screen_manager.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chromeos/network/network_configuration_handler.h"
11 #include "chromeos/network/network_connection_handler.h"
12 #include "chromeos/network/network_handler.h"
13 #include "chromeos/network/network_profile_handler.h"
14 #include "chromeos/network/network_state.h"
15 #include "chromeos/network/network_state_handler.h"
16 #include "chromeos/network/network_state_handler_observer.h"
17 #include "chromeos/network/network_type_pattern.h"
18 #include "third_party/cros_system_api/dbus/service_constants.h"
19 #include "ui/aura/window.h"
20 #include "ui/chromeos/network/network_icon.h"
21 #include "ui/chromeos/network/network_info.h"
22 #include "ui/chromeos/network/network_list.h"
23 #include "ui/chromeos/network/network_list_delegate.h"
24 #include "ui/compositor/layer.h"
25 #include "ui/gfx/canvas.h"
26 #include "ui/gfx/font.h"
27 #include "ui/gfx/font_list.h"
28 #include "ui/gfx/geometry/rect.h"
29 #include "ui/gfx/text_constants.h"
30 #include "ui/views/background.h"
31 #include "ui/views/border.h"
32 #include "ui/views/controls/button/blue_button.h"
33 #include "ui/views/controls/button/button.h"
34 #include "ui/views/controls/image_view.h"
35 #include "ui/views/controls/label.h"
36 #include "ui/views/controls/scroll_view.h"
37 #include "ui/views/controls/scrollbar/overlay_scroll_bar.h"
38 #include "ui/views/controls/textfield/textfield.h"
39 #include "ui/views/layout/box_layout.h"
40 #include "ui/views/layout/fill_layout.h"
41 #include "ui/views/widget/widget.h"
42 #include "ui/views/window/dialog_delegate.h"
43
44 using chromeos::NetworkConfigurationHandler;
45 using chromeos::NetworkConnectionHandler;
46 using chromeos::NetworkHandler;
47 using chromeos::NetworkProfileHandler;
48 using chromeos::NetworkState;
49
50 namespace {
51
52 // The View for the user to enter the password for connceting to a network. This
53 // view also shows an error message if the network connection fails.
54 class PasswordView : public views::View, public views::ButtonListener {
55  public:
56   PasswordView(const ui::NetworkInfo& network,
57                const base::Callback<void(bool)>& callback)
58       : network_(network),
59         callback_(callback),
60         connect_(nullptr),
61         cancel_(nullptr),
62         textfield_(nullptr),
63         error_msg_(nullptr),
64         weak_ptr_(this) {
65     const int kHorizontal = 5;
66     const int kVertical = 0;
67     const int kPadding = 0;
68
69     views::BoxLayout* layout = new views::BoxLayout(
70         views::BoxLayout::kVertical, kHorizontal, kVertical, kPadding);
71     layout->set_main_axis_alignment(
72         views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
73     layout->set_cross_axis_alignment(
74         views::BoxLayout::CROSS_AXIS_ALIGNMENT_STRETCH);
75     SetLayoutManager(layout);
76
77     views::View* container = new views::View;
78     layout = new views::BoxLayout(
79         views::BoxLayout::kHorizontal, kHorizontal, kVertical, kPadding);
80     layout->set_main_axis_alignment(
81         views::BoxLayout::MAIN_AXIS_ALIGNMENT_START);
82     container->SetLayoutManager(layout);
83
84     textfield_ = new views::Textfield();
85     textfield_->set_placeholder_text(base::ASCIIToUTF16("Password"));
86     textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
87     textfield_->set_default_width_in_chars(35);
88     container->AddChildView(textfield_);
89
90     connect_ = new views::BlueButton(this, base::ASCIIToUTF16("Connect"));
91     container->AddChildView(connect_);
92
93     cancel_ = new views::LabelButton(this, base::ASCIIToUTF16("Cancel"));
94     cancel_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
95     container->AddChildView(cancel_);
96
97     AddChildView(container);
98   }
99
100   ~PasswordView() override {}
101
102  private:
103   void CloseDialog(bool successful) { callback_.Run(successful); }
104
105   void OnKnownError(const std::string& error_name,
106                     scoped_ptr<base::DictionaryValue> error_data) {
107     std::string message;
108     if (!error_data->GetString(chromeos::network_handler::kDbusErrorMessage,
109                                &message))
110       message = error_name;
111     if (message.empty())
112       message = std::string("Unknown error.");
113     if (!error_msg_) {
114       error_msg_ = new views::Label();
115       error_msg_->SetFontList(
116           error_msg_->font_list().Derive(0, gfx::Font::BOLD));
117       error_msg_->SetEnabledColor(SK_ColorRED);
118     }
119     error_msg_->SetText(base::UTF8ToUTF16(message));
120     if (!error_msg_->parent()) {
121       AddChildView(error_msg_);
122       InvalidateLayout();
123       GetWidget()->GetRootView()->Layout();
124       ScrollRectToVisible(error_msg_->bounds());
125     }
126     connect_->SetEnabled(true);
127   }
128
129   void OnSetProfileSucceed(const base::string16& password) {
130     base::DictionaryValue properties;
131     properties.SetStringWithoutPathExpansion(shill::kPassphraseProperty,
132                                              textfield_->text());
133     NetworkHandler::Get()->network_configuration_handler()->SetProperties(
134         network_.service_path,
135         properties,
136         base::Bind(&PasswordView::OnSetPropertiesSucceed,
137                    weak_ptr_.GetWeakPtr()),
138         base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()));
139   }
140
141   void OnSetPropertiesSucceed() {
142     const bool check_error_state = false;
143     NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
144         network_.service_path,
145         base::Bind(&PasswordView::OnConnectionSucceed, weak_ptr_.GetWeakPtr()),
146         base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()),
147         check_error_state);
148   }
149
150   void OnConnectionSucceed() { CloseDialog(true); }
151
152   // views::View:
153   virtual void ViewHierarchyChanged(
154       const views::View::ViewHierarchyChangedDetails& details) override {
155     if (details.is_add && details.child == this)
156       textfield_->RequestFocus();
157   }
158
159   // views::ButtonListener:
160   virtual void ButtonPressed(views::Button* sender,
161                              const ui::Event& event) override {
162     if (sender == connect_) {
163       if (error_msg_) {
164         RemoveChildView(error_msg_);
165         delete error_msg_;
166         error_msg_ = nullptr;
167       }
168       connect_->SetEnabled(false);
169       NetworkHandler::Get()->network_configuration_handler()->SetNetworkProfile(
170           network_.service_path,
171           NetworkProfileHandler::GetSharedProfilePath(),
172           base::Bind(&PasswordView::OnSetProfileSucceed,
173                      weak_ptr_.GetWeakPtr(),
174                      textfield_->text()),
175           base::Bind(&PasswordView::OnKnownError, weak_ptr_.GetWeakPtr()));
176     } else if (sender == cancel_) {
177       CloseDialog(false);
178     } else {
179       NOTREACHED();
180     }
181   }
182
183   ui::NetworkInfo network_;
184   base::Callback<void(bool)> callback_;
185
186   views::BlueButton* connect_;
187   views::LabelButton* cancel_;
188   views::Textfield* textfield_;
189   views::Label* error_msg_;
190   base::WeakPtrFactory<PasswordView> weak_ptr_;
191
192   DISALLOW_COPY_AND_ASSIGN(PasswordView);
193 };
194
195 // A View that represents a single row in the network list. This row also
196 // contains the View for taking password for password-protected networks.
197 class NetworkRow : public views::View {
198  public:
199   NetworkRow(const ui::NetworkInfo& network)
200       : network_(network), weak_ptr_(this) {
201     SetBorder(views::Border::CreateEmptyBorder(10, 5, 10, 5));
202     SetLayoutManager(
203         new views::BoxLayout(views::BoxLayout::kHorizontal, 0, 0, 10));
204     Update(network);
205   }
206
207   ~NetworkRow() override {}
208
209   void Update(const ui::NetworkInfo& network) {
210     network_ = network;
211     views::ImageView* icon = new views::ImageView();
212     icon->SetImage(network.image);
213     icon->SetBounds(0, 0, network.image.width(), network.image.height());
214
215     views::Label* label = new views::Label(network.label);
216     if (network.highlight)
217       label->SetFontList(label->font_list().Derive(0, gfx::Font::BOLD));
218     AddChildView(icon);
219     AddChildView(label);
220     if (password_view_)
221       AddChildView(password_view_.get());
222   }
223
224   bool has_password_view() const { return password_view_; }
225
226  private:
227   void OnPasswordComplete(bool successful) {
228     password_view_.reset();
229     InvalidateLayout();
230     GetWidget()->GetRootView()->Layout();
231     ScrollRectToVisible(GetContentsBounds());
232   }
233
234   void ShowPasswordView(const std::string& service_path) {
235     const NetworkState* network =
236         NetworkHandler::Get()->network_state_handler()->GetNetworkState(
237             service_path);
238     if (!network)
239       return;
240
241     // If this is not a wifi network that needs a password, then ignore.
242     if (network->type() != shill::kTypeWifi ||
243         network->security() == shill::kSecurityNone) {
244       return;
245     }
246
247     password_view_.reset(new PasswordView(
248         network_,
249         base::Bind(&NetworkRow::OnPasswordComplete, weak_ptr_.GetWeakPtr())));
250     password_view_->set_owned_by_client();
251     AddChildView(password_view_.get());
252     PreferredSizeChanged();
253     GetWidget()->GetRootView()->Layout();
254     ScrollRectToVisible(password_view_->bounds());
255   }
256
257   void OnNetworkConnectionError(const std::string& service_path,
258                                 const std::string& error_name,
259                                 scoped_ptr<base::DictionaryValue> error_data) {
260     if (error_name == NetworkConnectionHandler::kErrorConnectCanceled)
261       return;
262     if (error_name == shill::kErrorBadPassphrase ||
263         error_name == NetworkConnectionHandler::kErrorPassphraseRequired ||
264         error_name == NetworkConnectionHandler::kErrorConfigurationRequired ||
265         error_name == NetworkConnectionHandler::kErrorAuthenticationRequired) {
266       ShowPasswordView(service_path);
267     }
268   }
269
270   void ActivateNetwork() {
271     const chromeos::NetworkState* network =
272         NetworkHandler::Get()->network_state_handler()->GetNetworkState(
273             network_.service_path);
274     if (!network)
275       return;
276     if (network->IsConnectedState()) {
277       NetworkHandler::Get()->network_connection_handler()->DisconnectNetwork(
278           network_.service_path,
279           base::Closure(),
280           chromeos::network_handler::ErrorCallback());
281     } else if (!network->IsConnectingState()) {
282       // |network| is not connected, and not already trying to connect.
283       NetworkHandler::Get()->network_connection_handler()->ConnectToNetwork(
284           network_.service_path,
285           base::Closure(),
286           base::Bind(&NetworkRow::OnNetworkConnectionError,
287                      weak_ptr_.GetWeakPtr(),
288                      network_.service_path),
289           false);
290     }
291   }
292
293   // views::View:
294   virtual void OnMouseEvent(ui::MouseEvent* event) override {
295     if (event->type() != ui::ET_MOUSE_PRESSED)
296       return;
297     ActivateNetwork();
298     event->SetHandled();
299   }
300
301   virtual void OnGestureEvent(ui::GestureEvent* gesture) override {
302     if (gesture->type() != ui::ET_GESTURE_TAP)
303       return;
304     ActivateNetwork();
305     gesture->SetHandled();
306   }
307
308   ui::NetworkInfo network_;
309   scoped_ptr<views::View> password_view_;
310   base::WeakPtrFactory<NetworkRow> weak_ptr_;
311
312   DISALLOW_COPY_AND_ASSIGN(NetworkRow);
313 };
314
315 class NetworkSelector : public ui::NetworkListDelegate,
316                         public chromeos::NetworkStateHandlerObserver,
317                         public views::DialogDelegate {
318  public:
319   NetworkSelector()
320       : scroll_content_(nullptr), scroller_(nullptr), network_list_(this) {
321     CreateNetworkList();
322     CreateWidget();
323
324     NetworkHandler::Get()->network_state_handler()->RequestScan();
325     NetworkHandler::Get()->network_state_handler()->AddObserver(this,
326                                                                 FROM_HERE);
327   }
328
329   ~NetworkSelector() override {
330     NetworkHandler::Get()->network_state_handler()->RemoveObserver(this,
331                                                                    FROM_HERE);
332   }
333
334  private:
335   void CreateWidget() {
336     // Same as CreateDialogWidgetWithBounds() with an empty |bounds|.
337     views::Widget* widget = views::DialogDelegate::CreateDialogWidget(
338         this, athena::ScreenManager::Get()->GetContext(), nullptr);
339     widget->Show();
340     widget->CenterWindow(gfx::Size(400, 400));
341   }
342
343   void CreateNetworkList() {
344     const int kListHeight = 400;
345     scroller_ = new views::ScrollView();
346     scroller_->set_background(
347         views::Background::CreateSolidBackground(SK_ColorWHITE));
348
349     scroll_content_ = new views::View;
350     scroll_content_->SetLayoutManager(
351         new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0));
352     scroller_->SetContents(scroll_content_);
353
354     scroller_->ClipHeightTo(kListHeight, kListHeight);
355     scroller_->SetVerticalScrollBar(new views::OverlayScrollBar(false));
356
357     network_list_.set_content_view(scroll_content_);
358   }
359
360   void UpdateNetworkList() { network_list_.UpdateNetworkList(); }
361
362   // ui::NetworkListDelegate:
363   virtual views::View* CreateViewForNetwork(
364       const ui::NetworkInfo& info) override {
365     return new NetworkRow(info);
366   }
367
368   virtual bool IsViewHovered(views::View* view) override {
369     return static_cast<NetworkRow*>(view)->has_password_view();
370   }
371
372   virtual chromeos::NetworkTypePattern GetNetworkTypePattern() const override {
373     return chromeos::NetworkTypePattern::NonVirtual();
374   }
375
376   virtual void UpdateViewForNetwork(views::View* view,
377                                     const ui::NetworkInfo& info) override {
378     static_cast<NetworkRow*>(view)->Update(info);
379   }
380
381   virtual views::Label* CreateInfoLabel() override {
382     views::Label* label = new views::Label();
383     return label;
384   }
385
386   virtual void RelayoutScrollList() override { scroller_->Layout(); }
387
388   // chromeos::NetworkStateHandlerObserver:
389   virtual void NetworkListChanged() override { UpdateNetworkList(); }
390
391   virtual void DeviceListChanged() override {}
392
393   virtual void DefaultNetworkChanged(
394       const chromeos::NetworkState* network) override {}
395
396   virtual void NetworkConnectionStateChanged(
397       const chromeos::NetworkState* network) override {}
398
399   virtual void NetworkPropertiesUpdated(
400       const chromeos::NetworkState* network) override {}
401
402   // views::DialogDelegate:
403   virtual ui::ModalType GetModalType() const override {
404     return ui::MODAL_TYPE_SYSTEM;
405   }
406   virtual void DeleteDelegate() override { delete this; }
407   virtual views::Widget* GetWidget() override { return scroller_->GetWidget(); }
408   virtual const views::Widget* GetWidget() const override {
409     return scroller_->GetWidget();
410   }
411   virtual views::View* GetContentsView() override { return scroller_; }
412   virtual int GetDialogButtons() const override { return ui::DIALOG_BUTTON_OK; }
413   virtual bool Close() override { return true; }
414
415   views::View* scroll_content_;
416   views::ScrollView* scroller_;
417
418   views::View* connect_;
419
420   ui::NetworkListView network_list_;
421
422   DISALLOW_COPY_AND_ASSIGN(NetworkSelector);
423 };
424
425 }  // namespace
426
427 namespace athena {
428
429 void CreateNetworkSelector() {
430   new NetworkSelector();
431 }
432
433 }  // namespace athena