1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h"
10 #include "base/command_line.h"
11 #include "base/lazy_instance.h"
12 #include "base/memory/linked_ptr.h"
13 #include "base/numerics/safe_conversions.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/thread_task_runner_handle.h"
16 #include "base/values.h"
17 #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/signin/easy_unlock_screenlock_state_handler.h"
20 #include "chrome/browser/signin/easy_unlock_service.h"
21 #include "chrome/browser/signin/easy_unlock_service_regular.h"
22 #include "chrome/browser/ui/proximity_auth/proximity_auth_error_bubble.h"
23 #include "chrome/common/extensions/api/easy_unlock_private.h"
24 #include "chrome/grit/generated_resources.h"
25 #include "components/proximity_auth/bluetooth_util.h"
26 #include "components/proximity_auth/cryptauth/base64url.h"
27 #include "components/proximity_auth/cryptauth/cryptauth_device_manager.h"
28 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h"
29 #include "components/proximity_auth/cryptauth/cryptauth_enrollment_utils.h"
30 #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h"
31 #include "components/proximity_auth/cryptauth/secure_message_delegate.h"
32 #include "components/proximity_auth/logging/logging.h"
33 #include "components/proximity_auth/proximity_auth_client.h"
34 #include "components/proximity_auth/screenlock_bridge.h"
35 #include "components/proximity_auth/screenlock_state.h"
36 #include "components/proximity_auth/switches.h"
37 #include "content/public/browser/browser_thread.h"
38 #include "content/public/browser/web_contents.h"
39 #include "extensions/browser/browser_context_keyed_api_factory.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "ui/gfx/geometry/rect.h"
42 #include "ui/gfx/range/range.h"
44 #if defined(OS_CHROMEOS)
45 #include "ash/system/chromeos/devicetype_utils.h"
46 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager.h"
47 #include "chrome/browser/chromeos/login/easy_unlock/easy_unlock_tpm_key_manager_factory.h"
48 #include "components/user_manager/user.h"
49 #include "components/user_manager/user_manager.h"
52 using proximity_auth::ScreenlockState
;
54 namespace extensions
{
56 namespace easy_unlock_private
= api::easy_unlock_private
;
60 static base::LazyInstance
<BrowserContextKeyedAPIFactory
<EasyUnlockPrivateAPI
> >
61 g_factory
= LAZY_INSTANCE_INITIALIZER
;
63 // Utility method for getting the API's crypto delegate.
64 EasyUnlockPrivateCryptoDelegate
* GetCryptoDelegate(
65 content::BrowserContext
* context
) {
66 return BrowserContextKeyedAPIFactory
<EasyUnlockPrivateAPI
>::Get(context
)
67 ->GetCryptoDelegate();
70 ScreenlockState
ToScreenlockState(easy_unlock_private::State state
) {
72 case easy_unlock_private::STATE_NO_BLUETOOTH
:
73 return ScreenlockState::NO_BLUETOOTH
;
74 case easy_unlock_private::STATE_BLUETOOTH_CONNECTING
:
75 return ScreenlockState::BLUETOOTH_CONNECTING
;
76 case easy_unlock_private::STATE_NO_PHONE
:
77 return ScreenlockState::NO_PHONE
;
78 case easy_unlock_private::STATE_PHONE_NOT_AUTHENTICATED
:
79 return ScreenlockState::PHONE_NOT_AUTHENTICATED
;
80 case easy_unlock_private::STATE_PHONE_LOCKED
:
81 return ScreenlockState::PHONE_LOCKED
;
82 case easy_unlock_private::STATE_PHONE_UNLOCKABLE
:
83 return ScreenlockState::PHONE_NOT_LOCKABLE
;
84 case easy_unlock_private::STATE_PHONE_UNSUPPORTED
:
85 return ScreenlockState::PHONE_UNSUPPORTED
;
86 case easy_unlock_private::STATE_RSSI_TOO_LOW
:
87 return ScreenlockState::RSSI_TOO_LOW
;
88 case easy_unlock_private::STATE_TX_POWER_TOO_HIGH
:
89 return ScreenlockState::TX_POWER_TOO_HIGH
;
90 case easy_unlock_private::STATE_PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
:
91 return ScreenlockState::PHONE_LOCKED_AND_TX_POWER_TOO_HIGH
;
92 case easy_unlock_private::STATE_AUTHENTICATED
:
93 return ScreenlockState::AUTHENTICATED
;
95 return ScreenlockState::INACTIVE
;
102 BrowserContextKeyedAPIFactory
<EasyUnlockPrivateAPI
>*
103 EasyUnlockPrivateAPI::GetFactoryInstance() {
104 return g_factory
.Pointer();
107 EasyUnlockPrivateAPI::EasyUnlockPrivateAPI(content::BrowserContext
* context
) {
110 EasyUnlockPrivateAPI::~EasyUnlockPrivateAPI() {}
112 EasyUnlockPrivateCryptoDelegate
* EasyUnlockPrivateAPI::GetCryptoDelegate() {
113 if (!crypto_delegate_
)
114 crypto_delegate_
= EasyUnlockPrivateCryptoDelegate::Create();
115 return crypto_delegate_
.get();
118 EasyUnlockPrivateGetStringsFunction::EasyUnlockPrivateGetStringsFunction() {
120 EasyUnlockPrivateGetStringsFunction::~EasyUnlockPrivateGetStringsFunction() {
123 bool EasyUnlockPrivateGetStringsFunction::RunSync() {
124 scoped_ptr
<base::DictionaryValue
> strings(new base::DictionaryValue
);
126 #if defined(OS_CHROMEOS)
127 const base::string16 device_type
= ash::GetChromeOSDeviceName();
129 // TODO(isherman): Set an appropriate device name for non-ChromeOS devices.
130 const base::string16 device_type
= base::ASCIIToUTF16("Chromeschnozzle");
131 #endif // defined(OS_CHROMEOS)
133 #if defined(OS_CHROMEOS)
134 const user_manager::UserManager
* manager
= user_manager::UserManager::Get();
135 const user_manager::User
* user
= manager
? manager
->GetActiveUser() : NULL
;
136 const std::string user_email_utf8
=
137 user
? user
->display_email() : std::string();
138 const base::string16 user_email
= base::UTF8ToUTF16(user_email_utf8
);
140 // TODO(isherman): Set an appropriate user display email for non-ChromeOS
142 const base::string16 user_email
= base::UTF8ToUTF16("superman@example.com");
143 #endif // defined(OS_CHROMEOS)
147 "learnMoreLinkTitle",
148 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_LEARN_MORE_LINK_TITLE
));
149 strings
->SetString("deviceType", device_type
);
151 // Setup notification strings.
153 "setupNotificationTitle",
154 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_TITLE
));
156 "setupNotificationMessage",
157 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_MESSAGE
,
160 "setupNotificationButtonTitle",
161 l10n_util::GetStringUTF16(
162 IDS_EASY_UNLOCK_SETUP_NOTIFICATION_BUTTON_TITLE
));
164 // Chromebook added to Easy Unlock notification strings.
166 "chromebookAddedNotificationTitle",
167 l10n_util::GetStringUTF16(
168 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_TITLE
));
170 "chromebookAddedNotificationMessage",
171 l10n_util::GetStringFUTF16(
172 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_MESSAGE
,
175 "chromebookAddedNotificationAboutButton",
176 l10n_util::GetStringUTF16(
177 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_ABOUT_BUTTON
));
179 // Shared "Learn more" button for the pairing changed and pairing change
180 // applied notification.
182 "phoneChangedNotificationLearnMoreButton",
183 l10n_util::GetStringUTF16(
184 IDS_EASY_UNLOCK_NOTIFICATION_LEARN_MORE_BUTTON
));
186 // Pairing changed notification strings.
188 "phoneChangedNotificationTitle",
189 l10n_util::GetStringUTF16(
190 IDS_EASY_UNLOCK_PAIRING_CHANGED_NOTIFICATION_TITLE
));
192 "phoneChangedNotificationMessage",
193 l10n_util::GetStringFUTF16(
194 IDS_EASY_UNLOCK_PAIRING_CHANGED_NOTIFICATION_MESSAGE
,
197 "phoneChangedNotificationUpdateButton",
198 l10n_util::GetStringUTF16(
199 IDS_EASY_UNLOCK_PAIRING_CHANGED_NOTIFICATION_UPDATE_BUTTON
));
201 // Phone change applied notification strings.
203 "phoneChangeAppliedNotificationTitle",
204 l10n_util::GetStringUTF16(
205 IDS_EASY_UNLOCK_PAIRING_CHANGE_APPLIED_NOTIFICATION_TITLE
));
207 "phoneChangeAppliedNotificationMessage",
208 l10n_util::GetStringUTF16(
209 IDS_EASY_UNLOCK_PAIRING_CHANGE_APPLIED_NOTIFICATION_MESSAGE
));
211 // Setup dialog strings.
214 "setupIntroHeaderTitle",
215 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TITLE
));
217 "setupIntroHeaderText",
218 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TEXT
,
222 "setupIntroFindPhoneButtonLabel",
223 l10n_util::GetStringUTF16(
224 IDS_EASY_UNLOCK_SETUP_INTRO_FIND_PHONE_BUTTON_LABEL
));
226 "setupIntroFindingPhoneButtonLabel",
227 l10n_util::GetStringUTF16(
228 IDS_EASY_UNLOCK_SETUP_INTRO_FINDING_PHONE_BUTTON_LABEL
));
230 "setupIntroRetryFindPhoneButtonLabel",
231 l10n_util::GetStringUTF16(
232 IDS_EASY_UNLOCK_SETUP_INTRO_RETRY_FIND_PHONE_BUTTON_LABEL
));
234 "setupIntroCloseFindPhoneButtonLabel",
235 l10n_util::GetStringUTF16(
236 IDS_EASY_UNLOCK_SETUP_INTRO_CLOSE_FIND_PHONE_BUTTON_LABEL
));
238 "setupIntroHowIsThisSecureLinkText",
239 l10n_util::GetStringUTF16(
240 IDS_EASY_UNLOCK_SETUP_INTRO_HOW_IS_THIS_SECURE_LINK_TEXT
));
241 // Step 1.5: Phone found but is not secured with lock screen
242 strings
->SetString("setupSecurePhoneHeaderTitle",
243 l10n_util::GetStringUTF16(
244 IDS_EASY_UNLOCK_SETUP_SECURE_PHONE_HEADER_TITLE
));
246 "setupSecurePhoneHeaderText",
247 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_SECURE_PHONE_HEADER_TEXT
,
249 strings
->SetString("setupSecurePhoneButtonLabel",
250 l10n_util::GetStringUTF16(
251 IDS_EASY_UNLOCK_SETUP_SECURE_PHONE_BUTTON_LABEL
));
252 strings
->SetString("setupSecurePhoneLinkText",
253 l10n_util::GetStringUTF16(
254 IDS_EASY_UNLOCK_SETUP_SECURE_PHONE_LINK_TEXT
));
255 // Step 2: Found a viable phone.
257 "setupFoundPhoneHeaderTitle",
258 l10n_util::GetStringFUTF16(
259 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TITLE
, device_type
));
261 "setupFoundPhoneHeaderText",
262 l10n_util::GetStringFUTF16(
263 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TEXT
, device_type
));
265 "setupFoundPhoneUseThisPhoneButtonLabel",
266 l10n_util::GetStringUTF16(
267 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_USE_THIS_PHONE_BUTTON_LABEL
));
268 strings
->SetString("setupFoundPhoneDeviceFormattedButtonLabel",
269 l10n_util::GetStringUTF16(
270 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_DEVICE_FORMATTED_BUTTON_LABEL
));
272 "setupFoundPhoneSwitchPhoneLinkLabel",
273 l10n_util::GetStringUTF16(
274 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_SWITCH_PHONE_LINK_LABEL
));
276 "setupPairingPhoneFailedButtonLabel",
277 l10n_util::GetStringUTF16(
278 IDS_EASY_UNLOCK_SETUP_PAIRING_PHONE_FAILED_BUTTON_LABEL
));
279 // Step 2.5: Recommend user to set up Android Smart Lock
281 "setupAndroidSmartLockHeaderTitle",
282 l10n_util::GetStringUTF16(
283 IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_HEADER_TITLE
));
285 "setupAndroidSmartLockHeaderText",
286 l10n_util::GetStringFUTF16(
287 IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_HEADER_TEXT
, device_type
));
289 "setupAndroidSmartLockDoneButtonText",
290 l10n_util::GetStringUTF16(
291 IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_DONE_BUTTON_LABEL
));
293 "setupAndroidSmartLockAboutLinkText",
294 l10n_util::GetStringUTF16(
295 IDS_EASY_UNLOCK_SETUP_ANDROID_SMART_LOCK_ABOUT_LINK_TEXT
));
296 // Step 3: Setup completed successfully.
298 "setupCompleteHeaderTitle",
299 l10n_util::GetStringUTF16(
300 IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TITLE
));
302 "setupCompleteHeaderText",
303 l10n_util::GetStringUTF16(
304 IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TEXT
));
306 "setupCompleteTryItOutButtonLabel",
307 l10n_util::GetStringUTF16(
308 IDS_EASY_UNLOCK_SETUP_COMPLETE_TRY_IT_OUT_BUTTON_LABEL
));
310 "setupCompleteSettingsLinkText",
311 l10n_util::GetStringUTF16(
312 IDS_EASY_UNLOCK_SETUP_COMPLETE_SETTINGS_LINK_TEXT
));
313 // Step 4: Post lockscreen confirmation.
314 strings
->SetString("setupPostLockDismissButtonLabel",
315 l10n_util::GetStringUTF16(
316 IDS_EASY_UNLOCK_SETUP_POST_LOCK_DISMISS_BUTTON_LABEL
));
320 "setupErrorBluetoothUnavailable",
321 l10n_util::GetStringFUTF16(
322 IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_UNAVAILBLE
, device_type
));
325 l10n_util::GetStringFUTF16(
326 IDS_EASY_UNLOCK_SETUP_ERROR_OFFLINE
, device_type
));
328 "setupErrorRemoteSoftwareOutOfDate",
329 l10n_util::GetStringUTF16(
330 IDS_EASY_UNLOCK_SETUP_ERROR_REMOTE_SOFTWARE_OUT_OF_DATE
));
332 "setupErrorRemoteSoftwareOutOfDateGeneric",
333 l10n_util::GetStringUTF16(
334 IDS_EASY_UNLOCK_SETUP_ERROR_REMOTE_SOFTWARE_OUT_OF_DATE_GENERIC
));
336 "setupErrorFindingPhone",
337 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SETUP_ERROR_FINDING_PHONE
));
339 "setupErrorSyncPhoneState",
340 l10n_util::GetStringUTF16(
341 IDS_EASY_UNLOCK_SETUP_ERROR_SYNC_PHONE_STATE_FAILED
));
343 "setupErrorConnectingToPhone",
344 l10n_util::GetStringFUTF16(
345 IDS_EASY_UNLOCK_SETUP_ERROR_CONNECTING_TO_PHONE
, device_type
));
347 SetResult(strings
.release());
351 EasyUnlockPrivatePerformECDHKeyAgreementFunction::
352 EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
354 EasyUnlockPrivatePerformECDHKeyAgreementFunction::
355 ~EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
357 bool EasyUnlockPrivatePerformECDHKeyAgreementFunction::RunAsync() {
358 scoped_ptr
<easy_unlock_private::PerformECDHKeyAgreement::Params
> params
=
359 easy_unlock_private::PerformECDHKeyAgreement::Params::Create(*args_
);
360 EXTENSION_FUNCTION_VALIDATE(params
);
362 GetCryptoDelegate(browser_context())->PerformECDHKeyAgreement(
364 base::Bind(&EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData
,
369 void EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData(
370 const std::string
& secret_key
) {
371 // TODO(tbarzic): Improve error handling.
372 if (!secret_key
.empty()) {
373 results_
= easy_unlock_private::PerformECDHKeyAgreement::Results::Create(
374 std::vector
<char>(secret_key
.begin(), secret_key
.end()));
379 EasyUnlockPrivateGenerateEcP256KeyPairFunction::
380 EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
382 EasyUnlockPrivateGenerateEcP256KeyPairFunction::
383 ~EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
385 bool EasyUnlockPrivateGenerateEcP256KeyPairFunction::RunAsync() {
386 GetCryptoDelegate(browser_context())->GenerateEcP256KeyPair(
387 base::Bind(&EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData
,
392 void EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData(
393 const std::string
& private_key
,
394 const std::string
& public_key
) {
395 // TODO(tbarzic): Improve error handling.
396 if (!public_key
.empty() && !private_key
.empty()) {
397 results_
= easy_unlock_private::GenerateEcP256KeyPair::Results::Create(
398 std::vector
<char>(public_key
.begin(), public_key
.end()),
399 std::vector
<char>(private_key
.begin(), private_key
.end()));
404 EasyUnlockPrivateCreateSecureMessageFunction::
405 EasyUnlockPrivateCreateSecureMessageFunction() {}
407 EasyUnlockPrivateCreateSecureMessageFunction::
408 ~EasyUnlockPrivateCreateSecureMessageFunction() {}
410 bool EasyUnlockPrivateCreateSecureMessageFunction::RunAsync() {
411 scoped_ptr
<easy_unlock_private::CreateSecureMessage::Params
> params
=
412 easy_unlock_private::CreateSecureMessage::Params::Create(*args_
);
413 EXTENSION_FUNCTION_VALIDATE(params
);
415 GetCryptoDelegate(browser_context())->CreateSecureMessage(
417 base::Bind(&EasyUnlockPrivateCreateSecureMessageFunction::OnData
,
422 void EasyUnlockPrivateCreateSecureMessageFunction::OnData(
423 const std::string
& message
) {
424 // TODO(tbarzic): Improve error handling.
425 if (!message
.empty()) {
426 results_
= easy_unlock_private::CreateSecureMessage::Results::Create(
427 std::vector
<char>(message
.begin(), message
.end()));
432 EasyUnlockPrivateUnwrapSecureMessageFunction::
433 EasyUnlockPrivateUnwrapSecureMessageFunction() {}
435 EasyUnlockPrivateUnwrapSecureMessageFunction::
436 ~EasyUnlockPrivateUnwrapSecureMessageFunction() {}
438 bool EasyUnlockPrivateUnwrapSecureMessageFunction::RunAsync() {
439 scoped_ptr
<easy_unlock_private::UnwrapSecureMessage::Params
> params
=
440 easy_unlock_private::UnwrapSecureMessage::Params::Create(*args_
);
441 EXTENSION_FUNCTION_VALIDATE(params
);
443 GetCryptoDelegate(browser_context())->UnwrapSecureMessage(
445 base::Bind(&EasyUnlockPrivateUnwrapSecureMessageFunction::OnData
,
450 void EasyUnlockPrivateUnwrapSecureMessageFunction::OnData(
451 const std::string
& data
) {
452 // TODO(tbarzic): Improve error handling.
454 results_
= easy_unlock_private::UnwrapSecureMessage::Results::Create(
455 std::vector
<char>(data
.begin(), data
.end()));
460 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
461 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
463 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
464 ~EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
466 bool EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::RunAsync() {
467 scoped_ptr
<easy_unlock_private::SeekBluetoothDeviceByAddress::Params
> params(
468 easy_unlock_private::SeekBluetoothDeviceByAddress::Params::Create(
470 EXTENSION_FUNCTION_VALIDATE(params
.get());
472 proximity_auth::bluetooth_util::SeekDeviceByAddress(
473 params
->device_address
,
475 &EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekSuccess
,
478 &EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekFailure
,
480 content::BrowserThread::GetBlockingPool()
481 ->GetTaskRunnerWithShutdownBehavior(
482 base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN
)
487 void EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekSuccess() {
491 void EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekFailure(
492 const std::string
& error_message
) {
493 SetError(error_message
);
497 EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
498 EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction() {}
500 EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
501 ~EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction() {}
503 void EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
504 ConnectToService(device::BluetoothDevice
* device
,
505 const device::BluetoothUUID
& uuid
) {
506 device
->ConnectToServiceInsecurely(
508 base::Bind(&EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
511 base::Bind(&EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
516 EasyUnlockPrivateUpdateScreenlockStateFunction::
517 EasyUnlockPrivateUpdateScreenlockStateFunction() {}
519 EasyUnlockPrivateUpdateScreenlockStateFunction::
520 ~EasyUnlockPrivateUpdateScreenlockStateFunction() {}
522 bool EasyUnlockPrivateUpdateScreenlockStateFunction::RunSync() {
523 scoped_ptr
<easy_unlock_private::UpdateScreenlockState::Params
> params(
524 easy_unlock_private::UpdateScreenlockState::Params::Create(*args_
));
525 EXTENSION_FUNCTION_VALIDATE(params
.get());
527 Profile
* profile
= Profile::FromBrowserContext(browser_context());
528 if (EasyUnlockService::Get(profile
)->UpdateScreenlockState(
529 ToScreenlockState(params
->state
)))
532 SetError("Not allowed");
536 EasyUnlockPrivateSetPermitAccessFunction::
537 EasyUnlockPrivateSetPermitAccessFunction() {
540 EasyUnlockPrivateSetPermitAccessFunction::
541 ~EasyUnlockPrivateSetPermitAccessFunction() {
544 bool EasyUnlockPrivateSetPermitAccessFunction::RunSync() {
545 scoped_ptr
<easy_unlock_private::SetPermitAccess::Params
> params(
546 easy_unlock_private::SetPermitAccess::Params::Create(*args_
));
547 EXTENSION_FUNCTION_VALIDATE(params
.get());
549 Profile
* profile
= Profile::FromBrowserContext(browser_context());
550 EasyUnlockService::Get(profile
)
551 ->SetPermitAccess(*params
->permit_access
.ToValue());
556 EasyUnlockPrivateGetPermitAccessFunction::
557 EasyUnlockPrivateGetPermitAccessFunction() {
560 EasyUnlockPrivateGetPermitAccessFunction::
561 ~EasyUnlockPrivateGetPermitAccessFunction() {
564 bool EasyUnlockPrivateGetPermitAccessFunction::RunSync() {
565 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
566 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
)) {
567 ReturnPermitAccessForExperiment();
571 Profile
* profile
= Profile::FromBrowserContext(browser_context());
572 const base::DictionaryValue
* permit_value
=
573 EasyUnlockService::Get(profile
)->GetPermitAccess();
575 scoped_ptr
<easy_unlock_private::PermitRecord
> permit
=
576 easy_unlock_private::PermitRecord::FromValue(*permit_value
);
577 results_
= easy_unlock_private::GetPermitAccess::Results::Create(*permit
);
583 void EasyUnlockPrivateGetPermitAccessFunction::GetKeyPairForExperiment(
584 std::string
* user_public_key
,
585 std::string
* user_private_key
) {
586 Profile
* profile
= Profile::FromBrowserContext(browser_context());
587 proximity_auth::CryptAuthEnrollmentManager
* enrollment_manager
=
588 EasyUnlockService::Get(profile
)
589 ->proximity_auth_client()
590 ->GetCryptAuthEnrollmentManager();
591 proximity_auth::Base64UrlEncode(enrollment_manager
->GetUserPublicKey(),
593 proximity_auth::Base64UrlEncode(enrollment_manager
->GetUserPrivateKey(),
597 void EasyUnlockPrivateGetPermitAccessFunction::
598 ReturnPermitAccessForExperiment() {
599 // Check that we are inside a user session.
600 Profile
* profile
= Profile::FromBrowserContext(browser_context());
601 EasyUnlockService
* easy_unlock_service
= EasyUnlockService::Get(profile
);
602 if (easy_unlock_service
->GetType() != EasyUnlockService::TYPE_REGULAR
) {
603 SetError("This function must be called inside a user session.");
608 std::string b64_public_key
, b64_private_key
;
609 GetKeyPairForExperiment(&b64_public_key
, &b64_private_key
);
611 // Fill in the permit access JSON dictionary.
612 proximity_auth::ProximityAuthClient
* client
=
613 easy_unlock_service
->proximity_auth_client();
614 scoped_ptr
<base::DictionaryValue
> permit_access(new base::DictionaryValue());
615 permit_access
->SetString("permitId",
616 "permit://google.com/" + client
->GetAccountId());
617 permit_access
->SetString("id", b64_public_key
);
618 permit_access
->SetString("type", "access");
619 permit_access
->SetString("data", b64_private_key
);
621 PA_LOG(INFO
) << "Returning permit access for "
622 << "chrome.easyUnlockPrivate.getPermitAccess:\n"
623 << " id: " << b64_public_key
;
625 scoped_ptr
<easy_unlock_private::PermitRecord
> result
=
626 easy_unlock_private::PermitRecord::FromValue(*permit_access
);
627 results_
= easy_unlock_private::GetPermitAccess::Results::Create(*result
);
630 EasyUnlockPrivateClearPermitAccessFunction::
631 EasyUnlockPrivateClearPermitAccessFunction() {
634 EasyUnlockPrivateClearPermitAccessFunction::
635 ~EasyUnlockPrivateClearPermitAccessFunction() {
638 bool EasyUnlockPrivateClearPermitAccessFunction::RunSync() {
639 Profile
* profile
= Profile::FromBrowserContext(browser_context());
640 EasyUnlockService::Get(profile
)->ClearPermitAccess();
644 EasyUnlockPrivateSetRemoteDevicesFunction::
645 EasyUnlockPrivateSetRemoteDevicesFunction() {
648 EasyUnlockPrivateSetRemoteDevicesFunction::
649 ~EasyUnlockPrivateSetRemoteDevicesFunction() {
652 bool EasyUnlockPrivateSetRemoteDevicesFunction::RunSync() {
653 scoped_ptr
<easy_unlock_private::SetRemoteDevices::Params
> params(
654 easy_unlock_private::SetRemoteDevices::Params::Create(*args_
));
655 EXTENSION_FUNCTION_VALIDATE(params
.get());
657 Profile
* profile
= Profile::FromBrowserContext(browser_context());
658 base::ListValue devices
;
659 for (size_t i
= 0; i
< params
->devices
.size(); ++i
) {
660 devices
.Append(params
->devices
[i
]->ToValue().release());
662 EasyUnlockService::Get(profile
)->SetRemoteDevices(devices
);
667 EasyUnlockPrivateGetRemoteDevicesFunction::
668 EasyUnlockPrivateGetRemoteDevicesFunction() {
671 EasyUnlockPrivateGetRemoteDevicesFunction::
672 ~EasyUnlockPrivateGetRemoteDevicesFunction() {
675 bool EasyUnlockPrivateGetRemoteDevicesFunction::RunAsync() {
676 // Return the remote devices stored with the native CryptAuthDeviceManager if
677 // we are trying out the BLE experiment.
678 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
679 proximity_auth::switches::kEnableBluetoothLowEnergyDiscovery
)) {
680 ReturnDevicesForExperiment();
682 Profile
* profile
= Profile::FromBrowserContext(browser_context());
683 const base::ListValue
* devices
=
684 EasyUnlockService::Get(profile
)->GetRemoteDevices();
685 SetResult(devices
? devices
->DeepCopy() : new base::ListValue());
692 std::string
EasyUnlockPrivateGetRemoteDevicesFunction::GetUserPrivateKey() {
693 Profile
* profile
= Profile::FromBrowserContext(browser_context());
694 proximity_auth::ProximityAuthClient
* client
=
695 EasyUnlockService::Get(profile
)->proximity_auth_client();
696 proximity_auth::CryptAuthEnrollmentManager
* enrollment_manager
=
697 client
->GetCryptAuthEnrollmentManager();
698 return enrollment_manager
->GetUserPrivateKey();
701 std::vector
<cryptauth::ExternalDeviceInfo
>
702 EasyUnlockPrivateGetRemoteDevicesFunction::GetUnlockKeys() {
703 Profile
* profile
= Profile::FromBrowserContext(browser_context());
704 proximity_auth::ProximityAuthClient
* client
=
705 EasyUnlockService::Get(profile
)->proximity_auth_client();
706 proximity_auth::CryptAuthDeviceManager
* device_manager
=
707 client
->GetCryptAuthDeviceManager();
708 return device_manager
->unlock_keys();
711 void EasyUnlockPrivateGetRemoteDevicesFunction::ReturnDevicesForExperiment() {
712 // Check that we are inside a user profile.
713 Profile
* profile
= Profile::FromBrowserContext(browser_context());
714 EasyUnlockService
* easy_unlock_service
= EasyUnlockService::Get(profile
);
715 if (easy_unlock_service
->GetType() != EasyUnlockService::TYPE_REGULAR
) {
716 SetError("This function must be called inside a user session.");
721 // Get the synced unlock key data.
722 proximity_auth::ProximityAuthClient
* client
=
723 easy_unlock_service
->proximity_auth_client();
725 permit_id_
= "permit://google.com/easyunlock/v1/" + client
->GetAccountId();
726 secure_message_delegate_
= client
->CreateSecureMessageDelegate();
727 std::vector
<cryptauth::ExternalDeviceInfo
> unlock_keys
= GetUnlockKeys();
728 expected_devices_count_
= unlock_keys
.size();
730 remote_devices_
.reset(new base::ListValue());
731 if (expected_devices_count_
== 0) {
732 SetResult(remote_devices_
.Pass());
737 // If there is a BLE unlock key, then don't return anything, so the app does
738 // not try the classic Bluetooth protocol.
739 for (const auto& unlock_key
: unlock_keys
) {
740 if (unlock_key
.bluetooth_address().empty()) {
741 SetResult(remote_devices_
.Pass());
747 // Derive the PSKs for the user's unlock keys.
748 PA_LOG(INFO
) << "Deriving PSKs for "
749 << "chrome.easyUnlockPrivate.getRemoteDevices.\n"
750 << "Expecting " << expected_devices_count_
<< " devices.";
751 for (const auto& unlock_key
: unlock_keys
) {
752 secure_message_delegate_
->DeriveKey(
753 GetUserPrivateKey(), unlock_key
.public_key(),
755 &EasyUnlockPrivateGetRemoteDevicesFunction::OnPSKDerivedForDevice
,
760 void EasyUnlockPrivateGetRemoteDevicesFunction::OnPSKDerivedForDevice(
761 const cryptauth::ExternalDeviceInfo
& device
,
762 const std::string
& persistent_symmetric_key
) {
763 std::string b64_public_key
, b64_psk
;
764 proximity_auth::Base64UrlEncode(device
.public_key(), &b64_public_key
);
765 proximity_auth::Base64UrlEncode(persistent_symmetric_key
, &b64_psk
);
767 // Fill in the JSON dictionary containing a single unlock key's data.
768 scoped_ptr
<base::DictionaryValue
> device_dictionary(
769 new base::DictionaryValue());
770 device_dictionary
->SetString("name", device
.friendly_device_name());
771 device_dictionary
->SetString("bluetoothAddress", device
.bluetooth_address());
772 device_dictionary
->SetString("psk", b64_psk
);
774 // Fill in the permit license for the unlock key.
775 scoped_ptr
<base::DictionaryValue
> permit_license(new base::DictionaryValue());
776 permit_license
->SetString("permitId", permit_id_
);
777 permit_license
->SetString("id", b64_public_key
);
778 permit_license
->SetString("type", "license");
779 permit_license
->SetString("data", b64_public_key
);
780 device_dictionary
->Set("permitRecord", permit_license
.Pass());
782 remote_devices_
->Append(device_dictionary
.Pass());
784 // If all PSKs are derived, then return from the API call.
785 PA_LOG(INFO
) << "Derived PSK for " << b64_public_key
<< ": "
786 << remote_devices_
->GetSize() << "/" << expected_devices_count_
;
787 if (remote_devices_
->GetSize() == expected_devices_count_
) {
788 SetResult(remote_devices_
.Pass());
793 EasyUnlockPrivateGetSignInChallengeFunction::
794 EasyUnlockPrivateGetSignInChallengeFunction() {
797 EasyUnlockPrivateGetSignInChallengeFunction::
798 ~EasyUnlockPrivateGetSignInChallengeFunction() {
801 bool EasyUnlockPrivateGetSignInChallengeFunction::RunAsync() {
802 scoped_ptr
<easy_unlock_private::GetSignInChallenge::Params
> params(
803 easy_unlock_private::GetSignInChallenge::Params::Create(*args_
));
804 EXTENSION_FUNCTION_VALIDATE(params
.get());
806 #if defined(OS_CHROMEOS)
807 Profile
* profile
= Profile::FromBrowserContext(browser_context());
808 const std::string challenge
=
809 EasyUnlockService::Get(profile
)->GetChallenge();
810 if (!challenge
.empty() && !params
->nonce
.empty()) {
811 EasyUnlockTpmKeyManager
* key_manager
=
812 EasyUnlockTpmKeyManagerFactory::GetInstance()->Get(profile
);
814 SetError("No EasyUnlockTpmKeyManager.");
817 key_manager
->SignUsingTpmKey(
818 EasyUnlockService::Get(profile
)->GetUserEmail(),
819 std::string(params
->nonce
.begin(), params
->nonce
.end()),
820 base::Bind(&EasyUnlockPrivateGetSignInChallengeFunction::OnDone
, this,
823 OnDone(challenge
, std::string());
826 #else // if !defined(OS_CHROMEOS)
827 SetError("Sign-in not supported.");
829 #endif // defined(OS_CHROMEOS)
832 void EasyUnlockPrivateGetSignInChallengeFunction::OnDone(
833 const std::string
& challenge
,
834 const std::string
& signed_nonce
) {
835 results_
= easy_unlock_private::GetSignInChallenge::Results::Create(
836 std::vector
<char>(challenge
.begin(), challenge
.end()),
837 std::vector
<char>(signed_nonce
.begin(), signed_nonce
.end()));
841 EasyUnlockPrivateTrySignInSecretFunction::
842 EasyUnlockPrivateTrySignInSecretFunction() {
845 EasyUnlockPrivateTrySignInSecretFunction::
846 ~EasyUnlockPrivateTrySignInSecretFunction() {
849 bool EasyUnlockPrivateTrySignInSecretFunction::RunSync() {
850 scoped_ptr
<easy_unlock_private::TrySignInSecret::Params
> params(
851 easy_unlock_private::TrySignInSecret::Params::Create(*args_
));
852 EXTENSION_FUNCTION_VALIDATE(params
.get());
854 Profile
* profile
= Profile::FromBrowserContext(browser_context());
855 EasyUnlockService::Get(profile
)->FinalizeSignin(std::string(
856 params
->sign_in_secret
.begin(), params
->sign_in_secret
.end()));
860 EasyUnlockPrivateGetUserInfoFunction::EasyUnlockPrivateGetUserInfoFunction() {
863 EasyUnlockPrivateGetUserInfoFunction::~EasyUnlockPrivateGetUserInfoFunction() {
866 bool EasyUnlockPrivateGetUserInfoFunction::RunSync() {
867 EasyUnlockService
* service
=
868 EasyUnlockService::Get(Profile::FromBrowserContext(browser_context()));
869 std::vector
<linked_ptr
<easy_unlock_private::UserInfo
> > users
;
870 std::string user_id
= service
->GetUserEmail();
871 if (!user_id
.empty()) {
873 linked_ptr
<easy_unlock_private::UserInfo
>(
874 new easy_unlock_private::UserInfo()));
875 users
[0]->user_id
= user_id
;
876 users
[0]->logged_in
= service
->GetType() == EasyUnlockService::TYPE_REGULAR
;
877 users
[0]->data_ready
= users
[0]->logged_in
||
878 service
->GetRemoteDevices() != NULL
;
880 EasyUnlockService::UserSettings user_settings
=
881 EasyUnlockService::GetUserSettings(user_id
);
882 users
[0]->require_close_proximity
= user_settings
.require_close_proximity
;
884 users
[0]->device_user_id
= proximity_auth::CalculateDeviceUserId(
885 EasyUnlockService::GetDeviceId(), user_id
);
887 results_
= easy_unlock_private::GetUserInfo::Results::Create(users
);
891 EasyUnlockPrivateGetConnectionInfoFunction::
892 EasyUnlockPrivateGetConnectionInfoFunction() {
895 EasyUnlockPrivateGetConnectionInfoFunction::
896 ~EasyUnlockPrivateGetConnectionInfoFunction() {
899 bool EasyUnlockPrivateGetConnectionInfoFunction::DoWork(
900 scoped_refptr
<device::BluetoothAdapter
> adapter
) {
901 scoped_ptr
<easy_unlock_private::GetConnectionInfo::Params
> params
=
902 easy_unlock_private::GetConnectionInfo::Params::Create(*args_
);
903 EXTENSION_FUNCTION_VALIDATE(params
);
905 device::BluetoothDevice
* device
= adapter
->GetDevice(params
->device_address
);
909 error
= "Invalid Bluetooth device.";
910 else if (!device
->IsConnected())
911 error
= "Bluetooth device not connected.";
913 if (!error
.empty()) {
919 device
->GetConnectionInfo(base::Bind(
920 &EasyUnlockPrivateGetConnectionInfoFunction::OnConnectionInfo
, this));
924 void EasyUnlockPrivateGetConnectionInfoFunction::OnConnectionInfo(
925 const device::BluetoothDevice::ConnectionInfo
& connection_info
) {
926 scoped_ptr
<base::ListValue
> results(new base::ListValue());
927 results
->AppendInteger(connection_info
.rssi
);
928 results
->AppendInteger(connection_info
.transmit_power
);
929 results
->AppendInteger(connection_info
.max_transmit_power
);
930 SetResultList(results
.Pass());
934 EasyUnlockPrivateShowErrorBubbleFunction::
935 EasyUnlockPrivateShowErrorBubbleFunction() {
938 EasyUnlockPrivateShowErrorBubbleFunction::
939 ~EasyUnlockPrivateShowErrorBubbleFunction() {
942 bool EasyUnlockPrivateShowErrorBubbleFunction::RunSync() {
943 content::WebContents
* web_contents
= GetAssociatedWebContents();
945 SetError("A foreground app window is required.");
949 scoped_ptr
<easy_unlock_private::ShowErrorBubble::Params
> params(
950 easy_unlock_private::ShowErrorBubble::Params::Create(*args_
));
951 EXTENSION_FUNCTION_VALIDATE(params
.get());
953 if (params
->link_range
.start
< 0 ||
954 params
->link_range
.end
< 0 ||
955 base::saturated_cast
<size_t>(params
->link_range
.end
) >
956 params
->message
.size()) {
957 SetError("Invalid link range.");
961 #if defined(TOOLKIT_VIEWS)
962 gfx::Rect
anchor_rect(
963 params
->anchor_rect
.left
, params
->anchor_rect
.top
,
964 params
->anchor_rect
.width
, params
->anchor_rect
.height
);
966 web_contents
->GetContainerBounds().OffsetFromOrigin();
967 ShowProximityAuthErrorBubble(
968 base::UTF8ToUTF16(params
->message
),
969 gfx::Range(params
->link_range
.start
, params
->link_range
.end
),
970 GURL(params
->link_target
), anchor_rect
, web_contents
);
972 SetError("Not supported on non-Views platforms.");
977 EasyUnlockPrivateHideErrorBubbleFunction::
978 EasyUnlockPrivateHideErrorBubbleFunction() {
981 EasyUnlockPrivateHideErrorBubbleFunction::
982 ~EasyUnlockPrivateHideErrorBubbleFunction() {
985 bool EasyUnlockPrivateHideErrorBubbleFunction::RunSync() {
986 #if defined(TOOLKIT_VIEWS)
987 HideProximityAuthErrorBubble();
989 SetError("Not supported on non-Views platforms.");
994 EasyUnlockPrivateSetAutoPairingResultFunction::
995 EasyUnlockPrivateSetAutoPairingResultFunction() {
998 EasyUnlockPrivateSetAutoPairingResultFunction::
999 ~EasyUnlockPrivateSetAutoPairingResultFunction() {
1002 bool EasyUnlockPrivateSetAutoPairingResultFunction::RunSync() {
1003 scoped_ptr
<easy_unlock_private::SetAutoPairingResult::Params
> params
=
1004 easy_unlock_private::SetAutoPairingResult::Params::Create(*args_
);
1005 EXTENSION_FUNCTION_VALIDATE(params
);
1007 std::string error_message
;
1008 if (params
->result
.error_message
)
1009 error_message
= *params
->result
.error_message
;
1011 Profile
* profile
= Profile::FromBrowserContext(browser_context());
1012 EasyUnlockService::Get(profile
)
1013 ->SetAutoPairingResult(params
->result
.success
, error_message
);
1018 } // namespace extensions