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.
5 #include "chrome/browser/chromeos/options/vpn_config_view.h"
7 #include "ash/system/chromeos/network/network_connect.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/net/onc_utils.h"
14 #include "chrome/browser/profiles/profile_manager.h"
15 #include "chrome/common/net/x509_certificate_model.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_state.h"
20 #include "chromeos/network/network_state_handler.h"
21 #include "chromeos/network/network_ui_data.h"
22 #include "components/onc/onc_constants.h"
23 #include "grit/chromium_strings.h"
24 #include "grit/generated_resources.h"
25 #include "grit/locale_settings.h"
26 #include "grit/theme_resources.h"
27 #include "third_party/cros_system_api/dbus/service_constants.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/models/combobox_model.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/combobox/combobox.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"
43 enum ProviderTypeIndex
{
44 PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
= 0,
45 PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
= 1,
46 PROVIDER_TYPE_INDEX_OPEN_VPN
= 2,
47 PROVIDER_TYPE_INDEX_MAX
= 3,
50 base::string16
ProviderTypeIndexToString(int index
) {
52 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
53 return l10n_util::GetStringUTF16(
54 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK
);
55 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
56 return l10n_util::GetStringUTF16(
57 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT
);
58 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
59 return l10n_util::GetStringUTF16(
60 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN
);
63 return base::string16();
66 int ProviderTypeToIndex(const std::string
& provider_type
,
67 const std::string
& client_cert_id
) {
68 if (provider_type
== shill::kProviderL2tpIpsec
) {
69 if (!client_cert_id
.empty())
70 return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
72 return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
;
74 DCHECK(provider_type
== shill::kProviderOpenVpn
);
75 return PROVIDER_TYPE_INDEX_OPEN_VPN
;
79 // Translates the provider type to the name of the respective ONC dictionary
80 // containing configuration data for the type.
81 std::string
ProviderTypeIndexToONCDictKey(int provider_type_index
) {
82 switch (provider_type_index
) {
83 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
84 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
85 return onc::vpn::kIPsec
;
86 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
87 return onc::vpn::kOpenVPN
;
89 NOTREACHED() << "Unhandled provider type index " << provider_type_index
;
93 std::string
GetPemFromDictionary(
94 const base::DictionaryValue
* provider_properties
,
95 const std::string
& key
) {
96 const base::ListValue
* pems
= NULL
;
97 if (!provider_properties
->GetListWithoutPathExpansion(key
, &pems
))
100 pems
->GetString(0, &pem
);
110 class ProviderTypeComboboxModel
: public ui::ComboboxModel
{
112 ProviderTypeComboboxModel();
113 virtual ~ProviderTypeComboboxModel();
115 // Overridden from ui::ComboboxModel:
116 virtual int GetItemCount() const OVERRIDE
;
117 virtual base::string16
GetItemAt(int index
) OVERRIDE
;
120 DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel
);
123 class VpnServerCACertComboboxModel
: public ui::ComboboxModel
{
125 VpnServerCACertComboboxModel();
126 virtual ~VpnServerCACertComboboxModel();
128 // Overridden from ui::ComboboxModel:
129 virtual int GetItemCount() const OVERRIDE
;
130 virtual base::string16
GetItemAt(int index
) OVERRIDE
;
133 DISALLOW_COPY_AND_ASSIGN(VpnServerCACertComboboxModel
);
136 class VpnUserCertComboboxModel
: public ui::ComboboxModel
{
138 VpnUserCertComboboxModel();
139 virtual ~VpnUserCertComboboxModel();
141 // Overridden from ui::ComboboxModel:
142 virtual int GetItemCount() const OVERRIDE
;
143 virtual base::string16
GetItemAt(int index
) OVERRIDE
;
146 DISALLOW_COPY_AND_ASSIGN(VpnUserCertComboboxModel
);
149 // ProviderTypeComboboxModel ---------------------------------------------------
151 ProviderTypeComboboxModel::ProviderTypeComboboxModel() {
154 ProviderTypeComboboxModel::~ProviderTypeComboboxModel() {
157 int ProviderTypeComboboxModel::GetItemCount() const {
158 return PROVIDER_TYPE_INDEX_MAX
;
161 base::string16
ProviderTypeComboboxModel::GetItemAt(int index
) {
162 return ProviderTypeIndexToString(index
);
165 // VpnServerCACertComboboxModel ------------------------------------------------
167 VpnServerCACertComboboxModel::VpnServerCACertComboboxModel() {
170 VpnServerCACertComboboxModel::~VpnServerCACertComboboxModel() {
173 int VpnServerCACertComboboxModel::GetItemCount() const {
174 if (CertLibrary::Get()->CertificatesLoading())
175 return 1; // "Loading"
176 // "Default" + certs.
177 return CertLibrary::Get()->NumCertificates(
178 CertLibrary::CERT_TYPE_SERVER_CA
) + 1;
181 base::string16
VpnServerCACertComboboxModel::GetItemAt(int index
) {
182 if (CertLibrary::Get()->CertificatesLoading())
183 return l10n_util::GetStringUTF16(
184 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING
);
186 return l10n_util::GetStringUTF16(
187 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT
);
188 int cert_index
= index
- 1;
189 return CertLibrary::Get()->GetCertDisplayStringAt(
190 CertLibrary::CERT_TYPE_SERVER_CA
, cert_index
);
193 // VpnUserCertComboboxModel ----------------------------------------------------
195 VpnUserCertComboboxModel::VpnUserCertComboboxModel() {
198 VpnUserCertComboboxModel::~VpnUserCertComboboxModel() {
201 int VpnUserCertComboboxModel::GetItemCount() const {
202 if (CertLibrary::Get()->CertificatesLoading())
203 return 1; // "Loading"
205 CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
);
207 return 1; // "None installed"
211 base::string16
VpnUserCertComboboxModel::GetItemAt(int index
) {
212 if (CertLibrary::Get()->CertificatesLoading()) {
213 return l10n_util::GetStringUTF16(
214 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING
);
216 if (CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
) == 0) {
217 return l10n_util::GetStringUTF16(
218 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED
);
220 return CertLibrary::Get()->GetCertDisplayStringAt(
221 CertLibrary::CERT_TYPE_USER
, index
);
224 } // namespace internal
226 VPNConfigView::VPNConfigView(NetworkConfigView
* parent
,
227 const std::string
& service_path
)
228 : ChildNetworkConfigView(parent
, service_path
),
229 service_text_modified_(false),
230 enable_psk_passphrase_(false),
231 enable_user_cert_(false),
232 enable_server_ca_cert_(false),
234 enable_group_name_(false),
237 server_textfield_(NULL
),
239 service_textfield_(NULL
),
240 provider_type_combobox_(NULL
),
241 provider_type_text_label_(NULL
),
242 psk_passphrase_label_(NULL
),
243 psk_passphrase_textfield_(NULL
),
244 user_cert_label_(NULL
),
245 user_cert_combobox_(NULL
),
246 server_ca_cert_label_(NULL
),
247 server_ca_cert_combobox_(NULL
),
248 username_textfield_(NULL
),
249 user_passphrase_textfield_(NULL
),
251 otp_textfield_(NULL
),
252 group_name_label_(NULL
),
253 group_name_textfield_(NULL
),
254 save_credentials_checkbox_(NULL
),
256 provider_type_index_(PROVIDER_TYPE_INDEX_MAX
),
257 weak_ptr_factory_(this) {
261 VPNConfigView::~VPNConfigView() {
262 RemoveAllChildViews(true); // Destroy children before models
263 CertLibrary::Get()->RemoveObserver(this);
266 base::string16
VPNConfigView::GetTitle() const {
267 DCHECK_NE(title_
, 0);
268 return l10n_util::GetStringUTF16(title_
);
271 views::View
* VPNConfigView::GetInitiallyFocusedView() {
272 if (service_path_
.empty()) {
273 // Put focus in the first editable field.
274 if (server_textfield_
)
275 return server_textfield_
;
276 else if (service_textfield_
)
277 return service_textfield_
;
278 else if (provider_type_combobox_
)
279 return provider_type_combobox_
;
280 else if (psk_passphrase_textfield_
&& psk_passphrase_textfield_
->enabled())
281 return psk_passphrase_textfield_
;
282 else if (user_cert_combobox_
&& user_cert_combobox_
->enabled())
283 return user_cert_combobox_
;
284 else if (server_ca_cert_combobox_
&& server_ca_cert_combobox_
->enabled())
285 return server_ca_cert_combobox_
;
287 if (user_passphrase_textfield_
)
288 return user_passphrase_textfield_
;
289 else if (otp_textfield_
)
290 return otp_textfield_
;
294 bool VPNConfigView::CanLogin() {
295 // Username is always required.
296 if (GetUsername().empty())
299 // TODO(stevenjb): min kMinPassphraseLen length?
300 if (service_path_
.empty() &&
301 (GetService().empty() || GetServer().empty()))
304 // Block login if certs are required but user has none.
306 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
307 if (cert_required
&& (!HaveUserCerts() || !IsUserCertValid()))
313 void VPNConfigView::ContentsChanged(views::Textfield
* sender
,
314 const base::string16
& new_contents
) {
315 if (sender
== server_textfield_
&& !service_text_modified_
) {
316 // Set the service name to the server name up to '.', unless it has
317 // been explicitly set by the user.
318 base::string16 server
= server_textfield_
->text();
319 base::string16::size_type n
= server
.find_first_of(L
'.');
320 service_name_from_server_
= server
.substr(0, n
);
321 service_textfield_
->SetText(service_name_from_server_
);
323 if (sender
== service_textfield_
) {
324 if (new_contents
.empty())
325 service_text_modified_
= false;
326 else if (new_contents
!= service_name_from_server_
)
327 service_text_modified_
= true;
332 bool VPNConfigView::HandleKeyEvent(views::Textfield
* sender
,
333 const ui::KeyEvent
& key_event
) {
334 if ((sender
== psk_passphrase_textfield_
||
335 sender
== user_passphrase_textfield_
) &&
336 key_event
.key_code() == ui::VKEY_RETURN
) {
337 parent_
->GetDialogClientView()->AcceptWindow();
342 void VPNConfigView::ButtonPressed(views::Button
* sender
,
343 const ui::Event
& event
) {
346 void VPNConfigView::OnPerformAction(views::Combobox
* combobox
) {
352 void VPNConfigView::OnCertificatesLoaded(bool initial_load
) {
356 bool VPNConfigView::Login() {
357 if (service_path_
.empty()) {
358 base::DictionaryValue properties
;
359 // Identifying properties
360 properties
.SetStringWithoutPathExpansion(
361 shill::kTypeProperty
, shill::kTypeVPN
);
362 properties
.SetStringWithoutPathExpansion(
363 shill::kNameProperty
, GetService());
364 properties
.SetStringWithoutPathExpansion(
365 shill::kProviderHostProperty
, GetServer());
366 properties
.SetStringWithoutPathExpansion(
367 shill::kProviderTypeProperty
, GetProviderTypeString());
369 SetConfigProperties(&properties
);
370 bool shared
= !LoginState::Get()->IsUserAuthenticated();
372 bool only_policy_autoconnect
=
373 onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!shared
);
374 if (only_policy_autoconnect
) {
375 properties
.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty
,
379 ash::network_connect::CreateConfigurationAndConnect(&properties
, shared
);
381 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
382 GetNetworkState(service_path_
);
384 // Shill no longer knows about this network (edge case).
385 // TODO(stevenjb): Add notification for this.
386 NET_LOG_ERROR("Network not found", service_path_
);
387 return true; // Close dialog
389 base::DictionaryValue properties
;
390 SetConfigProperties(&properties
);
391 ash::network_connect::ConfigureNetworkAndConnect(
392 service_path_
, properties
, false /* not shared */);
394 return true; // Close dialog.
397 void VPNConfigView::Cancel() {
400 void VPNConfigView::InitFocus() {
401 views::View
* view_to_focus
= GetInitiallyFocusedView();
403 view_to_focus
->RequestFocus();
406 const std::string
VPNConfigView::GetService() const {
407 if (service_textfield_
!= NULL
)
408 return GetTextFromField(service_textfield_
, true);
409 return service_path_
;
412 const std::string
VPNConfigView::GetServer() const {
413 if (server_textfield_
!= NULL
)
414 return GetTextFromField(server_textfield_
, true);
415 return std::string();
418 const std::string
VPNConfigView::GetPSKPassphrase() const {
419 if (psk_passphrase_textfield_
&&
420 enable_psk_passphrase_
&&
421 psk_passphrase_textfield_
->visible())
422 return GetPassphraseFromField(psk_passphrase_textfield_
);
423 return std::string();
426 const std::string
VPNConfigView::GetUsername() const {
427 return GetTextFromField(username_textfield_
, true);
430 const std::string
VPNConfigView::GetUserPassphrase() const {
431 return GetPassphraseFromField(user_passphrase_textfield_
);
434 const std::string
VPNConfigView::GetGroupName() const {
435 return GetTextFromField(group_name_textfield_
, false);
438 const std::string
VPNConfigView::GetOTP() const {
439 return GetTextFromField(otp_textfield_
, true);
442 const std::string
VPNConfigView::GetServerCACertPEM() const {
443 int index
= server_ca_cert_combobox_
?
444 server_ca_cert_combobox_
->selected_index() : 0;
446 // First item is "Default".
447 return std::string();
449 int cert_index
= index
- 1;
450 return CertLibrary::Get()->GetCertPEMAt(
451 CertLibrary::CERT_TYPE_SERVER_CA
, cert_index
);
455 const std::string
VPNConfigView::GetUserCertID() const {
456 if (!HaveUserCerts()) {
457 return std::string(); // "None installed"
459 // Certificates are listed in the order they appear in the model.
460 int index
= user_cert_combobox_
? user_cert_combobox_
->selected_index() : 0;
461 return CertLibrary::Get()->GetCertPkcs11IdAt(
462 CertLibrary::CERT_TYPE_USER
, index
);
466 bool VPNConfigView::GetSaveCredentials() const {
467 return save_credentials_checkbox_
->checked();
470 int VPNConfigView::GetProviderTypeIndex() const {
471 if (provider_type_combobox_
)
472 return provider_type_combobox_
->selected_index();
473 return provider_type_index_
;
476 std::string
VPNConfigView::GetProviderTypeString() const {
477 int index
= GetProviderTypeIndex();
479 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
480 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
481 return shill::kProviderL2tpIpsec
;
482 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
483 return shill::kProviderOpenVpn
;
486 return std::string();
489 void VPNConfigView::Init() {
490 const NetworkState
* vpn
= NULL
;
491 if (!service_path_
.empty()) {
492 vpn
= NetworkHandler::Get()->network_state_handler()->
493 GetNetworkState(service_path_
);
494 DCHECK(vpn
&& vpn
->type() == shill::kTypeVPN
);
496 layout_
= views::GridLayout::CreatePanel(this);
497 SetLayoutManager(layout_
);
499 // Observer any changes to the certificate list.
500 CertLibrary::Get()->AddObserver(this);
502 views::ColumnSet
* column_set
= layout_
->AddColumnSet(0);
504 column_set
->AddColumn(views::GridLayout::LEADING
, views::GridLayout::FILL
, 1,
505 views::GridLayout::USE_PREF
, 0, 0);
506 column_set
->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing
);
507 // Textfield, combobox.
508 column_set
->AddColumn(views::GridLayout::FILL
, views::GridLayout::FILL
, 1,
509 views::GridLayout::USE_PREF
, 0,
510 ChildNetworkConfigView::kInputFieldMinWidth
);
511 column_set
->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing
);
513 column_set
->AddColumn(views::GridLayout::CENTER
, views::GridLayout::CENTER
, 0,
514 views::GridLayout::USE_PREF
, 0, 0);
516 // Initialize members.
517 service_text_modified_
= false;
518 title_
= vpn
? IDS_OPTIONS_SETTINGS_JOIN_VPN
: IDS_OPTIONS_SETTINGS_ADD_VPN
;
520 // By default enable all controls.
521 enable_psk_passphrase_
= true;
522 enable_user_cert_
= true;
523 enable_server_ca_cert_
= true;
525 enable_group_name_
= true;
527 // Server label and input.
528 layout_
->StartRow(0, 0);
529 views::View
* server_label
=
530 new views::Label(l10n_util::GetStringUTF16(
531 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME
));
532 layout_
->AddView(server_label
);
533 server_textfield_
= new views::Textfield();
534 server_textfield_
->set_controller(this);
535 layout_
->AddView(server_textfield_
);
536 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
537 if (!service_path_
.empty()) {
538 server_label
->SetEnabled(false);
539 server_textfield_
->SetEnabled(false);
542 // Service label and name or input.
543 layout_
->StartRow(0, 0);
544 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
545 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME
)));
546 if (service_path_
.empty()) {
547 service_textfield_
= new views::Textfield();
548 service_textfield_
->set_controller(this);
549 layout_
->AddView(service_textfield_
);
550 service_text_
= NULL
;
552 service_text_
= new views::Label();
553 service_text_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
554 layout_
->AddView(service_text_
);
555 service_textfield_
= NULL
;
557 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
559 // Provider type label and select.
560 layout_
->StartRow(0, 0);
561 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
562 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE
)));
563 if (service_path_
.empty()) {
564 provider_type_combobox_model_
.reset(
565 new internal::ProviderTypeComboboxModel
);
566 provider_type_combobox_
= new views::Combobox(
567 provider_type_combobox_model_
.get());
568 provider_type_combobox_
->set_listener(this);
569 layout_
->AddView(provider_type_combobox_
);
570 provider_type_text_label_
= NULL
;
572 provider_type_text_label_
= new views::Label();
573 provider_type_text_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
574 layout_
->AddView(provider_type_text_label_
);
575 provider_type_combobox_
= NULL
;
577 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
579 // PSK passphrase label, input and visible button.
580 layout_
->StartRow(0, 0);
581 psk_passphrase_label_
= new views::Label(l10n_util::GetStringUTF16(
582 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE
));
583 layout_
->AddView(psk_passphrase_label_
);
584 psk_passphrase_textfield_
= new PassphraseTextfield();
585 psk_passphrase_textfield_
->set_controller(this);
586 layout_
->AddView(psk_passphrase_textfield_
);
588 new ControlledSettingIndicatorView(psk_passphrase_ui_data_
));
589 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
591 // Server CA certificate
592 if (service_path_
.empty()) {
593 layout_
->StartRow(0, 0);
594 server_ca_cert_label_
= new views::Label(l10n_util::GetStringUTF16(
595 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA
));
596 layout_
->AddView(server_ca_cert_label_
);
597 server_ca_cert_combobox_model_
.reset(
598 new internal::VpnServerCACertComboboxModel());
599 server_ca_cert_combobox_
= new views::Combobox(
600 server_ca_cert_combobox_model_
.get());
601 layout_
->AddView(server_ca_cert_combobox_
);
602 layout_
->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_
));
603 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
605 server_ca_cert_label_
= NULL
;
606 server_ca_cert_combobox_
= NULL
;
609 // User certificate label and input.
610 layout_
->StartRow(0, 0);
611 user_cert_label_
= new views::Label(l10n_util::GetStringUTF16(
612 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT
));
613 layout_
->AddView(user_cert_label_
);
614 user_cert_combobox_model_
.reset(
615 new internal::VpnUserCertComboboxModel());
616 user_cert_combobox_
= new views::Combobox(user_cert_combobox_model_
.get());
617 user_cert_combobox_
->set_listener(this);
618 layout_
->AddView(user_cert_combobox_
);
619 layout_
->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_
));
620 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
622 // Username label and input.
623 layout_
->StartRow(0, 0);
624 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
625 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME
)));
626 username_textfield_
= new views::Textfield();
627 username_textfield_
->set_controller(this);
628 username_textfield_
->SetEnabled(username_ui_data_
.IsEditable());
629 layout_
->AddView(username_textfield_
);
630 layout_
->AddView(new ControlledSettingIndicatorView(username_ui_data_
));
631 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
633 // User passphrase label, input and visble button.
634 layout_
->StartRow(0, 0);
635 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
636 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE
)));
637 user_passphrase_textfield_
= new PassphraseTextfield();
638 user_passphrase_textfield_
->set_controller(this);
639 user_passphrase_textfield_
->SetEnabled(user_passphrase_ui_data_
.IsEditable());
640 layout_
->AddView(user_passphrase_textfield_
);
642 new ControlledSettingIndicatorView(user_passphrase_ui_data_
));
643 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
645 // OTP label and input.
646 layout_
->StartRow(0, 0);
647 otp_label_
= new views::Label(l10n_util::GetStringUTF16(
648 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP
));
649 layout_
->AddView(otp_label_
);
650 otp_textfield_
= new views::Textfield();
651 otp_textfield_
->set_controller(this);
652 layout_
->AddView(otp_textfield_
);
653 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
655 // Group Name label and input.
656 layout_
->StartRow(0, 0);
657 group_name_label_
= new views::Label(l10n_util::GetStringUTF16(
658 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME
));
659 layout_
->AddView(group_name_label_
);
660 group_name_textfield_
=
661 new views::Textfield();
662 group_name_textfield_
->set_controller(this);
663 layout_
->AddView(group_name_textfield_
);
664 layout_
->AddView(new ControlledSettingIndicatorView(group_name_ui_data_
));
665 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
668 layout_
->StartRow(0, 0);
669 save_credentials_checkbox_
= new views::Checkbox(
670 l10n_util::GetStringUTF16(
671 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS
));
672 save_credentials_checkbox_
->SetEnabled(
673 save_credentials_ui_data_
.IsEditable());
674 layout_
->SkipColumns(1);
675 layout_
->AddView(save_credentials_checkbox_
);
677 new ControlledSettingIndicatorView(save_credentials_ui_data_
));
680 layout_
->StartRow(0, 0);
681 layout_
->SkipColumns(1);
682 error_label_
= new views::Label();
683 error_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
684 error_label_
->SetEnabledColor(SK_ColorRED
);
685 layout_
->AddView(error_label_
);
687 // Set or hide the UI, update comboboxes and error labels.
691 NetworkHandler::Get()->network_configuration_handler()->GetProperties(
693 base::Bind(&VPNConfigView::InitFromProperties
,
694 weak_ptr_factory_
.GetWeakPtr()),
695 base::Bind(&VPNConfigView::GetPropertiesError
,
696 weak_ptr_factory_
.GetWeakPtr()));
700 void VPNConfigView::InitFromProperties(
701 const std::string
& service_path
,
702 const base::DictionaryValue
& service_properties
) {
703 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
704 GetNetworkState(service_path
);
706 NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path
);
710 std::string provider_type
, server_hostname
, username
, group_name
;
711 bool psk_passphrase_required
= false;
712 const base::DictionaryValue
* provider_properties
;
713 if (service_properties
.GetDictionaryWithoutPathExpansion(
714 shill::kProviderProperty
, &provider_properties
)) {
715 provider_properties
->GetStringWithoutPathExpansion(
716 shill::kTypeProperty
, &provider_type
);
717 provider_properties
->GetStringWithoutPathExpansion(
718 shill::kHostProperty
, &server_hostname
);
720 if (provider_type
== shill::kProviderL2tpIpsec
) {
721 provider_properties
->GetStringWithoutPathExpansion(
722 shill::kL2tpIpsecClientCertIdProperty
, &client_cert_id_
);
723 ca_cert_pem_
= GetPemFromDictionary(
724 provider_properties
, shill::kL2tpIpsecCaCertPemProperty
);
725 provider_properties
->GetBooleanWithoutPathExpansion(
726 shill::kL2tpIpsecPskRequiredProperty
, &psk_passphrase_required
);
727 provider_properties
->GetStringWithoutPathExpansion(
728 shill::kL2tpIpsecUserProperty
, &username
);
729 provider_properties
->GetStringWithoutPathExpansion(
730 shill::kL2tpIpsecTunnelGroupProperty
, &group_name
);
731 } else if (provider_type
== shill::kProviderOpenVpn
) {
732 provider_properties
->GetStringWithoutPathExpansion(
733 shill::kOpenVPNClientCertIdProperty
, &client_cert_id_
);
734 ca_cert_pem_
= GetPemFromDictionary(
735 provider_properties
, shill::kOpenVPNCaCertPemProperty
);
736 provider_properties
->GetStringWithoutPathExpansion(
737 shill::kOpenVPNUserProperty
, &username
);
739 bool save_credentials
= false;
740 service_properties
.GetBooleanWithoutPathExpansion(
741 shill::kSaveCredentialsProperty
, &save_credentials
);
743 provider_type_index_
= ProviderTypeToIndex(provider_type
, client_cert_id_
);
746 service_text_
->SetText(base::ASCIIToUTF16(vpn
->name()));
747 if (provider_type_text_label_
)
748 provider_type_text_label_
->SetText(
749 ProviderTypeIndexToString(provider_type_index_
));
751 if (server_textfield_
&& !server_hostname
.empty())
752 server_textfield_
->SetText(base::UTF8ToUTF16(server_hostname
));
753 if (username_textfield_
&& !username
.empty())
754 username_textfield_
->SetText(base::UTF8ToUTF16(username
));
755 if (group_name_textfield_
&& !group_name
.empty())
756 group_name_textfield_
->SetText(base::UTF8ToUTF16(group_name
));
757 if (psk_passphrase_textfield_
)
758 psk_passphrase_textfield_
->SetShowFake(!psk_passphrase_required
);
759 if (save_credentials_checkbox_
)
760 save_credentials_checkbox_
->SetChecked(save_credentials
);
765 void VPNConfigView::ParseUIProperties(const NetworkState
* vpn
) {
766 std::string type_dict_name
=
767 ProviderTypeIndexToONCDictKey(provider_type_index_
);
768 if (provider_type_index_
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
) {
769 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kServerCARef
,
771 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kPSK
,
772 &psk_passphrase_ui_data_
);
773 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kGroup
,
774 &group_name_ui_data_
);
775 } else if (provider_type_index_
== PROVIDER_TYPE_INDEX_OPEN_VPN
) {
776 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::openvpn::kServerCARef
,
779 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::vpn::kClientCertRef
,
780 &user_cert_ui_data_
);
782 const std::string
credentials_dict_name(
783 provider_type_index_
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
?
784 ::onc::vpn::kL2TP
: type_dict_name
);
785 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kUsername
,
787 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kPassword
,
788 &user_passphrase_ui_data_
);
789 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kSaveCredentials
,
790 &save_credentials_ui_data_
);
793 void VPNConfigView::GetPropertiesError(
794 const std::string
& error_name
,
795 scoped_ptr
<base::DictionaryValue
> error_data
) {
796 NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name
, "");
799 void VPNConfigView::SetConfigProperties(
800 base::DictionaryValue
* properties
) {
801 int provider_type_index
= GetProviderTypeIndex();
802 std::string user_passphrase
= GetUserPassphrase();
803 std::string user_name
= GetUsername();
804 std::string group_name
= GetGroupName();
805 switch (provider_type_index
) {
806 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
: {
807 std::string psk_passphrase
= GetPSKPassphrase();
808 if (!psk_passphrase
.empty()) {
809 properties
->SetStringWithoutPathExpansion(
810 shill::kL2tpIpsecPskProperty
, GetPSKPassphrase());
812 if (!group_name
.empty()) {
813 properties
->SetStringWithoutPathExpansion(
814 shill::kL2tpIpsecTunnelGroupProperty
, group_name
);
816 if (!user_name
.empty()) {
817 properties
->SetStringWithoutPathExpansion(
818 shill::kL2tpIpsecUserProperty
, user_name
);
820 if (!user_passphrase
.empty()) {
821 properties
->SetStringWithoutPathExpansion(
822 shill::kL2tpIpsecPasswordProperty
, user_passphrase
);
826 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
: {
827 std::string ca_cert_pem
= GetServerCACertPEM();
828 if (!ca_cert_pem
.empty()) {
829 base::ListValue
* pem_list
= new base::ListValue
;
830 pem_list
->AppendString(ca_cert_pem
);
831 properties
->SetWithoutPathExpansion(
832 shill::kL2tpIpsecCaCertPemProperty
, pem_list
);
834 properties
->SetStringWithoutPathExpansion(
835 shill::kL2tpIpsecClientCertIdProperty
, GetUserCertID());
836 if (!group_name
.empty()) {
837 properties
->SetStringWithoutPathExpansion(
838 shill::kL2tpIpsecTunnelGroupProperty
, GetGroupName());
840 if (!user_name
.empty()) {
841 properties
->SetStringWithoutPathExpansion(
842 shill::kL2tpIpsecUserProperty
, user_name
);
844 if (!user_passphrase
.empty()) {
845 properties
->SetStringWithoutPathExpansion(
846 shill::kL2tpIpsecPasswordProperty
, user_passphrase
);
850 case PROVIDER_TYPE_INDEX_OPEN_VPN
: {
851 std::string ca_cert_pem
= GetServerCACertPEM();
852 if (!ca_cert_pem
.empty()) {
853 base::ListValue
* pem_list
= new base::ListValue
;
854 pem_list
->AppendString(ca_cert_pem
);
855 properties
->SetWithoutPathExpansion(
856 shill::kOpenVPNCaCertPemProperty
, pem_list
);
858 properties
->SetStringWithoutPathExpansion(
859 shill::kOpenVPNClientCertIdProperty
, GetUserCertID());
860 properties
->SetStringWithoutPathExpansion(
861 shill::kOpenVPNUserProperty
, GetUsername());
862 if (!user_passphrase
.empty()) {
863 properties
->SetStringWithoutPathExpansion(
864 shill::kOpenVPNPasswordProperty
, user_passphrase
);
866 std::string otp
= GetOTP();
868 properties
->SetStringWithoutPathExpansion(
869 shill::kOpenVPNOTPProperty
, otp
);
873 case PROVIDER_TYPE_INDEX_MAX
:
877 properties
->SetBooleanWithoutPathExpansion(
878 shill::kSaveCredentialsProperty
, GetSaveCredentials());
881 void VPNConfigView::Refresh() {
884 // Set certificate combo boxes.
885 if (server_ca_cert_combobox_
) {
886 server_ca_cert_combobox_
->ModelChanged();
887 if (enable_server_ca_cert_
&& !ca_cert_pem_
.empty()) {
888 // Select the current server CA certificate in the combobox.
889 int cert_index
= CertLibrary::Get()->GetCertIndexByPEM(
890 CertLibrary::CERT_TYPE_SERVER_CA
, ca_cert_pem_
);
891 if (cert_index
>= 0) {
892 // Skip item for "Default"
893 server_ca_cert_combobox_
->SetSelectedIndex(1 + cert_index
);
895 server_ca_cert_combobox_
->SetSelectedIndex(0);
898 server_ca_cert_combobox_
->SetSelectedIndex(0);
902 if (user_cert_combobox_
) {
903 user_cert_combobox_
->ModelChanged();
904 if (enable_user_cert_
&& !client_cert_id_
.empty()) {
905 int cert_index
= CertLibrary::Get()->GetCertIndexByPkcs11Id(
906 CertLibrary::CERT_TYPE_USER
, client_cert_id_
);
908 user_cert_combobox_
->SetSelectedIndex(cert_index
);
910 user_cert_combobox_
->SetSelectedIndex(0);
912 user_cert_combobox_
->SetSelectedIndex(0);
919 void VPNConfigView::UpdateControlsToEnable() {
920 enable_psk_passphrase_
= false;
921 enable_user_cert_
= false;
922 enable_server_ca_cert_
= false;
924 enable_group_name_
= false;
925 int provider_type_index
= GetProviderTypeIndex();
926 if (provider_type_index
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
) {
927 enable_psk_passphrase_
= true;
928 enable_group_name_
= true;
929 } else if (provider_type_index
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
) {
930 enable_server_ca_cert_
= true;
931 enable_user_cert_
= HaveUserCerts();
932 enable_group_name_
= true;
933 } else { // PROVIDER_TYPE_INDEX_OPEN_VPN (default)
934 enable_server_ca_cert_
= true;
935 enable_user_cert_
= HaveUserCerts();
940 void VPNConfigView::UpdateControls() {
941 UpdateControlsToEnable();
943 if (psk_passphrase_label_
)
944 psk_passphrase_label_
->SetEnabled(enable_psk_passphrase_
);
945 if (psk_passphrase_textfield_
)
946 psk_passphrase_textfield_
->SetEnabled(enable_psk_passphrase_
&&
947 psk_passphrase_ui_data_
.IsEditable());
949 if (user_cert_label_
)
950 user_cert_label_
->SetEnabled(enable_user_cert_
);
951 if (user_cert_combobox_
)
952 user_cert_combobox_
->SetEnabled(enable_user_cert_
&&
953 user_cert_ui_data_
.IsEditable());
955 if (server_ca_cert_label_
)
956 server_ca_cert_label_
->SetEnabled(enable_server_ca_cert_
);
957 if (server_ca_cert_combobox_
)
958 server_ca_cert_combobox_
->SetEnabled(enable_server_ca_cert_
&&
959 ca_cert_ui_data_
.IsEditable());
962 otp_label_
->SetEnabled(enable_otp_
);
964 otp_textfield_
->SetEnabled(enable_otp_
);
966 if (group_name_label_
)
967 group_name_label_
->SetEnabled(enable_group_name_
);
968 if (group_name_textfield_
)
969 group_name_textfield_
->SetEnabled(enable_group_name_
&&
970 group_name_ui_data_
.IsEditable());
973 void VPNConfigView::UpdateErrorLabel() {
975 base::string16 error_msg
;
977 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
978 if (cert_required
&& CertLibrary::Get()->CertificatesLoaded()) {
979 if (!HaveUserCerts()) {
980 error_msg
= l10n_util::GetStringUTF16(
981 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT
);
982 } else if (!IsUserCertValid()) {
983 error_msg
= l10n_util::GetStringUTF16(
984 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED
);
987 if (error_msg
.empty() && !service_path_
.empty()) {
988 // TODO(kuan): differentiate between bad psk and user passphrases.
989 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
990 GetNetworkState(service_path_
);
991 if (vpn
&& vpn
->connection_state() == shill::kStateFailure
)
992 error_msg
= ash::network_connect::ErrorString(
993 vpn
->last_error(), vpn
->path());
995 if (!error_msg
.empty()) {
996 error_label_
->SetText(error_msg
);
997 error_label_
->SetVisible(true);
999 error_label_
->SetVisible(false);
1003 void VPNConfigView::UpdateCanLogin() {
1004 parent_
->GetDialogClientView()->UpdateDialogButtons();
1007 bool VPNConfigView::HaveUserCerts() const {
1008 return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
) > 0;
1011 bool VPNConfigView::IsUserCertValid() const {
1012 if (!user_cert_combobox_
|| !enable_user_cert_
)
1014 int index
= user_cert_combobox_
->selected_index();
1017 // Currently only hardware-backed user certificates are valid.
1018 if (CertLibrary::Get()->IsHardwareBacked() &&
1019 !CertLibrary::Get()->IsCertHardwareBackedAt(
1020 CertLibrary::CERT_TYPE_USER
, index
))
1025 const std::string
VPNConfigView::GetTextFromField(views::Textfield
* textfield
,
1026 bool trim_whitespace
) const {
1028 return std::string();
1029 std::string untrimmed
= base::UTF16ToUTF8(textfield
->text());
1030 if (!trim_whitespace
)
1033 base::TrimWhitespaceASCII(untrimmed
, base::TRIM_ALL
, &result
);
1037 const std::string
VPNConfigView::GetPassphraseFromField(
1038 PassphraseTextfield
* textfield
) const {
1040 return std::string();
1041 return textfield
->GetPassphrase();
1044 void VPNConfigView::ParseVPNUIProperty(
1045 const NetworkState
* network
,
1046 const std::string
& dict_key
,
1047 const std::string
& key
,
1048 NetworkPropertyUIData
* property_ui_data
) {
1049 ::onc::ONCSource onc_source
= ::onc::ONC_SOURCE_NONE
;
1050 const base::DictionaryValue
* onc
=
1051 onc::FindPolicyForActiveUser(network
->guid(), &onc_source
);
1053 VLOG_IF(1, !onc
) << "No ONC found for VPN network " << network
->guid();
1054 property_ui_data
->ParseOncProperty(
1057 base::StringPrintf("%s.%s.%s",
1058 ::onc::network_config::kVPN
,
1063 } // namespace chromeos