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"
8 #include "base/lazy_instance.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_bluetooth_util.h"
12 #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/signin/easy_unlock_screenlock_state_handler.h"
15 #include "chrome/browser/signin/easy_unlock_service.h"
16 #include "chrome/common/extensions/api/easy_unlock_private.h"
17 #include "extensions/browser/browser_context_keyed_api_factory.h"
18 #include "grit/generated_resources.h"
19 #include "ui/base/l10n/l10n_util.h"
21 #if defined(OS_CHROMEOS)
22 #include "chrome/browser/chromeos/chromeos_utils.h"
23 #include "components/user_manager/user.h"
24 #include "components/user_manager/user_manager.h"
27 namespace extensions {
32 static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI> >
33 g_factory = LAZY_INSTANCE_INITIALIZER;
35 // Utility method for getting the API's crypto delegate.
36 EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate(
37 content::BrowserContext* context) {
38 return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context)
42 EasyUnlockScreenlockStateHandler* GetScreenlockStateHandler(
43 content::BrowserContext* context) {
44 return EasyUnlockService::Get(Profile::FromBrowserContext(context))
45 ->GetScreenlockStateHandler();
48 EasyUnlockScreenlockStateHandler::State ToScreenlockStateHandlerState(
49 easy_unlock_private::State state) {
51 case easy_unlock_private::STATE_NO_BLUETOOTH:
52 return EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH;
53 case easy_unlock_private::STATE_BLUETOOTH_CONNECTING:
54 return EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING;
55 case easy_unlock_private::STATE_NO_PHONE:
56 return EasyUnlockScreenlockStateHandler::STATE_NO_PHONE;
57 case easy_unlock_private::STATE_PHONE_NOT_AUTHENTICATED:
58 return EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED;
59 case easy_unlock_private::STATE_PHONE_LOCKED:
60 return EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED;
61 case easy_unlock_private::STATE_PHONE_UNLOCKABLE:
62 return EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE;
63 case easy_unlock_private::STATE_PHONE_NOT_NEARBY:
64 return EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY;
65 case easy_unlock_private::STATE_PHONE_UNSUPPORTED:
66 return EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED;
67 case easy_unlock_private::STATE_AUTHENTICATED:
68 return EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED;
70 return EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
77 BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>*
78 EasyUnlockPrivateAPI::GetFactoryInstance() {
79 return g_factory.Pointer();
82 EasyUnlockPrivateAPI::EasyUnlockPrivateAPI(content::BrowserContext* context)
83 : crypto_delegate_(EasyUnlockPrivateCryptoDelegate::Create()) {
86 EasyUnlockPrivateAPI::~EasyUnlockPrivateAPI() {}
88 EasyUnlockPrivateGetStringsFunction::EasyUnlockPrivateGetStringsFunction() {
90 EasyUnlockPrivateGetStringsFunction::~EasyUnlockPrivateGetStringsFunction() {
93 bool EasyUnlockPrivateGetStringsFunction::RunSync() {
94 scoped_ptr<base::DictionaryValue> strings(new base::DictionaryValue);
96 #if defined(OS_CHROMEOS)
97 const base::string16 device_type = chromeos::GetChromeDeviceType();
99 // TODO(isherman): Set an appropriate device name for non-ChromeOS devices.
100 const base::string16 device_type = base::ASCIIToUTF16("Chromeschnozzle");
101 #endif // defined(OS_CHROMEOS)
103 #if defined(OS_CHROMEOS)
104 const user_manager::UserManager* manager = user_manager::UserManager::Get();
105 const user_manager::User* user = manager ? manager->GetActiveUser() : NULL;
106 const std::string user_email_utf8 =
107 user ? user->display_email() : std::string();
108 const base::string16 user_email = base::UTF8ToUTF16(user_email_utf8);
110 // TODO(isherman): Set an appropriate user display email for non-ChromeOS
112 const base::string16 user_email = base::UTF8ToUTF16("superman@example.com");
113 #endif // defined(OS_CHROMEOS)
117 "learnMoreLinkTitle",
118 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_LEARN_MORE_LINK_TITLE));
120 // Setup notification strings.
122 "setupNotificationTitle",
123 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_TITLE,
126 "setupNotificationMessage",
127 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_MESSAGE,
130 "setupNotificationButtonTitle",
131 l10n_util::GetStringUTF16(
132 IDS_EASY_UNLOCK_SETUP_NOTIFICATION_BUTTON_TITLE));
134 // Success notification strings.
136 "successNotificationTitle",
137 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SUCCESS_NOTIFICATION_TITLE));
139 "successNotificationMessage",
140 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SUCCESS_NOTIFICATION_MESSAGE,
143 // Chromebook added to Easy Unlock notification strings.
145 "chromebookAddedNotificationTitle",
146 l10n_util::GetStringUTF16(
147 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_TITLE));
149 "chromebookAddedNotificationMessage",
150 l10n_util::GetStringFUTF16(
151 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_MESSAGE,
154 // Setup dialog strings.
157 "setupIntroHeaderTitle",
158 l10n_util::GetStringFUTF16(
159 IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TITLE, device_type));
161 "setupIntroHeaderText",
162 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TEXT,
166 "setupIntroFindPhoneButtonLabel",
167 l10n_util::GetStringUTF16(
168 IDS_EASY_UNLOCK_SETUP_INTRO_FIND_PHONE_BUTTON_LABEL));
170 "setupIntroFindingPhoneButtonLabel",
171 l10n_util::GetStringUTF16(
172 IDS_EASY_UNLOCK_SETUP_INTRO_FINDING_PHONE_BUTTON_LABEL));
174 "setupIntroRetryFindPhoneButtonLabel",
175 l10n_util::GetStringUTF16(
176 IDS_EASY_UNLOCK_SETUP_INTRO_RETRY_FIND_PHONE_BUTTON_LABEL));
178 "setupIntroHowIsThisSecureLinkText",
179 l10n_util::GetStringUTF16(
180 IDS_EASY_UNLOCK_SETUP_INTRO_HOW_IS_THIS_SECURE_LINK_TEXT));
181 // Step 2: Found a viable phone.
183 "setupFoundPhoneHeaderTitle",
184 l10n_util::GetStringFUTF16(
185 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TITLE, device_type));
187 "setupFoundPhoneHeaderText",
188 l10n_util::GetStringFUTF16(
189 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TEXT, device_type));
191 "setupFoundPhoneUseThisPhoneButtonLabel",
192 l10n_util::GetStringUTF16(
193 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_USE_THIS_PHONE_BUTTON_LABEL));
195 "setupPairingPhoneFailedButtonLabel",
196 l10n_util::GetStringUTF16(
197 IDS_EASY_UNLOCK_SETUP_PAIRING_PHONE_FAILED_BUTTON_LABEL));
198 // Step 3: Setup completed successfully.
200 "setupCompleteHeaderTitle",
201 l10n_util::GetStringUTF16(
202 IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TITLE));
204 "setupCompleteHeaderText",
205 l10n_util::GetStringUTF16(
206 IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TEXT));
208 "setupCompleteTryItOutButtonLabel",
209 l10n_util::GetStringUTF16(
210 IDS_EASY_UNLOCK_SETUP_COMPLETE_TRY_IT_OUT_BUTTON_LABEL));
212 "setupCompleteSettingsLinkText",
213 l10n_util::GetStringUTF16(
214 IDS_EASY_UNLOCK_SETUP_COMPLETE_SETTINGS_LINK_TEXT));
218 "setupErrorBluetoothUnavailable",
219 l10n_util::GetStringFUTF16(
220 IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_UNAVAILBLE, device_type));
223 l10n_util::GetStringFUTF16(
224 IDS_EASY_UNLOCK_SETUP_ERROR_OFFLINE, device_type));
226 "setupErrorFindingPhone",
227 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SETUP_ERROR_FINDING_PHONE));
229 "setupErrorBluetoothConnectionFailed",
230 l10n_util::GetStringFUTF16(
231 IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_CONNECTION_FAILED,
234 "setupErrorConnectionToPhoneTimeout",
235 l10n_util::GetStringFUTF16(
236 IDS_EASY_UNLOCK_SETUP_ERROR_CONNECT_TO_PHONE_TIMEOUT,
239 "setupErrorSyncPhoneState",
240 l10n_util::GetStringUTF16(
241 IDS_EASY_UNLOCK_SETUP_ERROR_SYNC_PHONE_STATE_FAILED));
243 "setupErrorConnectingToPhone",
244 l10n_util::GetStringFUTF16(
245 IDS_EASY_UNLOCK_SETUP_ERROR_CONNECTING_TO_PHONE, device_type));
247 // TODO(isherman): Remove this string once the app has been updated.
248 strings->SetString("setupIntroHeaderFootnote", base::string16());
250 SetResult(strings.release());
254 EasyUnlockPrivatePerformECDHKeyAgreementFunction::
255 EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
257 EasyUnlockPrivatePerformECDHKeyAgreementFunction::
258 ~EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
260 bool EasyUnlockPrivatePerformECDHKeyAgreementFunction::RunAsync() {
261 scoped_ptr<easy_unlock_private::PerformECDHKeyAgreement::Params> params =
262 easy_unlock_private::PerformECDHKeyAgreement::Params::Create(*args_);
263 EXTENSION_FUNCTION_VALIDATE(params);
265 GetCryptoDelegate(browser_context())->PerformECDHKeyAgreement(
268 base::Bind(&EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData,
273 void EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData(
274 const std::string& secret_key) {
275 // TODO(tbarzic): Improve error handling.
276 if (!secret_key.empty()) {
277 results_ = easy_unlock_private::PerformECDHKeyAgreement::Results::Create(
283 EasyUnlockPrivateGenerateEcP256KeyPairFunction::
284 EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
286 EasyUnlockPrivateGenerateEcP256KeyPairFunction::
287 ~EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
289 bool EasyUnlockPrivateGenerateEcP256KeyPairFunction::RunAsync() {
290 GetCryptoDelegate(browser_context())->GenerateEcP256KeyPair(
291 base::Bind(&EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData,
296 void EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData(
297 const std::string& private_key,
298 const std::string& public_key) {
299 // TODO(tbarzic): Improve error handling.
300 if (!public_key.empty() && !private_key.empty()) {
301 results_ = easy_unlock_private::GenerateEcP256KeyPair::Results::Create(
302 public_key, private_key);
307 EasyUnlockPrivateCreateSecureMessageFunction::
308 EasyUnlockPrivateCreateSecureMessageFunction() {}
310 EasyUnlockPrivateCreateSecureMessageFunction::
311 ~EasyUnlockPrivateCreateSecureMessageFunction() {}
313 bool EasyUnlockPrivateCreateSecureMessageFunction::RunAsync() {
314 scoped_ptr<easy_unlock_private::CreateSecureMessage::Params> params =
315 easy_unlock_private::CreateSecureMessage::Params::Create(*args_);
316 EXTENSION_FUNCTION_VALIDATE(params);
318 GetCryptoDelegate(browser_context())->CreateSecureMessage(
321 params->options.associated_data ?
322 *params->options.associated_data : std::string(),
323 params->options.public_metadata ?
324 *params->options.public_metadata : std::string(),
325 params->options.verification_key_id ?
326 *params->options.verification_key_id : std::string(),
327 params->options.encrypt_type,
328 params->options.sign_type,
329 base::Bind(&EasyUnlockPrivateCreateSecureMessageFunction::OnData,
334 void EasyUnlockPrivateCreateSecureMessageFunction::OnData(
335 const std::string& message) {
336 // TODO(tbarzic): Improve error handling.
337 if (!message.empty()) {
338 results_ = easy_unlock_private::CreateSecureMessage::Results::Create(
344 EasyUnlockPrivateUnwrapSecureMessageFunction::
345 EasyUnlockPrivateUnwrapSecureMessageFunction() {}
347 EasyUnlockPrivateUnwrapSecureMessageFunction::
348 ~EasyUnlockPrivateUnwrapSecureMessageFunction() {}
350 bool EasyUnlockPrivateUnwrapSecureMessageFunction::RunAsync() {
351 scoped_ptr<easy_unlock_private::UnwrapSecureMessage::Params> params =
352 easy_unlock_private::UnwrapSecureMessage::Params::Create(*args_);
353 EXTENSION_FUNCTION_VALIDATE(params);
355 GetCryptoDelegate(browser_context())->UnwrapSecureMessage(
356 params->secure_message,
358 params->options.associated_data ?
359 *params->options.associated_data : std::string(),
360 params->options.encrypt_type,
361 params->options.sign_type,
362 base::Bind(&EasyUnlockPrivateUnwrapSecureMessageFunction::OnData,
367 void EasyUnlockPrivateUnwrapSecureMessageFunction::OnData(
368 const std::string& data) {
369 // TODO(tbarzic): Improve error handling.
371 results_ = easy_unlock_private::UnwrapSecureMessage::Results::Create(data);
375 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
376 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
378 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
379 ~EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
381 bool EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::RunAsync() {
382 scoped_ptr<easy_unlock_private::SeekBluetoothDeviceByAddress::Params> params(
383 easy_unlock_private::SeekBluetoothDeviceByAddress::Params::Create(
385 EXTENSION_FUNCTION_VALIDATE(params.get());
387 easy_unlock::SeekBluetoothDeviceByAddress(
388 params->device_address,
390 &EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
396 void EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekCompleted(
397 const easy_unlock::SeekDeviceResult& seek_result) {
398 if (seek_result.success) {
401 SetError(seek_result.error_message);
406 EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
407 EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction() {}
409 EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
410 ~EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction() {}
412 void EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
413 ConnectToService(device::BluetoothDevice* device,
414 const device::BluetoothUUID& uuid) {
415 easy_unlock::ConnectToBluetoothServiceInsecurely(
418 base::Bind(&EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
421 base::Bind(&EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
426 EasyUnlockPrivateUpdateScreenlockStateFunction::
427 EasyUnlockPrivateUpdateScreenlockStateFunction() {}
429 EasyUnlockPrivateUpdateScreenlockStateFunction::
430 ~EasyUnlockPrivateUpdateScreenlockStateFunction() {}
432 bool EasyUnlockPrivateUpdateScreenlockStateFunction::RunSync() {
433 scoped_ptr<easy_unlock_private::UpdateScreenlockState::Params> params(
434 easy_unlock_private::UpdateScreenlockState::Params::Create(*args_));
435 EXTENSION_FUNCTION_VALIDATE(params.get());
437 EasyUnlockScreenlockStateHandler* screenlock_state_handler =
438 GetScreenlockStateHandler(browser_context());
439 if (screenlock_state_handler) {
440 screenlock_state_handler->ChangeState(
441 ToScreenlockStateHandlerState(params->state));
445 SetError("Not allowed");
449 EasyUnlockPrivateSetPermitAccessFunction::
450 EasyUnlockPrivateSetPermitAccessFunction() {
453 EasyUnlockPrivateSetPermitAccessFunction::
454 ~EasyUnlockPrivateSetPermitAccessFunction() {
457 bool EasyUnlockPrivateSetPermitAccessFunction::RunSync() {
458 scoped_ptr<easy_unlock_private::SetPermitAccess::Params> params(
459 easy_unlock_private::SetPermitAccess::Params::Create(*args_));
460 EXTENSION_FUNCTION_VALIDATE(params.get());
462 Profile* profile = Profile::FromBrowserContext(browser_context());
463 EasyUnlockService::Get(profile)
464 ->SetPermitAccess(*params->permit_access.ToValue());
469 EasyUnlockPrivateGetPermitAccessFunction::
470 EasyUnlockPrivateGetPermitAccessFunction() {
473 EasyUnlockPrivateGetPermitAccessFunction::
474 ~EasyUnlockPrivateGetPermitAccessFunction() {
477 bool EasyUnlockPrivateGetPermitAccessFunction::RunSync() {
478 Profile* profile = Profile::FromBrowserContext(browser_context());
479 const base::DictionaryValue* permit_value =
480 EasyUnlockService::Get(profile)->GetPermitAccess();
482 scoped_ptr<easy_unlock_private::PermitRecord> permit =
483 easy_unlock_private::PermitRecord::FromValue(*permit_value);
484 results_ = easy_unlock_private::GetPermitAccess::Results::Create(*permit);
490 EasyUnlockPrivateClearPermitAccessFunction::
491 EasyUnlockPrivateClearPermitAccessFunction() {
494 EasyUnlockPrivateClearPermitAccessFunction::
495 ~EasyUnlockPrivateClearPermitAccessFunction() {
498 bool EasyUnlockPrivateClearPermitAccessFunction::RunSync() {
499 Profile* profile = Profile::FromBrowserContext(browser_context());
500 EasyUnlockService::Get(profile)->ClearPermitAccess();
504 EasyUnlockPrivateSetRemoteDevicesFunction::
505 EasyUnlockPrivateSetRemoteDevicesFunction() {
508 EasyUnlockPrivateSetRemoteDevicesFunction::
509 ~EasyUnlockPrivateSetRemoteDevicesFunction() {
512 bool EasyUnlockPrivateSetRemoteDevicesFunction::RunSync() {
513 scoped_ptr<easy_unlock_private::SetRemoteDevices::Params> params(
514 easy_unlock_private::SetRemoteDevices::Params::Create(*args_));
515 EXTENSION_FUNCTION_VALIDATE(params.get());
517 Profile* profile = Profile::FromBrowserContext(browser_context());
518 if (params->devices.empty()) {
519 EasyUnlockService::Get(profile)->ClearRemoteDevices();
521 base::ListValue devices;
522 for (size_t i = 0; i < params->devices.size(); ++i) {
523 devices.Append(params->devices[i]->ToValue().release());
525 EasyUnlockService::Get(profile)->SetRemoteDevices(devices);
531 EasyUnlockPrivateGetRemoteDevicesFunction::
532 EasyUnlockPrivateGetRemoteDevicesFunction() {
535 EasyUnlockPrivateGetRemoteDevicesFunction::
536 ~EasyUnlockPrivateGetRemoteDevicesFunction() {
539 bool EasyUnlockPrivateGetRemoteDevicesFunction::RunSync() {
540 Profile* profile = Profile::FromBrowserContext(browser_context());
541 const base::ListValue* devices =
542 EasyUnlockService::Get(profile)->GetRemoteDevices();
543 SetResult(devices ? devices->DeepCopy() : new base::ListValue());
548 } // namespace extensions