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),
231 user_passphrase_required_(false),
234 server_textfield_(NULL
),
236 service_textfield_(NULL
),
237 provider_type_combobox_(NULL
),
238 provider_type_text_label_(NULL
),
239 psk_passphrase_label_(NULL
),
240 psk_passphrase_textfield_(NULL
),
241 user_cert_label_(NULL
),
242 user_cert_combobox_(NULL
),
243 server_ca_cert_label_(NULL
),
244 server_ca_cert_combobox_(NULL
),
245 username_textfield_(NULL
),
246 user_passphrase_textfield_(NULL
),
248 otp_textfield_(NULL
),
249 group_name_label_(NULL
),
250 group_name_textfield_(NULL
),
251 save_credentials_checkbox_(NULL
),
253 provider_type_index_(PROVIDER_TYPE_INDEX_MAX
),
254 weak_ptr_factory_(this) {
258 VPNConfigView::~VPNConfigView() {
259 RemoveAllChildViews(true); // Destroy children before models
260 CertLibrary::Get()->RemoveObserver(this);
263 base::string16
VPNConfigView::GetTitle() const {
264 DCHECK_NE(title_
, 0);
265 return l10n_util::GetStringUTF16(title_
);
268 views::View
* VPNConfigView::GetInitiallyFocusedView() {
269 if (service_path_
.empty()) {
270 // Put focus in the first editable field.
271 if (server_textfield_
)
272 return server_textfield_
;
273 else if (service_textfield_
)
274 return service_textfield_
;
275 else if (provider_type_combobox_
)
276 return provider_type_combobox_
;
277 else if (psk_passphrase_textfield_
&& psk_passphrase_textfield_
->enabled())
278 return psk_passphrase_textfield_
;
279 else if (user_cert_combobox_
&& user_cert_combobox_
->enabled())
280 return user_cert_combobox_
;
281 else if (server_ca_cert_combobox_
&& server_ca_cert_combobox_
->enabled())
282 return server_ca_cert_combobox_
;
284 if (user_passphrase_textfield_
&& user_passphrase_required_
)
285 return user_passphrase_textfield_
;
286 else if (otp_textfield_
)
287 return otp_textfield_
;
291 bool VPNConfigView::CanLogin() {
292 // Username is always required.
293 if (GetUsername().empty())
296 // TODO(stevenjb): min kMinPassphraseLen length?
297 if (service_path_
.empty() &&
298 (GetService().empty() || GetServer().empty()))
301 // Block login if certs are required but user has none.
303 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
304 if (cert_required
&& (!HaveUserCerts() || !IsUserCertValid()))
310 void VPNConfigView::ContentsChanged(views::Textfield
* sender
,
311 const base::string16
& new_contents
) {
312 if (sender
== server_textfield_
&& !service_text_modified_
) {
313 // Set the service name to the server name up to '.', unless it has
314 // been explicitly set by the user.
315 base::string16 server
= server_textfield_
->text();
316 base::string16::size_type n
= server
.find_first_of(L
'.');
317 service_name_from_server_
= server
.substr(0, n
);
318 service_textfield_
->SetText(service_name_from_server_
);
320 if (sender
== service_textfield_
) {
321 if (new_contents
.empty())
322 service_text_modified_
= false;
323 else if (new_contents
!= service_name_from_server_
)
324 service_text_modified_
= true;
329 bool VPNConfigView::HandleKeyEvent(views::Textfield
* sender
,
330 const ui::KeyEvent
& key_event
) {
331 if ((sender
== psk_passphrase_textfield_
||
332 sender
== user_passphrase_textfield_
) &&
333 key_event
.key_code() == ui::VKEY_RETURN
) {
334 parent_
->GetDialogClientView()->AcceptWindow();
339 void VPNConfigView::ButtonPressed(views::Button
* sender
,
340 const ui::Event
& event
) {
343 void VPNConfigView::OnPerformAction(views::Combobox
* combobox
) {
349 void VPNConfigView::OnCertificatesLoaded(bool initial_load
) {
353 bool VPNConfigView::Login() {
354 if (service_path_
.empty()) {
355 base::DictionaryValue properties
;
356 // Identifying properties
357 properties
.SetStringWithoutPathExpansion(
358 shill::kTypeProperty
, shill::kTypeVPN
);
359 properties
.SetStringWithoutPathExpansion(
360 shill::kNameProperty
, GetService());
361 properties
.SetStringWithoutPathExpansion(
362 shill::kProviderHostProperty
, GetServer());
363 properties
.SetStringWithoutPathExpansion(
364 shill::kProviderTypeProperty
, GetProviderTypeString());
366 SetConfigProperties(&properties
);
368 bool modifiable
= false;
369 ChildNetworkConfigView::GetShareStateForLoginState(&shared
, &modifiable
);
371 bool only_policy_autoconnect
=
372 onc::PolicyAllowsOnlyPolicyNetworksToAutoconnect(!shared
);
373 if (only_policy_autoconnect
) {
374 properties
.SetBooleanWithoutPathExpansion(shill::kAutoConnectProperty
,
378 ui::NetworkConnect::Get()->CreateConfigurationAndConnect(&properties
,
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 ui::NetworkConnect::Get()->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()->GetServerCACertPEMAt(cert_index
);
454 void VPNConfigView::SetUserCertProperties(
455 chromeos::client_cert::ConfigType client_cert_type
,
456 base::DictionaryValue
* properties
) const {
457 if (!HaveUserCerts()) {
458 // No certificate selected or not required.
459 chromeos::client_cert::SetEmptyShillProperties(client_cert_type
,
462 // Certificates are listed in the order they appear in the model.
463 int index
= user_cert_combobox_
? user_cert_combobox_
->selected_index() : 0;
465 const std::string pkcs11_id
=
466 CertLibrary::Get()->GetUserCertPkcs11IdAt(index
, &slot_id
);
467 chromeos::client_cert::SetShillProperties(
468 client_cert_type
, slot_id
, pkcs11_id
, properties
);
472 bool VPNConfigView::GetSaveCredentials() const {
473 return save_credentials_checkbox_
->checked();
476 int VPNConfigView::GetProviderTypeIndex() const {
477 if (provider_type_combobox_
)
478 return provider_type_combobox_
->selected_index();
479 return provider_type_index_
;
482 std::string
VPNConfigView::GetProviderTypeString() const {
483 int index
= GetProviderTypeIndex();
485 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
:
486 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
:
487 return shill::kProviderL2tpIpsec
;
488 case PROVIDER_TYPE_INDEX_OPEN_VPN
:
489 return shill::kProviderOpenVpn
;
492 return std::string();
495 void VPNConfigView::Init() {
496 const NetworkState
* vpn
= NULL
;
497 if (!service_path_
.empty()) {
498 vpn
= NetworkHandler::Get()->network_state_handler()->
499 GetNetworkState(service_path_
);
500 DCHECK(vpn
&& vpn
->type() == shill::kTypeVPN
);
502 layout_
= views::GridLayout::CreatePanel(this);
503 SetLayoutManager(layout_
);
505 // Observer any changes to the certificate list.
506 CertLibrary::Get()->AddObserver(this);
508 views::ColumnSet
* column_set
= layout_
->AddColumnSet(0);
510 column_set
->AddColumn(views::GridLayout::LEADING
, views::GridLayout::FILL
, 1,
511 views::GridLayout::USE_PREF
, 0, 0);
512 column_set
->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing
);
513 // Textfield, combobox.
514 column_set
->AddColumn(views::GridLayout::FILL
, views::GridLayout::FILL
, 1,
515 views::GridLayout::USE_PREF
, 0,
516 ChildNetworkConfigView::kInputFieldMinWidth
);
517 column_set
->AddPaddingColumn(0, views::kRelatedControlSmallHorizontalSpacing
);
519 column_set
->AddColumn(views::GridLayout::CENTER
, views::GridLayout::CENTER
, 0,
520 views::GridLayout::USE_PREF
, 0, 0);
522 // Initialize members.
523 service_text_modified_
= false;
524 title_
= vpn
? IDS_OPTIONS_SETTINGS_JOIN_VPN
: IDS_OPTIONS_SETTINGS_ADD_VPN
;
526 // By default enable all controls.
527 enable_psk_passphrase_
= true;
528 enable_user_cert_
= true;
529 enable_server_ca_cert_
= true;
531 enable_group_name_
= true;
533 // Server label and input.
534 layout_
->StartRow(0, 0);
535 views::View
* server_label
=
536 new views::Label(l10n_util::GetStringUTF16(
537 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVER_HOSTNAME
));
538 layout_
->AddView(server_label
);
539 server_textfield_
= new views::Textfield();
540 server_textfield_
->set_controller(this);
541 layout_
->AddView(server_textfield_
);
542 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
543 if (!service_path_
.empty()) {
544 server_label
->SetEnabled(false);
545 server_textfield_
->SetEnabled(false);
548 // Service label and name or input.
549 layout_
->StartRow(0, 0);
550 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
551 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_SERVICE_NAME
)));
552 if (service_path_
.empty()) {
553 service_textfield_
= new views::Textfield();
554 service_textfield_
->set_controller(this);
555 layout_
->AddView(service_textfield_
);
556 service_text_
= NULL
;
558 service_text_
= new views::Label();
559 service_text_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
560 layout_
->AddView(service_text_
);
561 service_textfield_
= NULL
;
563 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
565 // Provider type label and select.
566 layout_
->StartRow(0, 0);
567 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
568 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PROVIDER_TYPE
)));
569 if (service_path_
.empty()) {
570 provider_type_combobox_model_
.reset(
571 new internal::ProviderTypeComboboxModel
);
572 provider_type_combobox_
= new views::Combobox(
573 provider_type_combobox_model_
.get());
574 provider_type_combobox_
->set_listener(this);
575 layout_
->AddView(provider_type_combobox_
);
576 provider_type_text_label_
= NULL
;
578 provider_type_text_label_
= new views::Label();
579 provider_type_text_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
580 layout_
->AddView(provider_type_text_label_
);
581 provider_type_combobox_
= NULL
;
583 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
585 // PSK passphrase label, input and visible button.
586 layout_
->StartRow(0, 0);
587 psk_passphrase_label_
= new views::Label(l10n_util::GetStringUTF16(
588 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_PSK_PASSPHRASE
));
589 layout_
->AddView(psk_passphrase_label_
);
590 psk_passphrase_textfield_
= new PassphraseTextfield();
591 psk_passphrase_textfield_
->set_controller(this);
592 layout_
->AddView(psk_passphrase_textfield_
);
594 new ControlledSettingIndicatorView(psk_passphrase_ui_data_
));
595 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
597 // Server CA certificate
598 if (service_path_
.empty()) {
599 layout_
->StartRow(0, 0);
600 server_ca_cert_label_
= new views::Label(l10n_util::GetStringUTF16(
601 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_CERT_SERVER_CA
));
602 layout_
->AddView(server_ca_cert_label_
);
603 server_ca_cert_combobox_model_
.reset(
604 new internal::VpnServerCACertComboboxModel());
605 server_ca_cert_combobox_
= new views::Combobox(
606 server_ca_cert_combobox_model_
.get());
607 layout_
->AddView(server_ca_cert_combobox_
);
608 layout_
->AddView(new ControlledSettingIndicatorView(ca_cert_ui_data_
));
609 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
611 server_ca_cert_label_
= NULL
;
612 server_ca_cert_combobox_
= NULL
;
615 // User certificate label and input.
616 layout_
->StartRow(0, 0);
617 user_cert_label_
= new views::Label(l10n_util::GetStringUTF16(
618 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_CERT
));
619 layout_
->AddView(user_cert_label_
);
620 user_cert_combobox_model_
.reset(
621 new internal::VpnUserCertComboboxModel());
622 user_cert_combobox_
= new views::Combobox(user_cert_combobox_model_
.get());
623 user_cert_combobox_
->set_listener(this);
624 layout_
->AddView(user_cert_combobox_
);
625 layout_
->AddView(new ControlledSettingIndicatorView(user_cert_ui_data_
));
626 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
628 // Username label and input.
629 layout_
->StartRow(0, 0);
630 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
631 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USERNAME
)));
632 username_textfield_
= new views::Textfield();
633 username_textfield_
->set_controller(this);
634 username_textfield_
->SetEnabled(username_ui_data_
.IsEditable());
635 layout_
->AddView(username_textfield_
);
636 layout_
->AddView(new ControlledSettingIndicatorView(username_ui_data_
));
637 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
639 // User passphrase label, input and visble button.
640 layout_
->StartRow(0, 0);
641 layout_
->AddView(new views::Label(l10n_util::GetStringUTF16(
642 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_USER_PASSPHRASE
)));
643 user_passphrase_textfield_
= new PassphraseTextfield();
644 user_passphrase_textfield_
->set_controller(this);
645 user_passphrase_textfield_
->SetEnabled(user_passphrase_ui_data_
.IsEditable());
646 layout_
->AddView(user_passphrase_textfield_
);
648 new ControlledSettingIndicatorView(user_passphrase_ui_data_
));
649 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
651 // OTP label and input.
652 layout_
->StartRow(0, 0);
653 otp_label_
= new views::Label(l10n_util::GetStringUTF16(
654 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_OTP
));
655 layout_
->AddView(otp_label_
);
656 otp_textfield_
= new views::Textfield();
657 otp_textfield_
->set_controller(this);
658 layout_
->AddView(otp_textfield_
);
659 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
661 // Group Name label and input.
662 layout_
->StartRow(0, 0);
663 group_name_label_
= new views::Label(l10n_util::GetStringUTF16(
664 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_VPN_GROUP_NAME
));
665 layout_
->AddView(group_name_label_
);
666 group_name_textfield_
=
667 new views::Textfield();
668 group_name_textfield_
->set_controller(this);
669 layout_
->AddView(group_name_textfield_
);
670 layout_
->AddView(new ControlledSettingIndicatorView(group_name_ui_data_
));
671 layout_
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
674 layout_
->StartRow(0, 0);
675 save_credentials_checkbox_
= new views::Checkbox(
676 l10n_util::GetStringUTF16(
677 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_SAVE_CREDENTIALS
));
678 save_credentials_checkbox_
->SetEnabled(
679 save_credentials_ui_data_
.IsEditable());
680 layout_
->SkipColumns(1);
681 layout_
->AddView(save_credentials_checkbox_
);
683 new ControlledSettingIndicatorView(save_credentials_ui_data_
));
686 layout_
->StartRow(0, 0);
687 layout_
->SkipColumns(1);
688 error_label_
= new views::Label();
689 error_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
690 error_label_
->SetEnabledColor(SK_ColorRED
);
691 layout_
->AddView(error_label_
);
693 // Set or hide the UI, update comboboxes and error labels.
697 NetworkHandler::Get()->network_configuration_handler()->GetShillProperties(
698 service_path_
, base::Bind(&VPNConfigView::InitFromProperties
,
699 weak_ptr_factory_
.GetWeakPtr()),
700 base::Bind(&VPNConfigView::GetPropertiesError
,
701 weak_ptr_factory_
.GetWeakPtr()));
705 void VPNConfigView::InitFromProperties(
706 const std::string
& service_path
,
707 const base::DictionaryValue
& service_properties
) {
708 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
709 GetNetworkState(service_path
);
711 NET_LOG_ERROR("Shill Error getting properties VpnConfigView", service_path
);
715 std::string provider_type
, server_hostname
, username
, group_name
;
716 bool psk_passphrase_required
= false;
717 user_passphrase_required_
= true;
718 const base::DictionaryValue
* provider_properties
;
719 if (service_properties
.GetDictionaryWithoutPathExpansion(
720 shill::kProviderProperty
, &provider_properties
)) {
721 provider_properties
->GetStringWithoutPathExpansion(
722 shill::kTypeProperty
, &provider_type
);
723 provider_properties
->GetStringWithoutPathExpansion(
724 shill::kHostProperty
, &server_hostname
);
725 if (provider_type
== shill::kProviderL2tpIpsec
) {
726 provider_properties
->GetStringWithoutPathExpansion(
727 shill::kL2tpIpsecClientCertIdProperty
, &client_cert_id_
);
728 ca_cert_pem_
= GetPemFromDictionary(
729 provider_properties
, shill::kL2tpIpsecCaCertPemProperty
);
730 provider_properties
->GetBooleanWithoutPathExpansion(
731 shill::kL2tpIpsecPskRequiredProperty
, &psk_passphrase_required
);
732 provider_properties
->GetStringWithoutPathExpansion(
733 shill::kL2tpIpsecUserProperty
, &username
);
734 provider_properties
->GetStringWithoutPathExpansion(
735 shill::kL2tpIpsecTunnelGroupProperty
, &group_name
);
736 } else if (provider_type
== shill::kProviderOpenVpn
) {
737 provider_properties
->GetStringWithoutPathExpansion(
738 shill::kOpenVPNClientCertIdProperty
, &client_cert_id_
);
739 ca_cert_pem_
= GetPemFromDictionary(
740 provider_properties
, shill::kOpenVPNCaCertPemProperty
);
741 provider_properties
->GetStringWithoutPathExpansion(
742 shill::kOpenVPNUserProperty
, &username
);
743 provider_properties
->GetBooleanWithoutPathExpansion(
744 shill::kPassphraseRequiredProperty
, &user_passphrase_required_
);
747 bool save_credentials
= false;
748 service_properties
.GetBooleanWithoutPathExpansion(
749 shill::kSaveCredentialsProperty
, &save_credentials
);
751 provider_type_index_
= ProviderTypeToIndex(provider_type
, client_cert_id_
);
754 service_text_
->SetText(base::ASCIIToUTF16(vpn
->name()));
755 if (provider_type_text_label_
)
756 provider_type_text_label_
->SetText(
757 ProviderTypeIndexToString(provider_type_index_
));
759 if (server_textfield_
&& !server_hostname
.empty())
760 server_textfield_
->SetText(base::UTF8ToUTF16(server_hostname
));
761 if (username_textfield_
&& !username
.empty())
762 username_textfield_
->SetText(base::UTF8ToUTF16(username
));
763 if (group_name_textfield_
&& !group_name
.empty())
764 group_name_textfield_
->SetText(base::UTF8ToUTF16(group_name
));
765 if (psk_passphrase_textfield_
)
766 psk_passphrase_textfield_
->SetShowFake(!psk_passphrase_required
);
767 if (user_passphrase_textfield_
)
768 user_passphrase_textfield_
->SetShowFake(!user_passphrase_required_
);
769 if (save_credentials_checkbox_
)
770 save_credentials_checkbox_
->SetChecked(save_credentials
);
776 void VPNConfigView::ParseUIProperties(const NetworkState
* vpn
) {
777 std::string type_dict_name
=
778 ProviderTypeIndexToONCDictKey(provider_type_index_
);
779 if (provider_type_index_
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
) {
780 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kServerCARef
,
782 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kPSK
,
783 &psk_passphrase_ui_data_
);
784 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::ipsec::kGroup
,
785 &group_name_ui_data_
);
786 } else if (provider_type_index_
== PROVIDER_TYPE_INDEX_OPEN_VPN
) {
787 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::openvpn::kServerCARef
,
790 ParseVPNUIProperty(vpn
, type_dict_name
, ::onc::client_cert::kClientCertRef
,
791 &user_cert_ui_data_
);
793 const std::string
credentials_dict_name(
794 provider_type_index_
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
?
795 ::onc::vpn::kL2TP
: type_dict_name
);
796 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kUsername
,
798 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kPassword
,
799 &user_passphrase_ui_data_
);
800 ParseVPNUIProperty(vpn
, credentials_dict_name
, ::onc::vpn::kSaveCredentials
,
801 &save_credentials_ui_data_
);
804 void VPNConfigView::GetPropertiesError(
805 const std::string
& error_name
,
806 scoped_ptr
<base::DictionaryValue
> error_data
) {
807 NET_LOG_ERROR("Shill Error from VpnConfigView: " + error_name
, "");
810 void VPNConfigView::SetConfigProperties(
811 base::DictionaryValue
* properties
) {
812 int provider_type_index
= GetProviderTypeIndex();
813 std::string user_passphrase
= GetUserPassphrase();
814 std::string user_name
= GetUsername();
815 std::string group_name
= GetGroupName();
816 switch (provider_type_index
) {
817 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
: {
818 std::string psk_passphrase
= GetPSKPassphrase();
819 if (!psk_passphrase
.empty()) {
820 properties
->SetStringWithoutPathExpansion(
821 shill::kL2tpIpsecPskProperty
, GetPSKPassphrase());
823 if (!group_name
.empty()) {
824 properties
->SetStringWithoutPathExpansion(
825 shill::kL2tpIpsecTunnelGroupProperty
, group_name
);
827 if (!user_name
.empty()) {
828 properties
->SetStringWithoutPathExpansion(
829 shill::kL2tpIpsecUserProperty
, user_name
);
831 if (!user_passphrase
.empty()) {
832 properties
->SetStringWithoutPathExpansion(
833 shill::kL2tpIpsecPasswordProperty
, user_passphrase
);
837 case PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
: {
838 if (server_ca_cert_combobox_
) {
839 std::string ca_cert_pem
= GetServerCACertPEM();
840 base::ListValue
* pem_list
= new base::ListValue
;
841 if (!ca_cert_pem
.empty())
842 pem_list
->AppendString(ca_cert_pem
);
843 properties
->SetWithoutPathExpansion(shill::kL2tpIpsecCaCertPemProperty
,
846 SetUserCertProperties(client_cert::CONFIG_TYPE_IPSEC
, properties
);
847 if (!group_name
.empty()) {
848 properties
->SetStringWithoutPathExpansion(
849 shill::kL2tpIpsecTunnelGroupProperty
, GetGroupName());
851 if (!user_name
.empty()) {
852 properties
->SetStringWithoutPathExpansion(
853 shill::kL2tpIpsecUserProperty
, user_name
);
855 if (!user_passphrase
.empty()) {
856 properties
->SetStringWithoutPathExpansion(
857 shill::kL2tpIpsecPasswordProperty
, user_passphrase
);
861 case PROVIDER_TYPE_INDEX_OPEN_VPN
: {
862 if (server_ca_cert_combobox_
) {
863 std::string ca_cert_pem
= GetServerCACertPEM();
864 base::ListValue
* pem_list
= new base::ListValue
;
865 if (!ca_cert_pem
.empty())
866 pem_list
->AppendString(ca_cert_pem
);
867 properties
->SetWithoutPathExpansion(shill::kOpenVPNCaCertPemProperty
,
870 SetUserCertProperties(client_cert::CONFIG_TYPE_OPENVPN
, properties
);
871 properties
->SetStringWithoutPathExpansion(
872 shill::kOpenVPNUserProperty
, GetUsername());
873 if (!user_passphrase
.empty()) {
874 properties
->SetStringWithoutPathExpansion(
875 shill::kOpenVPNPasswordProperty
, user_passphrase
);
877 std::string otp
= GetOTP();
879 properties
->SetStringWithoutPathExpansion(
880 shill::kOpenVPNOTPProperty
, otp
);
884 case PROVIDER_TYPE_INDEX_MAX
:
888 properties
->SetBooleanWithoutPathExpansion(
889 shill::kSaveCredentialsProperty
, GetSaveCredentials());
892 void VPNConfigView::Refresh() {
895 // Set certificate combo boxes.
896 if (server_ca_cert_combobox_
) {
897 server_ca_cert_combobox_
->ModelChanged();
898 if (enable_server_ca_cert_
&& !ca_cert_pem_
.empty()) {
899 // Select the current server CA certificate in the combobox.
901 CertLibrary::Get()->GetServerCACertIndexByPEM(ca_cert_pem_
);
902 if (cert_index
>= 0) {
903 // Skip item for "Default"
904 server_ca_cert_combobox_
->SetSelectedIndex(1 + cert_index
);
906 server_ca_cert_combobox_
->SetSelectedIndex(0);
909 server_ca_cert_combobox_
->SetSelectedIndex(0);
913 if (user_cert_combobox_
) {
914 user_cert_combobox_
->ModelChanged();
915 if (enable_user_cert_
&& !client_cert_id_
.empty()) {
917 CertLibrary::Get()->GetUserCertIndexByPkcs11Id(client_cert_id_
);
919 user_cert_combobox_
->SetSelectedIndex(cert_index
);
921 user_cert_combobox_
->SetSelectedIndex(0);
923 user_cert_combobox_
->SetSelectedIndex(0);
930 void VPNConfigView::UpdateControlsToEnable() {
931 enable_psk_passphrase_
= false;
932 enable_user_cert_
= false;
933 enable_server_ca_cert_
= false;
935 enable_group_name_
= false;
936 int provider_type_index
= GetProviderTypeIndex();
937 if (provider_type_index
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_PSK
) {
938 enable_psk_passphrase_
= true;
939 enable_group_name_
= true;
940 } else if (provider_type_index
== PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
) {
941 enable_server_ca_cert_
= true;
942 enable_user_cert_
= HaveUserCerts();
943 enable_group_name_
= true;
944 } else { // PROVIDER_TYPE_INDEX_OPEN_VPN (default)
945 enable_server_ca_cert_
= true;
946 enable_user_cert_
= HaveUserCerts();
951 void VPNConfigView::UpdateControls() {
952 UpdateControlsToEnable();
954 if (psk_passphrase_label_
)
955 psk_passphrase_label_
->SetEnabled(enable_psk_passphrase_
);
956 if (psk_passphrase_textfield_
)
957 psk_passphrase_textfield_
->SetEnabled(enable_psk_passphrase_
&&
958 psk_passphrase_ui_data_
.IsEditable());
960 if (user_cert_label_
)
961 user_cert_label_
->SetEnabled(enable_user_cert_
);
962 if (user_cert_combobox_
)
963 user_cert_combobox_
->SetEnabled(enable_user_cert_
&&
964 user_cert_ui_data_
.IsEditable());
966 if (server_ca_cert_label_
)
967 server_ca_cert_label_
->SetEnabled(enable_server_ca_cert_
);
968 if (server_ca_cert_combobox_
)
969 server_ca_cert_combobox_
->SetEnabled(enable_server_ca_cert_
&&
970 ca_cert_ui_data_
.IsEditable());
973 otp_label_
->SetEnabled(enable_otp_
);
975 otp_textfield_
->SetEnabled(enable_otp_
);
977 if (group_name_label_
)
978 group_name_label_
->SetEnabled(enable_group_name_
);
979 if (group_name_textfield_
)
980 group_name_textfield_
->SetEnabled(enable_group_name_
&&
981 group_name_ui_data_
.IsEditable());
984 void VPNConfigView::UpdateErrorLabel() {
986 base::string16 error_msg
;
988 GetProviderTypeIndex() == PROVIDER_TYPE_INDEX_L2TP_IPSEC_USER_CERT
;
989 if (cert_required
&& CertLibrary::Get()->CertificatesLoaded()) {
990 if (!HaveUserCerts()) {
991 error_msg
= l10n_util::GetStringUTF16(
992 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_PLEASE_INSTALL_USER_CERT
);
993 } else if (!IsUserCertValid()) {
994 error_msg
= l10n_util::GetStringUTF16(
995 IDS_OPTIONS_SETTINGS_INTERNET_OPTIONS_REQUIRE_HARDWARE_BACKED
);
998 if (error_msg
.empty() && !service_path_
.empty()) {
999 // TODO(kuan): differentiate between bad psk and user passphrases.
1000 const NetworkState
* vpn
= NetworkHandler::Get()->network_state_handler()->
1001 GetNetworkState(service_path_
);
1002 if (vpn
&& vpn
->connection_state() == shill::kStateFailure
)
1003 error_msg
= ui::NetworkConnect::Get()->GetShillErrorString(
1004 vpn
->last_error(), vpn
->path());
1006 if (!error_msg
.empty()) {
1007 error_label_
->SetText(error_msg
);
1008 error_label_
->SetVisible(true);
1010 error_label_
->SetVisible(false);
1014 void VPNConfigView::UpdateCanLogin() {
1015 parent_
->GetDialogClientView()->UpdateDialogButtons();
1018 bool VPNConfigView::HaveUserCerts() const {
1019 return CertLibrary::Get()->NumCertificates(CertLibrary::CERT_TYPE_USER
) > 0;
1022 bool VPNConfigView::IsUserCertValid() const {
1023 if (!user_cert_combobox_
|| !enable_user_cert_
)
1025 int index
= user_cert_combobox_
->selected_index();
1028 // Currently only hardware-backed user certificates are valid.
1029 if (!CertLibrary::Get()->IsCertHardwareBackedAt(CertLibrary::CERT_TYPE_USER
,
1036 const std::string
VPNConfigView::GetTextFromField(views::Textfield
* textfield
,
1037 bool trim_whitespace
) const {
1039 return std::string();
1040 std::string untrimmed
= base::UTF16ToUTF8(textfield
->text());
1041 if (!trim_whitespace
)
1044 base::TrimWhitespaceASCII(untrimmed
, base::TRIM_ALL
, &result
);
1048 const std::string
VPNConfigView::GetPassphraseFromField(
1049 PassphraseTextfield
* textfield
) const {
1051 return std::string();
1052 return textfield
->GetPassphrase();
1055 void VPNConfigView::ParseVPNUIProperty(
1056 const NetworkState
* network
,
1057 const std::string
& dict_key
,
1058 const std::string
& key
,
1059 NetworkPropertyUIData
* property_ui_data
) {
1060 ::onc::ONCSource onc_source
= ::onc::ONC_SOURCE_NONE
;
1061 const base::DictionaryValue
* onc
=
1062 onc::FindPolicyForActiveUser(network
->guid(), &onc_source
);
1064 VLOG_IF(1, !onc
) << "No ONC found for VPN network " << network
->guid();
1065 property_ui_data
->ParseOncProperty(
1068 base::StringPrintf("%s.%s.%s",
1069 ::onc::network_config::kVPN
,
1074 } // namespace chromeos