wimax_config_view.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
1// Copyright (c) 2012 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/options/wimax_config_view.h"
6
7#include "ash/system/chromeos/network/network_connect.h"
8#include "base/bind.h"
9#include "base/strings/string_util.h"
10#include "base/strings/stringprintf.h"
11#include "base/strings/utf_string_conversions.h"
12#include "chrome/browser/chromeos/enrollment_dialog_view.h"
13#include "chrome/browser/chromeos/login/startup_utils.h"
14#include "chrome/browser/chromeos/net/onc_utils.h"
15#include "chrome/browser/profiles/profile_manager.h"
16#include "chromeos/login/login_state.h"
17#include "chromeos/network/network_configuration_handler.h"
18#include "chromeos/network/network_event_log.h"
19#include "chromeos/network/network_profile.h"
20#include "chromeos/network/network_profile_handler.h"
21#include "chromeos/network/network_state.h"
22#include "chromeos/network/network_state_handler.h"
23#include "components/onc/onc_constants.h"
24#include "grit/chromium_strings.h"
25#include "grit/generated_resources.h"
26#include "grit/locale_settings.h"
27#include "grit/theme_resources.h"
28#include "third_party/cros_system_api/dbus/service_constants.h"
29#include "ui/base/l10n/l10n_util.h"
30#include "ui/base/resource/resource_bundle.h"
31#include "ui/events/event.h"
32#include "ui/views/controls/button/checkbox.h"
33#include "ui/views/controls/button/image_button.h"
34#include "ui/views/controls/label.h"
35#include "ui/views/controls/textfield/textfield.h"
36#include "ui/views/layout/grid_layout.h"
37#include "ui/views/layout/layout_constants.h"
38#include "ui/views/widget/widget.h"
39#include "ui/views/window/dialog_client_view.h"
40
41namespace chromeos {
42
43namespace {
44
45void ShillError(const std::string& function,
46                const std::string& error_name,
47                scoped_ptr<base::DictionaryValue> error_data) {
48  NET_LOG_ERROR("Shill Error from WimaxConfigView: " + error_name, function);
49}
50
51}  // namespace
52
53WimaxConfigView::WimaxConfigView(NetworkConfigView* parent,
54                                 const std::string& service_path)
55    : ChildNetworkConfigView(parent, service_path),
56      identity_label_(NULL),
57      identity_textfield_(NULL),
58      save_credentials_checkbox_(NULL),
59      share_network_checkbox_(NULL),
60      shared_network_label_(NULL),
61      passphrase_label_(NULL),
62      passphrase_textfield_(NULL),
63      passphrase_visible_button_(NULL),
64      error_label_(NULL),
65      weak_ptr_factory_(this) {
66  Init();
67}
68
69WimaxConfigView::~WimaxConfigView() {
70  RemoveAllChildViews(true);  // Destroy children before models
71}
72
73base::string16 WimaxConfigView::GetTitle() const {
74  return l10n_util::GetStringUTF16(IDS_OPTIONS_SETTINGS_JOIN_WIMAX_NETWORKS);
75}
76
77views::View* WimaxConfigView::GetInitiallyFocusedView() {
78  if (identity_textfield_ && identity_textfield_->enabled())
79    return identity_textfield_;
80  if (passphrase_textfield_ && passphrase_textfield_->enabled())
81    return passphrase_textfield_;
82  return NULL;
83}
84
85bool WimaxConfigView::CanLogin() {
86  // In OOBE it may be valid to log in with no credentials (crbug.com/137776).
87  if (!chromeos::StartupUtils::IsOobeCompleted())
88    return true;
89
90  // TODO(benchan): Update this with the correct minimum length (don't just
91  // check if empty).
92  // If the network requires a passphrase, make sure it is the right length.
93  return passphrase_textfield_ && !passphrase_textfield_->text().empty();
94}
95
96void WimaxConfigView::UpdateDialogButtons() {
97  parent_->GetDialogClientView()->UpdateDialogButtons();
98}
99
100void WimaxConfigView::UpdateErrorLabel() {
101  base::string16 error_msg;
102  if (!service_path_.empty()) {
103    const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
104        GetNetworkState(service_path_);
105    if (wimax && wimax->connection_state() == shill::kStateFailure)
106      error_msg = ash::network_connect::ErrorString(
107          wimax->error(), wimax->path());
108  }
109  if (!error_msg.empty()) {
110    error_label_->SetText(error_msg);
111    error_label_->SetVisible(true);
112  } else {
113    error_label_->SetVisible(false);
114  }
115}
116
117void WimaxConfigView::ContentsChanged(views::Textfield* sender,
118                                      const base::string16& new_contents) {
119  UpdateDialogButtons();
120}
121
122bool WimaxConfigView::HandleKeyEvent(views::Textfield* sender,
123                                     const ui::KeyEvent& key_event) {
124  if (sender == passphrase_textfield_ &&
125      key_event.key_code() == ui::VKEY_RETURN) {
126    parent_->GetDialogClientView()->AcceptWindow();
127  }
128  return false;
129}
130
131void WimaxConfigView::ButtonPressed(views::Button* sender,
132                                   const ui::Event& event) {
133  if (sender == passphrase_visible_button_ && passphrase_textfield_) {
134    if (passphrase_textfield_->GetTextInputType() == ui::TEXT_INPUT_TYPE_TEXT) {
135      passphrase_textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
136      passphrase_visible_button_->SetToggled(false);
137    } else {
138      passphrase_textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_TEXT);
139      passphrase_visible_button_->SetToggled(true);
140    }
141  } else {
142    NOTREACHED();
143  }
144}
145
146bool WimaxConfigView::Login() {
147  const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
148      GetNetworkState(service_path_);
149  if (!wimax) {
150    // Shill no longer knows about this network (edge case).
151    // TODO(stevenjb): Add notification for this.
152    NET_LOG_ERROR("Network not found", service_path_);
153    return true;  // Close dialog
154  }
155  base::DictionaryValue properties;
156  properties.SetStringWithoutPathExpansion(
157      shill::kEapIdentityProperty, GetEapIdentity());
158  properties.SetStringWithoutPathExpansion(
159      shill::kEapPasswordProperty, GetEapPassphrase());
160  properties.SetBooleanWithoutPathExpansion(
161      shill::kSaveCredentialsProperty, GetSaveCredentials());
162
163  const bool share_default = true;
164  bool share_network = GetShareNetwork(share_default);
165
166  bool only_policy_autoconnect =
167      onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!share_network);
168  if (only_policy_autoconnect) {
169    properties.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty,
170                                              false);
171  }
172
173  ash::network_connect::ConfigureNetworkAndConnect(
174      service_path_, properties, share_network);
175  return true;  // dialog will be closed
176}
177
178std::string WimaxConfigView::GetEapIdentity() const {
179  DCHECK(identity_textfield_);
180  return base::UTF16ToUTF8(identity_textfield_->text());
181}
182
183std::string WimaxConfigView::GetEapPassphrase() const {
184  return passphrase_textfield_ ? base::UTF16ToUTF8(
185                                     passphrase_textfield_->text()) :
186                                 std::string();
187}
188
189bool WimaxConfigView::GetSaveCredentials() const {
190  return save_credentials_checkbox_ ? save_credentials_checkbox_->checked() :
191                                      false;
192}
193
194bool WimaxConfigView::GetShareNetwork(bool share_default) const {
195  return share_network_checkbox_ ? share_network_checkbox_->checked() :
196                                   share_default;
197}
198
199void WimaxConfigView::Cancel() {
200}
201
202void WimaxConfigView::Init() {
203  const NetworkState* wimax = NetworkHandler::Get()->network_state_handler()->
204      GetNetworkState(service_path_);
205  DCHECK(wimax && wimax->type() == shill::kTypeWimax);
206
207  WifiConfigView::ParseWiFiEAPUIProperty(
208      &save_credentials_ui_data_, wimax, ::onc::eap::kSaveCredentials);
209  WifiConfigView::ParseWiFiEAPUIProperty(
210      &identity_ui_data_, wimax, ::onc::eap::kIdentity);
211  WifiConfigView::ParseWiFiUIProperty(
212      &passphrase_ui_data_, wimax, ::onc::wifi::kPassphrase);
213
214  views::GridLayout* layout = views::GridLayout::CreatePanel(this);
215  SetLayoutManager(layout);
216
217  const int column_view_set_id = 0;
218  views::ColumnSet* column_set = layout->AddColumnSet(column_view_set_id);
219  const int kPasswordVisibleWidth = 20;
220  // Label
221  column_set->AddColumn(views::GridLayout::LEADING, views::GridLayout::FILL, 1,
222                        views::GridLayout::USE_PREF, 0, 0);
223  column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
224  // Textfield, combobox.
225  column_set->AddColumn(views::GridLayout::FILL, views::GridLayout::FILL, 1,
226                        views::GridLayout::USE_PREF, 0,
227                        ChildNetworkConfigView::kInputFieldMinWidth);
228  column_set->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing);
229  // Password visible button / policy indicator.
230  column_set->AddColumn(views::GridLayout::CENTER, views::GridLayout::FILL, 1,
231                        views::GridLayout::USE_PREF, 0, kPasswordVisibleWidth);
232
233  // Network name
234  layout->StartRow(0, column_view_set_id);
235  layout->AddView(new views::Label(l10n_util::GetStringUTF16(
236      IDS_OPTIONS_SETTINGS_INTERNET_TAB_NETWORK)));
237  views::Label* label = new views::Label(base::UTF8ToUTF16(wimax->name()));
238  label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
239  layout->AddView(label);
240  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
241
242  // Identity
243  layout->StartRow(0, column_view_set_id);
244  base::string16 identity_label_text = l10n_util::GetStringUTF16(
245      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_IDENTITY);
246  identity_label_ = new views::Label(identity_label_text);
247  layout->AddView(identity_label_);
248  identity_textfield_ = new views::Textfield();
249  identity_textfield_->SetAccessibleName(identity_label_text);
250  identity_textfield_->set_controller(this);
251  identity_textfield_->SetEnabled(identity_ui_data_.IsEditable());
252  layout->AddView(identity_textfield_);
253  layout->AddView(new ControlledSettingIndicatorView(identity_ui_data_));
254  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
255
256  // Passphrase input
257  layout->StartRow(0, column_view_set_id);
258  base::string16 passphrase_label_text = l10n_util::GetStringUTF16(
259      IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE);
260  passphrase_label_ = new views::Label(passphrase_label_text);
261  layout->AddView(passphrase_label_);
262  passphrase_textfield_ = new views::Textfield();
263  passphrase_textfield_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
264  passphrase_textfield_->set_controller(this);
265  passphrase_label_->SetEnabled(true);
266  passphrase_textfield_->SetEnabled(passphrase_ui_data_.IsEditable());
267  passphrase_textfield_->SetAccessibleName(passphrase_label_text);
268  layout->AddView(passphrase_textfield_);
269
270  if (passphrase_ui_data_.IsManaged()) {
271    layout->AddView(new ControlledSettingIndicatorView(passphrase_ui_data_));
272  } else {
273    // Password visible button.
274    passphrase_visible_button_ = new views::ToggleImageButton(this);
275    passphrase_visible_button_->SetFocusable(true);
276    passphrase_visible_button_->SetTooltipText(
277        l10n_util::GetStringUTF16(
278            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_SHOW));
279    passphrase_visible_button_->SetToggledTooltipText(
280        l10n_util::GetStringUTF16(
281            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PASSPHRASE_HIDE));
282    passphrase_visible_button_->SetImage(
283        views::ImageButton::STATE_NORMAL,
284        ResourceBundle::GetSharedInstance().
285        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD));
286    passphrase_visible_button_->SetImage(
287        views::ImageButton::STATE_HOVERED,
288        ResourceBundle::GetSharedInstance().
289        GetImageSkiaNamed(IDR_NETWORK_SHOW_PASSWORD_HOVER));
290    passphrase_visible_button_->SetToggledImage(
291        views::ImageButton::STATE_NORMAL,
292        ResourceBundle::GetSharedInstance().
293        GetImageSkiaNamed(IDR_NETWORK_HIDE_PASSWORD));
294    passphrase_visible_button_->SetToggledImage(
295        views::ImageButton::STATE_HOVERED,
296        ResourceBundle::GetSharedInstance().
297        GetImageSkiaNamed(IDR_NETWORK_HIDE_PASSWORD_HOVER));
298    passphrase_visible_button_->SetImageAlignment(
299        views::ImageButton::ALIGN_CENTER, views::ImageButton::ALIGN_MIDDLE);
300    layout->AddView(passphrase_visible_button_);
301  }
302
303  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
304
305  // Checkboxes.
306
307  if (LoginState::Get()->IsUserAuthenticated()) {
308    // Save credentials
309    layout->StartRow(0, column_view_set_id);
310    save_credentials_checkbox_ = new views::Checkbox(
311        l10n_util::GetStringUTF16(
312            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS));
313    save_credentials_checkbox_->SetEnabled(
314        save_credentials_ui_data_.IsEditable());
315    layout->SkipColumns(1);
316    layout->AddView(save_credentials_checkbox_);
317    layout->AddView(
318        new ControlledSettingIndicatorView(save_credentials_ui_data_));
319  }
320
321  // Share network
322  if (wimax->profile_path().empty()) {
323    layout->StartRow(0, column_view_set_id);
324    share_network_checkbox_ = new views::Checkbox(
325        l10n_util::GetStringUTF16(
326            IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SHARE_NETWORK));
327    if (LoginState::Get()->IsUserAuthenticated()) {
328      share_network_checkbox_->SetChecked(false);  // Default to unshared
329      share_network_checkbox_->SetEnabled(true);
330    } else {
331      // Not logged in, must be shared
332      share_network_checkbox_->SetChecked(true);
333      share_network_checkbox_->SetEnabled(false);
334    }
335    layout->SkipColumns(1);
336    layout->AddView(share_network_checkbox_);
337  }
338  layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
339
340  // Create an error label.
341  layout->StartRow(0, column_view_set_id);
342  layout->SkipColumns(1);
343  error_label_ = new views::Label();
344  error_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
345  error_label_->SetEnabledColor(SK_ColorRED);
346  layout->AddView(error_label_);
347
348  UpdateErrorLabel();
349
350  if (wimax) {
351    NetworkHandler::Get()->network_configuration_handler()->GetProperties(
352        service_path_,
353        base::Bind(&WimaxConfigView::InitFromProperties,
354                   weak_ptr_factory_.GetWeakPtr()),
355        base::Bind(&ShillError, "GetProperties"));
356  }
357}
358
359void WimaxConfigView::InitFromProperties(
360    const std::string& service_path,
361    const base::DictionaryValue& properties) {
362  // EapIdentity
363  std::string eap_identity;
364  properties.GetStringWithoutPathExpansion(
365      shill::kEapIdentityProperty, &eap_identity);
366  identity_textfield_->SetText(base::UTF8ToUTF16(eap_identity));
367
368  // Save credentials
369  if (save_credentials_checkbox_) {
370    bool save_credentials = false;
371    properties.GetBooleanWithoutPathExpansion(
372        shill::kSaveCredentialsProperty, &save_credentials);
373    save_credentials_checkbox_->SetChecked(save_credentials);
374  }
375}
376
377void WimaxConfigView::InitFocus() {
378  views::View* view_to_focus = GetInitiallyFocusedView();
379  if (view_to_focus)
380    view_to_focus->RequestFocus();
381}
382
383}  // namespace chromeos
384