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"
8 #include "base/strings/string_util.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chromeos/enrollment_dialog_view.h"
12 #include "chrome/browser/chromeos/net/onc_utils.h"
13 #include "chrome/browser/profiles/profile_manager.h"
14 #include "chrome/common/net/x509_certificate_model.h"
15 #include "chrome/grit/generated_resources.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 "third_party/cros_system_api/dbus/service_constants.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/base/models/combobox_model.h"
26 #include "ui/chromeos/network/network_connect.h"
27 #include "ui/events/event.h"
28 #include "ui/views/controls/button/checkbox.h"
29 #include "ui/views/controls/combobox/combobox.h"
30 #include "ui/views/controls/label.h"
31 #include "ui/views/controls/textfield/textfield.h"
32 #include "ui/views/layout/grid_layout.h"
33 #include "ui/views/layout/layout_constants.h"
34 #include "ui/views/widget/widget.h"
35 #include "ui/views/window/dialog_client_view.h"
39 enum ProviderTypeIndex
{
40 PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
= 0,
41 PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
= 1,
42 PROVIDER_TYPE_INDEX_OPEN_VPN
= 2,
43 PROVIDER_TYPE_INDEX_MAX
= 3,
46 base::string16
ProviderTypeIndexToString(int index
) {
48 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
49 return l10n_util::GetStringUTF16(
50 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_PSK
);
51 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
52 return l10n_util::GetStringUTF16(
53 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_L2TP_IPSEC_USER_CERT
);
54 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
55 return l10n_util::GetStringUTF16(
56 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_OPEN_VPN
);
59 return base::string16();
62 int ProviderTypeToIndex(const std::string
& provider_type
,
63 const std::string
& client_cert_id
) {
64 if (provider_type
== shill::kProviderL2tpIpsec
) {
65 if (!client_cert_id
.empty())
66 return PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
68 return PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
;
70 DCHECK(provider_type
== shill::kProviderOpenVpn
);
71 return PROVIDER_TYPE_INDEX_OPEN_VPN
;
75 // Translates the provider type to the name of the respective ONC dictionary
76 // containing configuration data for the type.
77 std::string
ProviderTypeIndexToONCDictKey(int provider_type_index
) {
78 switch (provider_type_index
) {
79 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
80 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
81 return onc::vpn::kIPsec
;
82 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
83 return onc::vpn::kOpenVPN
;
85 NOTREACHED() << "Unhandled provider type index " << provider_type_index
;
89 std::string
GetPemFromDictionary(
90 const base::DictionaryValue
* provider_properties
,
91 const std::string
& key
) {
92 const base::ListValue
* pems
= NULL
;
93 if (!provider_properties
->GetListWithoutPathExpansion(key
, &pems
))
96 pems
->GetString(0, &pem
);
106 class ProviderTypeComboboxModel
: public ui::ComboboxModel
{
108 ProviderTypeComboboxModel();
109 ~ProviderTypeComboboxModel() override
;
111 // Overridden from ui::ComboboxModel:
112 int GetItemCount() const override
;
113 base::string16
GetItemAt(int index
) override
;
116 DISALLOW_COPY_AND_ASSIGN(ProviderTypeComboboxModel
);
119 class VpnServerCACertComboboxModel
: public ui::ComboboxModel
{
121 VpnServerCACertComboboxModel();
122 ~VpnServerCACertComboboxModel() override
;
124 // Overridden from ui::ComboboxModel:
125 int GetItemCount() const override
;
126 base::string16
GetItemAt(int index
) override
;
129 DISALLOW_COPY_AND_ASSIGN(VpnServerCACertComboboxModel
);
132 class VpnUserCertComboboxModel
: public ui::ComboboxModel
{
134 VpnUserCertComboboxModel();
135 ~VpnUserCertComboboxModel() override
;
137 // Overridden from ui::ComboboxModel:
138 int GetItemCount() const override
;
139 base::string16
GetItemAt(int index
) override
;
142 DISALLOW_COPY_AND_ASSIGN(VpnUserCertComboboxModel
);
145 // ProviderTypeComboboxModel ---------------------------------------------------
147 ProviderTypeComboboxModel::ProviderTypeComboboxModel() {
150 ProviderTypeComboboxModel::~ProviderTypeComboboxModel() {
153 int ProviderTypeComboboxModel::GetItemCount() const {
154 return PROVIDER_TYPE_INDEX_MAX
;
157 base::string16
ProviderTypeComboboxModel::GetItemAt(int index
) {
158 return ProviderTypeIndexToString(index
);
161 // VpnServerCACertComboboxModel ------------------------------------------------
163 VpnServerCACertComboboxModel::VpnServerCACertComboboxModel() {
166 VpnServerCACertComboboxModel::~VpnServerCACertComboboxModel() {
169 int VpnServerCACertComboboxModel::GetItemCount() const {
170 if (CertLibrary::Get()->CertificatesLoading())
171 return 1; // "Loading"
172 // "Default" + certs.
173 return CertLibrary::Get()->NumCertificates(
174 CertLibrary::CERT_TYPE_SERVER_CA
) + 1;
177 base::string16
VpnServerCACertComboboxModel::GetItemAt(int index
) {
178 if (CertLibrary::Get()->CertificatesLoading())
179 return l10n_util::GetStringUTF16(
180 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING
);
182 return l10n_util::GetStringUTF16(
183 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA_DEFAULT
);
184 int cert_index
= index
- 1;
185 return CertLibrary::Get()->GetCertDisplayStringAt(
186 CertLibrary::CERT_TYPE_SERVER_CA
, cert_index
);
189 // VpnUserCertComboboxModel ----------------------------------------------------
191 VpnUserCertComboboxModel::VpnUserCertComboboxModel() {
194 VpnUserCertComboboxModel::~VpnUserCertComboboxModel() {
197 int VpnUserCertComboboxModel::GetItemCount() const {
198 if (CertLibrary::Get()->CertificatesLoading())
199 return 1; // "Loading"
201 CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
);
203 return 1; // "None installed"
207 base::string16
VpnUserCertComboboxModel::GetItemAt(int index
) {
208 if (CertLibrary::Get()->CertificatesLoading()) {
209 return l10n_util::GetStringUTF16(
210 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_LOADING
);
212 if (CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
) == 0) {
213 return l10n_util::GetStringUTF16(
214 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_USER_CERT_NONE_INSTALLED
);
216 return CertLibrary::Get()->GetCertDisplayStringAt(
217 CertLibrary::CERT_TYPE_USER
, index
);
220 } // namespace internal
222 VPNConfigView::VPNConfigView(NetworkConfigView
* parent
,
223 const std::string
& service_path
)
224 : ChildNetworkConfigView(parent
, service_path
),
225 service_text_modified_(false),
226 enable_psk_passphrase_(false),
227 enable_user_cert_(false),
228 enable_server_ca_cert_(false),
230 enable_group_name_(false),
233 server_textfield_(NULL
),
235 service_textfield_(NULL
),
236 provider_type_combobox_(NULL
),
237 provider_type_text_label_(NULL
),
238 psk_passphrase_label_(NULL
),
239 psk_passphrase_textfield_(NULL
),
240 user_cert_label_(NULL
),
241 user_cert_combobox_(NULL
),
242 server_ca_cert_label_(NULL
),
243 server_ca_cert_combobox_(NULL
),
244 username_textfield_(NULL
),
245 user_passphrase_textfield_(NULL
),
247 otp_textfield_(NULL
),
248 group_name_label_(NULL
),
249 group_name_textfield_(NULL
),
250 save_credentials_checkbox_(NULL
),
252 provider_type_index_(PROVIDER_TYPE_INDEX_MAX
),
253 weak_ptr_factory_(this) {
257 VPNConfigView::~VPNConfigView() {
258 RemoveAllChildViews(true); // Destroy children before models
259 CertLibrary::Get()->RemoveObserver(this);
262 base::string16
VPNConfigView::GetTitle() const {
263 DCHECK_NE(title_
, 0);
264 return l10n_util::GetStringUTF16(title_
);
267 views::View
* VPNConfigView::GetInitiallyFocusedView() {
268 if (service_path_
.empty()) {
269 // Put focus in the first editable field.
270 if (server_textfield_
)
271 return server_textfield_
;
272 else if (service_textfield_
)
273 return service_textfield_
;
274 else if (provider_type_combobox_
)
275 return provider_type_combobox_
;
276 else if (psk_passphrase_textfield_
&& psk_passphrase_textfield_
->enabled())
277 return psk_passphrase_textfield_
;
278 else if (user_cert_combobox_
&& user_cert_combobox_
->enabled())
279 return user_cert_combobox_
;
280 else if (server_ca_cert_combobox_
&& server_ca_cert_combobox_
->enabled())
281 return server_ca_cert_combobox_
;
283 if (user_passphrase_textfield_
)
284 return user_passphrase_textfield_
;
285 else if (otp_textfield_
)
286 return otp_textfield_
;
290 bool VPNConfigView::CanLogin() {
291 // Username is always required.
292 if (GetUsername().empty())
295 // TODO(stevenjb): min kMinPassphraseLen length?
296 if (service_path_
.empty() &&
297 (GetService().empty() || GetServer().empty()))
300 // Block login if certs are required but user has none.
302 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
303 if (cert_required
&& (!HaveUserCerts() || !IsUserCertValid()))
309 void VPNConfigView::ContentsChanged(views::Textfield
* sender
,
310 const base::string16
& new_contents
) {
311 if (sender
== server_textfield_
&& !service_text_modified_
) {
312 // Set the service name to the server name up to '.', unless it has
313 // been explicitly set by the user.
314 base::string16 server
= server_textfield_
->text();
315 base::string16::size_type n
= server
.find_first_of(L
'.');
316 service_name_from_server_
= server
.substr(0, n
);
317 service_textfield_
->SetText(service_name_from_server_
);
319 if (sender
== service_textfield_
) {
320 if (new_contents
.empty())
321 service_text_modified_
= false;
322 else if (new_contents
!= service_name_from_server_
)
323 service_text_modified_
= true;
328 bool VPNConfigView::HandleKeyEvent(views::Textfield
* sender
,
329 const ui::KeyEvent
& key_event
) {
330 if ((sender
== psk_passphrase_textfield_
||
331 sender
== user_passphrase_textfield_
) &&
332 key_event
.key_code() == ui::VKEY_RETURN
) {
333 parent_
->GetDialogClientView()->AcceptWindow();
338 void VPNConfigView::ButtonPressed(views::Button
* sender
,
339 const ui::Event
& event
) {
342 void VPNConfigView::OnPerformAction(views::Combobox
* combobox
) {
348 void VPNConfigView::OnCertificatesLoaded(bool initial_load
) {
352 bool VPNConfigView::Login() {
353 if (service_path_
.empty()) {
354 base::DictionaryValue properties
;
355 // Identifying properties
356 properties
.SetStringWithoutPathExpansion(
357 shill::kTypeProperty
, shill::kTypeVPN
);
358 properties
.SetStringWithoutPathExpansion(
359 shill::kNameProperty
, GetService());
360 properties
.SetStringWithoutPathExpansion(
361 shill::kProviderHostProperty
, GetServer());
362 properties
.SetStringWithoutPathExpansion(
363 shill::kProviderTypeProperty
, GetProviderTypeString());
365 SetConfigProperties(&properties
);
367 bool modifiable
= false;
368 ChildNetworkConfigView::GetShareStateForLoginState(&shared
, &modifiable
);
370 bool only_policy_autoconnect
=
371 onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!shared
);
372 if (only_policy_autoconnect
) {
373 properties
.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty
,
377 ui::NetworkConnect::Get()->CreateConfigurationAndConnect(&properties
,
380 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
381 GetNetworkState(service_path_
);
383 // Shill no longer knows about this network (edge case).
384 // TODO(stevenjb): Add notification for this.
385 NET_LOG_ERROR("Network not found", service_path_
);
386 return true; // Close dialog
388 base::DictionaryValue properties
;
389 SetConfigProperties(&properties
);
390 ui::NetworkConnect::Get()->ConfigureNetworkAndConnect(
391 service_path_
, properties
, false /* not shared */);
393 return true; // Close dialog.
396 void VPNConfigView::Cancel() {
399 void VPNConfigView::InitFocus() {
400 views::View
* view_to_focus
= GetInitiallyFocusedView();
402 view_to_focus
->RequestFocus();
405 const std::string
VPNConfigView::GetService() const {
406 if (service_textfield_
!= NULL
)
407 return GetTextFromField(service_textfield_
, true);
408 return service_path_
;
411 const std::string
VPNConfigView::GetServer() const {
412 if (server_textfield_
!= NULL
)
413 return GetTextFromField(server_textfield_
, true);
414 return std::string();
417 const std::string
VPNConfigView::GetPSKPassphrase() const {
418 if (psk_passphrase_textfield_
&&
419 enable_psk_passphrase_
&&
420 psk_passphrase_textfield_
->visible())
421 return GetPassphraseFromField(psk_passphrase_textfield_
);
422 return std::string();
425 const std::string
VPNConfigView::GetUsername() const {
426 return GetTextFromField(username_textfield_
, true);
429 const std::string
VPNConfigView::GetUserPassphrase() const {
430 return GetPassphraseFromField(user_passphrase_textfield_
);
433 const std::string
VPNConfigView::GetGroupName() const {
434 return GetTextFromField(group_name_textfield_
, false);
437 const std::string
VPNConfigView::GetOTP() const {
438 return GetTextFromField(otp_textfield_
, true);
441 const std::string
VPNConfigView::GetServerCACertPEM() const {
442 int index
= server_ca_cert_combobox_
?
443 server_ca_cert_combobox_
->selected_index() : 0;
445 // First item is "Default".
446 return std::string();
448 int cert_index
= index
- 1;
449 return CertLibrary::Get()->GetServerCACertPEMAt(cert_index
);
453 void VPNConfigView::SetUserCertProperties(
454 chromeos::client_cert::ConfigType client_cert_type
,
455 base::DictionaryValue
* properties
) const {
456 if (!HaveUserCerts()) {
457 // No certificate selected or not required.
458 chromeos::client_cert::SetEmptyShillProperties(client_cert_type
,
461 // Certificates are listed in the order they appear in the model.
462 int index
= user_cert_combobox_
? user_cert_combobox_
->selected_index() : 0;
464 const std::string pkcs11_id
=
465 CertLibrary::Get()->GetUserCertPkcs11IdAt(index
, &slot_id
);
466 chromeos::client_cert::SetShillProperties(
467 client_cert_type
, slot_id
, pkcs11_id
, properties
);
471 bool VPNConfigView::GetSaveCredentials() const {
472 return save_credentials_checkbox_
->checked();
475 int VPNConfigView::GetProviderTypeIndex() const {
476 if (provider_type_combobox_
)
477 return provider_type_combobox_
->selected_index();
478 return provider_type_index_
;
481 std::string
VPNConfigView::GetProviderTypeString() const {
482 int index
= GetProviderTypeIndex();
484 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
485 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
486 return shill::kProviderL2tpIpsec
;
487 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
488 return shill::kProviderOpenVpn
;
491 return std::string();
494 void VPNConfigView::Init() {
495 const NetworkState
* vpn
= NULL
;
496 if (!service_path_
.empty()) {
497 vpn
= NetworkHandler::Get()->network_state_handler()->
498 GetNetworkState(service_path_
);
499 DCHECK(vpn
&& vpn
->type() == shill::kTypeVPN
);
501 layout_
= views::GridLayout::CreatePanel(this);
502 SetLayoutManager(layout_
);
504 // Observer any changes to the certificate list.
505 CertLibrary::Get()->AddObserver(this);
507 views::ColumnSet
* column_set
= layout_
->AddColumnSet(0);
509 column_set
->AddColumn(views::GridLayout::LEADING
, views::GridLayout::FILL
, 1,
510 views::GridLayout::USE_PREF
, 0, 0);
511 column_set
->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing
);
512 // Textfield, combobox.
513 column_set
->AddColumn(views::GridLayout::FILL
, views::GridLayout::FILL
, 1,
514 views::GridLayout::USE_PREF
, 0,
515 ChildNetworkConfigView::kInputFieldMinWidth
);
516 column_set
->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing
);
518 column_set
->AddColumn(views::GridLayout::CENTER
, views::GridLayout::CENTER
, 0,
519 views::GridLayout::USE_PREF
, 0, 0);
521 // Initialize members.
522 service_text_modified_
= false;
523 title_
= vpn
? IDS_OPTIONS_SETTINGS_JOIN_VPN
: IDS_OPTIONS_SETTINGS_ADD_VPN
;
525 // By default enable all controls.
526 enable_psk_passphrase_
= true;
527 enable_user_cert_
= true;
528 enable_server_ca_cert_
= true;
530 enable_group_name_
= true;
532 // Server label and input.
533 layout_
->StartRow(0, 0);
534 views::View
* server_label
=
535 new views::Label(l10n_util::GetStringUTF16(
536 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME
));
537 layout_
->AddView(server_label
);
538 server_textfield_
= new views::Textfield();
539 server_textfield_
->set_controller(this);
540 layout_
->AddView(server_textfield_
);
541 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
542 if (!service_path_
.empty()) {
543 server_label
->SetEnabled(false);
544 server_textfield_
->SetEnabled(false);
547 // Service label and name or input.
548 layout_
->StartRow(0, 0);
549 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
550 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME
)));
551 if (service_path_
.empty()) {
552 service_textfield_
= new views::Textfield();
553 service_textfield_
->set_controller(this);
554 layout_
->AddView(service_textfield_
);
555 service_text_
= NULL
;
557 service_text_
= new views::Label();
558 service_text_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
559 layout_
->AddView(service_text_
);
560 service_textfield_
= NULL
;
562 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
564 // Provider type label and select.
565 layout_
->StartRow(0, 0);
566 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
567 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE
)));
568 if (service_path_
.empty()) {
569 provider_type_combobox_model_
.reset(
570 new internal::ProviderTypeComboboxModel
);
571 provider_type_combobox_
= new views::Combobox(
572 provider_type_combobox_model_
.get());
573 provider_type_combobox_
->set_listener(this);
574 layout_
->AddView(provider_type_combobox_
);
575 provider_type_text_label_
= NULL
;
577 provider_type_text_label_
= new views::Label();
578 provider_type_text_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
579 layout_
->AddView(provider_type_text_label_
);
580 provider_type_combobox_
= NULL
;
582 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
584 // PSK passphrase label, input and visible button.
585 layout_
->StartRow(0, 0);
586 psk_passphrase_label_
= new views::Label(l10n_util::GetStringUTF16(
587 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE
));
588 layout_
->AddView(psk_passphrase_label_
);
589 psk_passphrase_textfield_
= new PassphraseTextfield();
590 psk_passphrase_textfield_
->set_controller(this);
591 layout_
->AddView(psk_passphrase_textfield_
);
593 new ControlledSettingIndicatorView(psk_passphrase_ui_data_
));
594 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
596 // Server CA certificate
597 if (service_path_
.empty()) {
598 layout_
->StartRow(0, 0);
599 server_ca_cert_label_
= new views::Label(l10n_util::GetStringUTF16(
600 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA
));
601 layout_
->AddView(server_ca_cert_label_
);
602 server_ca_cert_combobox_model_
.reset(
603 new internal::VpnServerCACertComboboxModel());
604 server_ca_cert_combobox_
= new views::Combobox(
605 server_ca_cert_combobox_model_
.get());
606 layout_
->AddView(server_ca_cert_combobox_
);
607 layout_
->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_
));
608 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
610 server_ca_cert_label_
= NULL
;
611 server_ca_cert_combobox_
= NULL
;
614 // User certificate label and input.
615 layout_
->StartRow(0, 0);
616 user_cert_label_
= new views::Label(l10n_util::GetStringUTF16(
617 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT
));
618 layout_
->AddView(user_cert_label_
);
619 user_cert_combobox_model_
.reset(
620 new internal::VpnUserCertComboboxModel());
621 user_cert_combobox_
= new views::Combobox(user_cert_combobox_model_
.get());
622 user_cert_combobox_
->set_listener(this);
623 layout_
->AddView(user_cert_combobox_
);
624 layout_
->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_
));
625 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
627 // Username label and input.
628 layout_
->StartRow(0, 0);
629 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
630 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME
)));
631 username_textfield_
= new views::Textfield();
632 username_textfield_
->set_controller(this);
633 username_textfield_
->SetEnabled(username_ui_data_
.IsEditable());
634 layout_
->AddView(username_textfield_
);
635 layout_
->AddView(new ControlledSettingIndicatorView(username_ui_data_
));
636 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
638 // User passphrase label, input and visble button.
639 layout_
->StartRow(0, 0);
640 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
641 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE
)));
642 user_passphrase_textfield_
= new PassphraseTextfield();
643 user_passphrase_textfield_
->set_controller(this);
644 user_passphrase_textfield_
->SetEnabled(user_passphrase_ui_data_
.IsEditable());
645 layout_
->AddView(user_passphrase_textfield_
);
647 new ControlledSettingIndicatorView(user_passphrase_ui_data_
));
648 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
650 // OTP label and input.
651 layout_
->StartRow(0, 0);
652 otp_label_
= new views::Label(l10n_util::GetStringUTF16(
653 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP
));
654 layout_
->AddView(otp_label_
);
655 otp_textfield_
= new views::Textfield();
656 otp_textfield_
->set_controller(this);
657 layout_
->AddView(otp_textfield_
);
658 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
660 // Group Name label and input.
661 layout_
->StartRow(0, 0);
662 group_name_label_
= new views::Label(l10n_util::GetStringUTF16(
663 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME
));
664 layout_
->AddView(group_name_label_
);
665 group_name_textfield_
=
666 new views::Textfield();
667 group_name_textfield_
->set_controller(this);
668 layout_
->AddView(group_name_textfield_
);
669 layout_
->AddView(new ControlledSettingIndicatorView(group_name_ui_data_
));
670 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
673 layout_
->StartRow(0, 0);
674 save_credentials_checkbox_
= new views::Checkbox(
675 l10n_util::GetStringUTF16(
676 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS
));
677 save_credentials_checkbox_
->SetEnabled(
678 save_credentials_ui_data_
.IsEditable());
679 layout_
->SkipColumns(1);
680 layout_
->AddView(save_credentials_checkbox_
);
682 new ControlledSettingIndicatorView(save_credentials_ui_data_
));
685 layout_
->StartRow(0, 0);
686 layout_
->SkipColumns(1);
687 error_label_
= new views::Label();
688 error_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
689 error_label_
->SetEnabledColor(SK_ColorRED
);
690 layout_
->AddView(error_label_
);
692 // Set or hide the UI, update comboboxes and error labels.
696 NetworkHandler::Get()->network_configuration_handler()->GetShillProperties(
697 service_path_
, base::Bind(&VPNConfigView::InitFromProperties
,
698 weak_ptr_factory_
.GetWeakPtr()),
699 base::Bind(&VPNConfigView::GetPropertiesError
,
700 weak_ptr_factory_
.GetWeakPtr()));
704 void VPNConfigView::InitFromProperties(
705 const std::string
& service_path
,
706 const base::DictionaryValue
& service_properties
) {
707 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
708 GetNetworkState(service_path
);
710 NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path
);
714 std::string provider_type
, server_hostname
, username
, group_name
;
715 bool psk_passphrase_required
= false;
716 bool user_passphrase_required
= true;
717 const base::DictionaryValue
* provider_properties
;
718 if (service_properties
.GetDictionaryWithoutPathExpansion(
719 shill::kProviderProperty
, &provider_properties
)) {
720 provider_properties
->GetStringWithoutPathExpansion(
721 shill::kTypeProperty
, &provider_type
);
722 provider_properties
->GetStringWithoutPathExpansion(
723 shill::kHostProperty
, &server_hostname
);
724 if (provider_type
== shill::kProviderL2tpIpsec
) {
725 provider_properties
->GetStringWithoutPathExpansion(
726 shill::kL2tpIpsecClientCertIdProperty
, &client_cert_id_
);
727 ca_cert_pem_
= GetPemFromDictionary(
728 provider_properties
, shill::kL2tpIpsecCaCertPemProperty
);
729 provider_properties
->GetBooleanWithoutPathExpansion(
730 shill::kL2tpIpsecPskRequiredProperty
, &psk_passphrase_required
);
731 provider_properties
->GetStringWithoutPathExpansion(
732 shill::kL2tpIpsecUserProperty
, &username
);
733 provider_properties
->GetStringWithoutPathExpansion(
734 shill::kL2tpIpsecTunnelGroupProperty
, &group_name
);
735 } else if (provider_type
== shill::kProviderOpenVpn
) {
736 provider_properties
->GetStringWithoutPathExpansion(
737 shill::kOpenVPNClientCertIdProperty
, &client_cert_id_
);
738 ca_cert_pem_
= GetPemFromDictionary(
739 provider_properties
, shill::kOpenVPNCaCertPemProperty
);
740 provider_properties
->GetStringWithoutPathExpansion(
741 shill::kOpenVPNUserProperty
, &username
);
742 provider_properties
->GetBooleanWithoutPathExpansion(
743 shill::kPassphraseRequiredProperty
, &user_passphrase_required
);
746 bool save_credentials
= false;
747 service_properties
.GetBooleanWithoutPathExpansion(
748 shill::kSaveCredentialsProperty
, &save_credentials
);
750 provider_type_index_
= ProviderTypeToIndex(provider_type
, client_cert_id_
);
753 service_text_
->SetText(base::ASCIIToUTF16(vpn
->name()));
754 if (provider_type_text_label_
)
755 provider_type_text_label_
->SetText(
756 ProviderTypeIndexToString(provider_type_index_
));
758 if (server_textfield_
&& !server_hostname
.empty())
759 server_textfield_
->SetText(base::UTF8ToUTF16(server_hostname
));
760 if (username_textfield_
&& !username
.empty())
761 username_textfield_
->SetText(base::UTF8ToUTF16(username
));
762 if (group_name_textfield_
&& !group_name
.empty())
763 group_name_textfield_
->SetText(base::UTF8ToUTF16(group_name
));
764 if (psk_passphrase_textfield_
)
765 psk_passphrase_textfield_
->SetShowFake(!psk_passphrase_required
);
766 if (user_passphrase_textfield_
)
767 user_passphrase_textfield_
->SetShowFake(!user_passphrase_required
);
768 if (save_credentials_checkbox_
)
769 save_credentials_checkbox_
->SetChecked(save_credentials
);
775 void VPNConfigView::ParseUIProperties(const NetworkState
* vpn
) {
776 std::string type_dict_name
=
777 ProviderTypeIndexToONCDictKey(provider_type_index_
);
778 if (provider_type_index_
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
) {
779 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kServerCARef
,
781 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kPSK
,
782 &psk_passphrase_ui_data_
);
783 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kGroup
,
784 &group_name_ui_data_
);
785 } else if (provider_type_index_
== PROVIDER_TYPE_INDEX_OPEN_VPN
) {
786 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::openvpn::kServerCARef
,
789 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::client_cert::kClientCertRef
,
790 &user_cert_ui_data_
);
792 const std::string
credentials_dict_name(
793 provider_type_index_
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
?
794 ::onc::vpn::kL2TP
: type_dict_name
);
795 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kUsername
,
797 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kPassword
,
798 &user_passphrase_ui_data_
);
799 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kSaveCredentials
,
800 &save_credentials_ui_data_
);
803 void VPNConfigView::GetPropertiesError(
804 const std::string
& error_name
,
805 scoped_ptr
<base::DictionaryValue
> error_data
) {
806 NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name
, "");
809 void VPNConfigView::SetConfigProperties(
810 base::DictionaryValue
* properties
) {
811 int provider_type_index
= GetProviderTypeIndex();
812 std::string user_passphrase
= GetUserPassphrase();
813 std::string user_name
= GetUsername();
814 std::string group_name
= GetGroupName();
815 switch (provider_type_index
) {
816 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
: {
817 std::string psk_passphrase
= GetPSKPassphrase();
818 if (!psk_passphrase
.empty()) {
819 properties
->SetStringWithoutPathExpansion(
820 shill::kL2tpIpsecPskProperty
, GetPSKPassphrase());
822 if (!group_name
.empty()) {
823 properties
->SetStringWithoutPathExpansion(
824 shill::kL2tpIpsecTunnelGroupProperty
, group_name
);
826 if (!user_name
.empty()) {
827 properties
->SetStringWithoutPathExpansion(
828 shill::kL2tpIpsecUserProperty
, user_name
);
830 if (!user_passphrase
.empty()) {
831 properties
->SetStringWithoutPathExpansion(
832 shill::kL2tpIpsecPasswordProperty
, user_passphrase
);
836 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
: {
837 if (server_ca_cert_combobox_
) {
838 std::string ca_cert_pem
= GetServerCACertPEM();
839 base::ListValue
* pem_list
= new base::ListValue
;
840 if (!ca_cert_pem
.empty())
841 pem_list
->AppendString(ca_cert_pem
);
842 properties
->SetWithoutPathExpansion(shill::kL2tpIpsecCaCertPemProperty
,
845 SetUserCertProperties(client_cert::CONFIG_TYPE_IPSEC
, properties
);
846 if (!group_name
.empty()) {
847 properties
->SetStringWithoutPathExpansion(
848 shill::kL2tpIpsecTunnelGroupProperty
, GetGroupName());
850 if (!user_name
.empty()) {
851 properties
->SetStringWithoutPathExpansion(
852 shill::kL2tpIpsecUserProperty
, user_name
);
854 if (!user_passphrase
.empty()) {
855 properties
->SetStringWithoutPathExpansion(
856 shill::kL2tpIpsecPasswordProperty
, user_passphrase
);
860 case PROVIDER_TYPE_INDEX_OPEN_VPN
: {
861 if (server_ca_cert_combobox_
) {
862 std::string ca_cert_pem
= GetServerCACertPEM();
863 base::ListValue
* pem_list
= new base::ListValue
;
864 if (!ca_cert_pem
.empty())
865 pem_list
->AppendString(ca_cert_pem
);
866 properties
->SetWithoutPathExpansion(shill::kOpenVPNCaCertPemProperty
,
869 SetUserCertProperties(client_cert::CONFIG_TYPE_OPENVPN
, properties
);
870 properties
->SetStringWithoutPathExpansion(
871 shill::kOpenVPNUserProperty
, GetUsername());
872 if (!user_passphrase
.empty()) {
873 properties
->SetStringWithoutPathExpansion(
874 shill::kOpenVPNPasswordProperty
, user_passphrase
);
876 std::string otp
= GetOTP();
878 properties
->SetStringWithoutPathExpansion(
879 shill::kOpenVPNOTPProperty
, otp
);
883 case PROVIDER_TYPE_INDEX_MAX
:
887 properties
->SetBooleanWithoutPathExpansion(
888 shill::kSaveCredentialsProperty
, GetSaveCredentials());
891 void VPNConfigView::Refresh() {
894 // Set certificate combo boxes.
895 if (server_ca_cert_combobox_
) {
896 server_ca_cert_combobox_
->ModelChanged();
897 if (enable_server_ca_cert_
&& !ca_cert_pem_
.empty()) {
898 // Select the current server CA certificate in the combobox.
900 CertLibrary::Get()->GetServerCACertIndexByPEM(ca_cert_pem_
);
901 if (cert_index
>= 0) {
902 // Skip item for "Default"
903 server_ca_cert_combobox_
->SetSelectedIndex(1 + cert_index
);
905 server_ca_cert_combobox_
->SetSelectedIndex(0);
908 server_ca_cert_combobox_
->SetSelectedIndex(0);
912 if (user_cert_combobox_
) {
913 user_cert_combobox_
->ModelChanged();
914 if (enable_user_cert_
&& !client_cert_id_
.empty()) {
916 CertLibrary::Get()->GetUserCertIndexByPkcs11Id(client_cert_id_
);
918 user_cert_combobox_
->SetSelectedIndex(cert_index
);
920 user_cert_combobox_
->SetSelectedIndex(0);
922 user_cert_combobox_
->SetSelectedIndex(0);
929 void VPNConfigView::UpdateControlsToEnable() {
930 enable_psk_passphrase_
= false;
931 enable_user_cert_
= false;
932 enable_server_ca_cert_
= false;
934 enable_group_name_
= false;
935 int provider_type_index
= GetProviderTypeIndex();
936 if (provider_type_index
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
) {
937 enable_psk_passphrase_
= true;
938 enable_group_name_
= true;
939 } else if (provider_type_index
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
) {
940 enable_server_ca_cert_
= true;
941 enable_user_cert_
= HaveUserCerts();
942 enable_group_name_
= true;
943 } else { // PROVIDER_TYPE_INDEX_OPEN_VPN (default)
944 enable_server_ca_cert_
= true;
945 enable_user_cert_
= HaveUserCerts();
950 void VPNConfigView::UpdateControls() {
951 UpdateControlsToEnable();
953 if (psk_passphrase_label_
)
954 psk_passphrase_label_
->SetEnabled(enable_psk_passphrase_
);
955 if (psk_passphrase_textfield_
)
956 psk_passphrase_textfield_
->SetEnabled(enable_psk_passphrase_
&&
957 psk_passphrase_ui_data_
.IsEditable());
959 if (user_cert_label_
)
960 user_cert_label_
->SetEnabled(enable_user_cert_
);
961 if (user_cert_combobox_
)
962 user_cert_combobox_
->SetEnabled(enable_user_cert_
&&
963 user_cert_ui_data_
.IsEditable());
965 if (server_ca_cert_label_
)
966 server_ca_cert_label_
->SetEnabled(enable_server_ca_cert_
);
967 if (server_ca_cert_combobox_
)
968 server_ca_cert_combobox_
->SetEnabled(enable_server_ca_cert_
&&
969 ca_cert_ui_data_
.IsEditable());
972 otp_label_
->SetEnabled(enable_otp_
);
974 otp_textfield_
->SetEnabled(enable_otp_
);
976 if (group_name_label_
)
977 group_name_label_
->SetEnabled(enable_group_name_
);
978 if (group_name_textfield_
)
979 group_name_textfield_
->SetEnabled(enable_group_name_
&&
980 group_name_ui_data_
.IsEditable());
983 void VPNConfigView::UpdateErrorLabel() {
985 base::string16 error_msg
;
987 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
988 if (cert_required
&& CertLibrary::Get()->CertificatesLoaded()) {
989 if (!HaveUserCerts()) {
990 error_msg
= l10n_util::GetStringUTF16(
991 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT
);
992 } else if (!IsUserCertValid()) {
993 error_msg
= l10n_util::GetStringUTF16(
994 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED
);
997 if (error_msg
.empty() && !service_path_
.empty()) {
998 // TODO(kuan): differentiate between bad psk and user passphrases.
999 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
1000 GetNetworkState(service_path_
);
1001 if (vpn
&& vpn
->connection_state() == shill::kStateFailure
)
1002 error_msg
= ui::NetworkConnect::Get()->GetShillErrorString(
1003 vpn
->last_error(), vpn
->path());
1005 if (!error_msg
.empty()) {
1006 error_label_
->SetText(error_msg
);
1007 error_label_
->SetVisible(true);
1009 error_label_
->SetVisible(false);
1013 void VPNConfigView::UpdateCanLogin() {
1014 parent_
->GetDialogClientView()->UpdateDialogButtons();
1017 bool VPNConfigView::HaveUserCerts() const {
1018 return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
) > 0;
1021 bool VPNConfigView::IsUserCertValid() const {
1022 if (!user_cert_combobox_
|| !enable_user_cert_
)
1024 int index
= user_cert_combobox_
->selected_index();
1027 // Currently only hardware-backed user certificates are valid.
1028 if (!CertLibrary::Get()->IsCertHardwareBackedAt(CertLibrary::CERT_TYPE_USER
,
1035 const std::string
VPNConfigView::GetTextFromField(views::Textfield
* textfield
,
1036 bool trim_whitespace
) const {
1038 return std::string();
1039 std::string untrimmed
= base::UTF16ToUTF8(textfield
->text());
1040 if (!trim_whitespace
)
1043 base::TrimWhitespaceASCII(untrimmed
, base::TRIM_ALL
, &result
);
1047 const std::string
VPNConfigView::GetPassphraseFromField(
1048 PassphraseTextfield
* textfield
) const {
1050 return std::string();
1051 return textfield
->GetPassphrase();
1054 void VPNConfigView::ParseVPNUIProperty(
1055 const NetworkState
* network
,
1056 const std::string
& dict_key
,
1057 const std::string
& key
,
1058 NetworkPropertyUIData
* property_ui_data
) {
1059 ::onc::ONCSource onc_source
= ::onc::ONC_SOURCE_NONE
;
1060 const base::DictionaryValue
* onc
=
1061 onc::FindPolicyForActiveUser(network
->guid(), &onc_source
);
1063 VLOG_IF(1, !onc
) << "No ONC found for VPN network " << network
->guid();
1064 property_ui_data
->ParseOncProperty(
1067 base::StringPrintf("%s.%s.%s",
1068 ::onc::network_config::kVPN
,
1073 } // namespace chromeos