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"
25 namespace extensions {
30 static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI> >
31 g_factory = LAZY_INSTANCE_INITIALIZER;
33 // Utility method for getting the API's crypto delegate.
34 EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate(
35 content::BrowserContext* context) {
36 return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context)
40 EasyUnlockScreenlockStateHandler* GetScreenlockStateHandler(
41 content::BrowserContext* context) {
42 return EasyUnlockService::Get(Profile::FromBrowserContext(context))
43 ->GetScreenlockStateHandler();
46 EasyUnlockScreenlockStateHandler::State ToScreenlockStateHandlerState(
47 easy_unlock_private::State state) {
49 case easy_unlock_private::STATE_NO_BLUETOOTH:
50 return EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH;
51 case easy_unlock_private::STATE_BLUETOOTH_CONNECTING:
52 return EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING;
53 case easy_unlock_private::STATE_NO_PHONE:
54 return EasyUnlockScreenlockStateHandler::STATE_NO_PHONE;
55 case easy_unlock_private::STATE_PHONE_NOT_AUTHENTICATED:
56 return EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED;
57 case easy_unlock_private::STATE_PHONE_LOCKED:
58 return EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED;
59 case easy_unlock_private::STATE_PHONE_UNLOCKABLE:
60 return EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE;
61 case easy_unlock_private::STATE_PHONE_NOT_NEARBY:
62 return EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY;
63 case easy_unlock_private::STATE_AUTHENTICATED:
64 return EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED;
66 return EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
73 BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>*
74 EasyUnlockPrivateAPI::GetFactoryInstance() {
75 return g_factory.Pointer();
78 EasyUnlockPrivateAPI::EasyUnlockPrivateAPI(content::BrowserContext* context)
79 : crypto_delegate_(EasyUnlockPrivateCryptoDelegate::Create()) {
82 EasyUnlockPrivateAPI::~EasyUnlockPrivateAPI() {}
84 EasyUnlockPrivateGetStringsFunction::EasyUnlockPrivateGetStringsFunction() {
86 EasyUnlockPrivateGetStringsFunction::~EasyUnlockPrivateGetStringsFunction() {
89 bool EasyUnlockPrivateGetStringsFunction::RunSync() {
90 scoped_ptr<base::DictionaryValue> strings(new base::DictionaryValue);
92 #if defined(OS_CHROMEOS)
93 const base::string16 device_type = chromeos::GetChromeDeviceType();
95 // TODO(isherman): Set an appropriate device name for non-ChromeOS devices.
96 const base::string16 device_type = base::ASCIIToUTF16("Chromeschnozzle");
97 #endif // defined(OS_CHROMEOS)
101 "learnMoreLinkTitle",
102 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_LEARN_MORE_LINK_TITLE));
104 // Setup notification strings.
106 "setupNotificationTitle",
107 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_TITLE,
110 "setupNotificationMessage",
111 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_MESSAGE,
114 "setupNotificationButtonTitle",
115 l10n_util::GetStringUTF16(
116 IDS_EASY_UNLOCK_SETUP_NOTIFICATION_BUTTON_TITLE));
118 // Success notification strings.
120 "successNotificationTitle",
121 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SUCCESS_NOTIFICATION_TITLE));
123 "successNotificationMessage",
124 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SUCCESS_NOTIFICATION_MESSAGE,
127 // Chromebook added to Easy Unlock notification strings.
129 "chromebookAddedNotificationTitle",
130 l10n_util::GetStringUTF16(
131 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_TITLE));
133 "chromebookAddedNotificationMessage",
134 l10n_util::GetStringFUTF16(
135 IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_MESSAGE,
138 // Setup dialog strings.
141 "setupIntroHeaderTitle",
142 l10n_util::GetStringFUTF16(
143 IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TITLE, device_type));
145 "setupIntroHeaderText",
146 l10n_util::GetStringFUTF16(
147 IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TEXT, device_type));
149 "setupIntroHeaderFootnote",
150 l10n_util::GetStringUTF16(
151 IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_FOOTNOTE));
153 "setupIntroFindPhoneButtonLabel",
154 l10n_util::GetStringUTF16(
155 IDS_EASY_UNLOCK_SETUP_INTRO_FIND_PHONE_BUTTON_LABEL));
157 "setupIntroFindingPhoneButtonLabel",
158 l10n_util::GetStringUTF16(
159 IDS_EASY_UNLOCK_SETUP_INTRO_FINDING_PHONE_BUTTON_LABEL));
161 "setupIntroRetryFindPhoneButtonLabel",
162 l10n_util::GetStringUTF16(
163 IDS_EASY_UNLOCK_SETUP_INTRO_RETRY_FIND_PHONE_BUTTON_LABEL));
165 "setupIntroHowIsThisSecureLinkText",
166 l10n_util::GetStringUTF16(
167 IDS_EASY_UNLOCK_SETUP_INTRO_HOW_IS_THIS_SECURE_LINK_TEXT));
168 // Step 2: Found a viable phone.
170 "setupFoundPhoneHeaderTitle",
171 l10n_util::GetStringFUTF16(
172 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TITLE, device_type));
174 "setupFoundPhoneHeaderText",
175 l10n_util::GetStringFUTF16(
176 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TEXT, device_type));
178 "setupFoundPhoneUseThisPhoneButtonLabel",
179 l10n_util::GetStringUTF16(
180 IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_USE_THIS_PHONE_BUTTON_LABEL));
182 "setupPairingPhoneFailedButtonLabel",
183 l10n_util::GetStringUTF16(
184 IDS_EASY_UNLOCK_SETUP_PAIRING_PHONE_FAILED_BUTTON_LABEL));
185 // Step 3: Setup completed successfully.
187 "setupCompleteHeaderTitle",
188 l10n_util::GetStringUTF16(
189 IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TITLE));
191 "setupCompleteHeaderText",
192 l10n_util::GetStringUTF16(
193 IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TEXT));
195 "setupCompleteTryItOutButtonLabel",
196 l10n_util::GetStringUTF16(
197 IDS_EASY_UNLOCK_SETUP_COMPLETE_TRY_IT_OUT_BUTTON_LABEL));
199 "setupCompleteSettingsLinkText",
200 l10n_util::GetStringUTF16(
201 IDS_EASY_UNLOCK_SETUP_COMPLETE_SETTINGS_LINK_TEXT));
205 "setupErrorBluetoothUnavailable",
206 l10n_util::GetStringFUTF16(
207 IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_UNAVAILBLE, device_type));
210 l10n_util::GetStringFUTF16(
211 IDS_EASY_UNLOCK_SETUP_ERROR_OFFLINE, device_type));
213 "setupErrorFindingPhone",
214 l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SETUP_ERROR_FINDING_PHONE));
216 "setupErrorBluetoothConnectionFailed",
217 l10n_util::GetStringFUTF16(
218 IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_CONNECTION_FAILED,
221 "setupErrorConnectionToPhoneTimeout",
222 l10n_util::GetStringFUTF16(
223 IDS_EASY_UNLOCK_SETUP_ERROR_CONNECT_TO_PHONE_TIMEOUT,
226 "setupErrorSyncPhoneState",
227 l10n_util::GetStringUTF16(
228 IDS_EASY_UNLOCK_SETUP_ERROR_SYNC_PHONE_STATE_FAILED));
230 "setupErrorConnectingToPhone",
231 l10n_util::GetStringFUTF16(
232 IDS_EASY_UNLOCK_SETUP_ERROR_CONNECTING_TO_PHONE, device_type));
234 // TODO(isherman): Remove these strings once the app has been updated.
237 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_TITLE,
240 "notificationMessage",
241 l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_MESSAGE,
244 "notificationButtonTitle",
245 l10n_util::GetStringUTF16(
246 IDS_EASY_UNLOCK_SETUP_NOTIFICATION_BUTTON_TITLE));
248 SetResult(strings.release());
252 EasyUnlockPrivatePerformECDHKeyAgreementFunction::
253 EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
255 EasyUnlockPrivatePerformECDHKeyAgreementFunction::
256 ~EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
258 bool EasyUnlockPrivatePerformECDHKeyAgreementFunction::RunAsync() {
259 scoped_ptr<easy_unlock_private::PerformECDHKeyAgreement::Params> params =
260 easy_unlock_private::PerformECDHKeyAgreement::Params::Create(*args_);
261 EXTENSION_FUNCTION_VALIDATE(params);
263 GetCryptoDelegate(browser_context())->PerformECDHKeyAgreement(
266 base::Bind(&EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData,
271 void EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData(
272 const std::string& secret_key) {
273 // TODO(tbarzic): Improve error handling.
274 if (!secret_key.empty()) {
275 results_ = easy_unlock_private::PerformECDHKeyAgreement::Results::Create(
281 EasyUnlockPrivateGenerateEcP256KeyPairFunction::
282 EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
284 EasyUnlockPrivateGenerateEcP256KeyPairFunction::
285 ~EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
287 bool EasyUnlockPrivateGenerateEcP256KeyPairFunction::RunAsync() {
288 GetCryptoDelegate(browser_context())->GenerateEcP256KeyPair(
289 base::Bind(&EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData,
294 void EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData(
295 const std::string& private_key,
296 const std::string& public_key) {
297 // TODO(tbarzic): Improve error handling.
298 if (!public_key.empty() && !private_key.empty()) {
299 results_ = easy_unlock_private::GenerateEcP256KeyPair::Results::Create(
300 public_key, private_key);
305 EasyUnlockPrivateCreateSecureMessageFunction::
306 EasyUnlockPrivateCreateSecureMessageFunction() {}
308 EasyUnlockPrivateCreateSecureMessageFunction::
309 ~EasyUnlockPrivateCreateSecureMessageFunction() {}
311 bool EasyUnlockPrivateCreateSecureMessageFunction::RunAsync() {
312 scoped_ptr<easy_unlock_private::CreateSecureMessage::Params> params =
313 easy_unlock_private::CreateSecureMessage::Params::Create(*args_);
314 EXTENSION_FUNCTION_VALIDATE(params);
316 GetCryptoDelegate(browser_context())->CreateSecureMessage(
319 params->options.associated_data ?
320 *params->options.associated_data : std::string(),
321 params->options.public_metadata ?
322 *params->options.public_metadata : std::string(),
323 params->options.verification_key_id ?
324 *params->options.verification_key_id : std::string(),
325 params->options.encrypt_type,
326 params->options.sign_type,
327 base::Bind(&EasyUnlockPrivateCreateSecureMessageFunction::OnData,
332 void EasyUnlockPrivateCreateSecureMessageFunction::OnData(
333 const std::string& message) {
334 // TODO(tbarzic): Improve error handling.
335 if (!message.empty()) {
336 results_ = easy_unlock_private::CreateSecureMessage::Results::Create(
342 EasyUnlockPrivateUnwrapSecureMessageFunction::
343 EasyUnlockPrivateUnwrapSecureMessageFunction() {}
345 EasyUnlockPrivateUnwrapSecureMessageFunction::
346 ~EasyUnlockPrivateUnwrapSecureMessageFunction() {}
348 bool EasyUnlockPrivateUnwrapSecureMessageFunction::RunAsync() {
349 scoped_ptr<easy_unlock_private::UnwrapSecureMessage::Params> params =
350 easy_unlock_private::UnwrapSecureMessage::Params::Create(*args_);
351 EXTENSION_FUNCTION_VALIDATE(params);
353 GetCryptoDelegate(browser_context())->UnwrapSecureMessage(
354 params->secure_message,
356 params->options.associated_data ?
357 *params->options.associated_data : std::string(),
358 params->options.encrypt_type,
359 params->options.sign_type,
360 base::Bind(&EasyUnlockPrivateUnwrapSecureMessageFunction::OnData,
365 void EasyUnlockPrivateUnwrapSecureMessageFunction::OnData(
366 const std::string& data) {
367 // TODO(tbarzic): Improve error handling.
369 results_ = easy_unlock_private::UnwrapSecureMessage::Results::Create(data);
373 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
374 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
376 EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
377 ~EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
379 bool EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::RunAsync() {
380 scoped_ptr<easy_unlock_private::SeekBluetoothDeviceByAddress::Params> params(
381 easy_unlock_private::SeekBluetoothDeviceByAddress::Params::Create(
383 EXTENSION_FUNCTION_VALIDATE(params.get());
385 easy_unlock::SeekBluetoothDeviceByAddress(
386 params->device_address,
388 &EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
394 void EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekCompleted(
395 const easy_unlock::SeekDeviceResult& seek_result) {
396 if (seek_result.success) {
399 SetError(seek_result.error_message);
404 EasyUnlockPrivateUpdateScreenlockStateFunction::
405 EasyUnlockPrivateUpdateScreenlockStateFunction() {}
407 EasyUnlockPrivateUpdateScreenlockStateFunction::
408 ~EasyUnlockPrivateUpdateScreenlockStateFunction() {}
410 bool EasyUnlockPrivateUpdateScreenlockStateFunction::RunSync() {
411 scoped_ptr<easy_unlock_private::UpdateScreenlockState::Params> params(
412 easy_unlock_private::UpdateScreenlockState::Params::Create(*args_));
413 EXTENSION_FUNCTION_VALIDATE(params.get());
415 EasyUnlockScreenlockStateHandler* screenlock_state_handler =
416 GetScreenlockStateHandler(browser_context());
417 if (screenlock_state_handler) {
418 screenlock_state_handler->ChangeState(
419 ToScreenlockStateHandlerState(params->state));
423 SetError("Not allowed");
427 EasyUnlockPrivateSetPermitAccessFunction::
428 EasyUnlockPrivateSetPermitAccessFunction() {
431 EasyUnlockPrivateSetPermitAccessFunction::
432 ~EasyUnlockPrivateSetPermitAccessFunction() {
435 bool EasyUnlockPrivateSetPermitAccessFunction::RunSync() {
436 scoped_ptr<easy_unlock_private::SetPermitAccess::Params> params(
437 easy_unlock_private::SetPermitAccess::Params::Create(*args_));
438 EXTENSION_FUNCTION_VALIDATE(params.get());
440 Profile* profile = Profile::FromBrowserContext(browser_context());
441 EasyUnlockService::Get(profile)
442 ->SetPermitAccess(*params->permit_access.ToValue());
447 EasyUnlockPrivateGetPermitAccessFunction::
448 EasyUnlockPrivateGetPermitAccessFunction() {
451 EasyUnlockPrivateGetPermitAccessFunction::
452 ~EasyUnlockPrivateGetPermitAccessFunction() {
455 bool EasyUnlockPrivateGetPermitAccessFunction::RunSync() {
456 Profile* profile = Profile::FromBrowserContext(browser_context());
457 const base::DictionaryValue* permit_value =
458 EasyUnlockService::Get(profile)->GetPermitAccess();
460 scoped_ptr<easy_unlock_private::PermitRecord> permit =
461 easy_unlock_private::PermitRecord::FromValue(*permit_value);
462 results_ = easy_unlock_private::GetPermitAccess::Results::Create(*permit);
468 EasyUnlockPrivateClearPermitAccessFunction::
469 EasyUnlockPrivateClearPermitAccessFunction() {
472 EasyUnlockPrivateClearPermitAccessFunction::
473 ~EasyUnlockPrivateClearPermitAccessFunction() {
476 bool EasyUnlockPrivateClearPermitAccessFunction::RunSync() {
477 Profile* profile = Profile::FromBrowserContext(browser_context());
478 EasyUnlockService::Get(profile)->ClearPermitAccess();
482 EasyUnlockPrivateSetRemoteDevicesFunction::
483 EasyUnlockPrivateSetRemoteDevicesFunction() {
486 EasyUnlockPrivateSetRemoteDevicesFunction::
487 ~EasyUnlockPrivateSetRemoteDevicesFunction() {
490 bool EasyUnlockPrivateSetRemoteDevicesFunction::RunSync() {
491 scoped_ptr<easy_unlock_private::SetRemoteDevices::Params> params(
492 easy_unlock_private::SetRemoteDevices::Params::Create(*args_));
493 EXTENSION_FUNCTION_VALIDATE(params.get());
495 Profile* profile = Profile::FromBrowserContext(browser_context());
496 if (params->devices.empty()) {
497 EasyUnlockService::Get(profile)->ClearRemoteDevices();
499 base::ListValue devices;
500 for (size_t i = 0; i < params->devices.size(); ++i) {
501 devices.Append(params->devices[i]->ToValue().release());
503 EasyUnlockService::Get(profile)->SetRemoteDevices(devices);
509 EasyUnlockPrivateGetRemoteDevicesFunction::
510 EasyUnlockPrivateGetRemoteDevicesFunction() {
513 EasyUnlockPrivateGetRemoteDevicesFunction::
514 ~EasyUnlockPrivateGetRemoteDevicesFunction() {
517 bool EasyUnlockPrivateGetRemoteDevicesFunction::RunSync() {
518 Profile* profile = Profile::FromBrowserContext(browser_context());
519 const base::ListValue* devices =
520 EasyUnlockService::Get(profile)->GetRemoteDevices();
521 SetResult(devices ? devices->DeepCopy() : new base::ListValue());
526 } // namespace extensions