blob: efd7f88b5d56039592778eb8167259675dfd9bdc [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h"
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_bluetooth_util.h"
#include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_crypto_delegate.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/easy_unlock_screenlock_state_handler.h"
#include "chrome/browser/signin/easy_unlock_service.h"
#include "chrome/common/extensions/api/easy_unlock_private.h"
#include "extensions/browser/browser_context_keyed_api_factory.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#if defined(OS_CHROMEOS)
#include "chrome/browser/chromeos/chromeos_utils.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#endif
namespace extensions {
namespace api {
namespace {
static base::LazyInstance<BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI> >
g_factory = LAZY_INSTANCE_INITIALIZER;
// Utility method for getting the API's crypto delegate.
EasyUnlockPrivateCryptoDelegate* GetCryptoDelegate(
content::BrowserContext* context) {
return BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>::Get(context)
->crypto_delegate();
}
EasyUnlockScreenlockStateHandler* GetScreenlockStateHandler(
content::BrowserContext* context) {
return EasyUnlockService::Get(Profile::FromBrowserContext(context))
->GetScreenlockStateHandler();
}
EasyUnlockScreenlockStateHandler::State ToScreenlockStateHandlerState(
easy_unlock_private::State state) {
switch (state) {
case easy_unlock_private::STATE_NO_BLUETOOTH:
return EasyUnlockScreenlockStateHandler::STATE_NO_BLUETOOTH;
case easy_unlock_private::STATE_BLUETOOTH_CONNECTING:
return EasyUnlockScreenlockStateHandler::STATE_BLUETOOTH_CONNECTING;
case easy_unlock_private::STATE_NO_PHONE:
return EasyUnlockScreenlockStateHandler::STATE_NO_PHONE;
case easy_unlock_private::STATE_PHONE_NOT_AUTHENTICATED:
return EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_AUTHENTICATED;
case easy_unlock_private::STATE_PHONE_LOCKED:
return EasyUnlockScreenlockStateHandler::STATE_PHONE_LOCKED;
case easy_unlock_private::STATE_PHONE_UNLOCKABLE:
return EasyUnlockScreenlockStateHandler::STATE_PHONE_UNLOCKABLE;
case easy_unlock_private::STATE_PHONE_NOT_NEARBY:
return EasyUnlockScreenlockStateHandler::STATE_PHONE_NOT_NEARBY;
case easy_unlock_private::STATE_PHONE_UNSUPPORTED:
return EasyUnlockScreenlockStateHandler::STATE_PHONE_UNSUPPORTED;
case easy_unlock_private::STATE_AUTHENTICATED:
return EasyUnlockScreenlockStateHandler::STATE_AUTHENTICATED;
default:
return EasyUnlockScreenlockStateHandler::STATE_INACTIVE;
}
}
} // namespace
// static
BrowserContextKeyedAPIFactory<EasyUnlockPrivateAPI>*
EasyUnlockPrivateAPI::GetFactoryInstance() {
return g_factory.Pointer();
}
EasyUnlockPrivateAPI::EasyUnlockPrivateAPI(content::BrowserContext* context)
: crypto_delegate_(EasyUnlockPrivateCryptoDelegate::Create()) {
}
EasyUnlockPrivateAPI::~EasyUnlockPrivateAPI() {}
EasyUnlockPrivateGetStringsFunction::EasyUnlockPrivateGetStringsFunction() {
}
EasyUnlockPrivateGetStringsFunction::~EasyUnlockPrivateGetStringsFunction() {
}
bool EasyUnlockPrivateGetStringsFunction::RunSync() {
scoped_ptr<base::DictionaryValue> strings(new base::DictionaryValue);
#if defined(OS_CHROMEOS)
const base::string16 device_type = chromeos::GetChromeDeviceType();
#else
// TODO(isherman): Set an appropriate device name for non-ChromeOS devices.
const base::string16 device_type = base::ASCIIToUTF16("Chromeschnozzle");
#endif // defined(OS_CHROMEOS)
#if defined(OS_CHROMEOS)
const user_manager::UserManager* manager = user_manager::UserManager::Get();
const user_manager::User* user = manager ? manager->GetActiveUser() : NULL;
const std::string user_email_utf8 =
user ? user->display_email() : std::string();
const base::string16 user_email = base::UTF8ToUTF16(user_email_utf8);
#else
// TODO(isherman): Set an appropriate user display email for non-ChromeOS
// platforms.
const base::string16 user_email = base::UTF8ToUTF16("superman@example.com");
#endif // defined(OS_CHROMEOS)
// Common strings.
strings->SetString(
"learnMoreLinkTitle",
l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_LEARN_MORE_LINK_TITLE));
// Setup notification strings.
strings->SetString(
"setupNotificationTitle",
l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_TITLE,
device_type));
strings->SetString(
"setupNotificationMessage",
l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_NOTIFICATION_MESSAGE,
device_type));
strings->SetString(
"setupNotificationButtonTitle",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_NOTIFICATION_BUTTON_TITLE));
// Success notification strings.
strings->SetString(
"successNotificationTitle",
l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SUCCESS_NOTIFICATION_TITLE));
strings->SetString(
"successNotificationMessage",
l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SUCCESS_NOTIFICATION_MESSAGE,
device_type));
// Chromebook added to Easy Unlock notification strings.
strings->SetString(
"chromebookAddedNotificationTitle",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_TITLE));
strings->SetString(
"chromebookAddedNotificationMessage",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_CHROMEBOOK_ADDED_NOTIFICATION_MESSAGE,
device_type));
// Setup dialog strings.
// Step 1: Intro.
strings->SetString(
"setupIntroHeaderTitle",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TITLE, device_type));
strings->SetString(
"setupIntroHeaderText",
l10n_util::GetStringFUTF16(IDS_EASY_UNLOCK_SETUP_INTRO_HEADER_TEXT,
device_type,
user_email));
strings->SetString(
"setupIntroFindPhoneButtonLabel",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_INTRO_FIND_PHONE_BUTTON_LABEL));
strings->SetString(
"setupIntroFindingPhoneButtonLabel",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_INTRO_FINDING_PHONE_BUTTON_LABEL));
strings->SetString(
"setupIntroRetryFindPhoneButtonLabel",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_INTRO_RETRY_FIND_PHONE_BUTTON_LABEL));
strings->SetString(
"setupIntroHowIsThisSecureLinkText",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_INTRO_HOW_IS_THIS_SECURE_LINK_TEXT));
// Step 2: Found a viable phone.
strings->SetString(
"setupFoundPhoneHeaderTitle",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TITLE, device_type));
strings->SetString(
"setupFoundPhoneHeaderText",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_HEADER_TEXT, device_type));
strings->SetString(
"setupFoundPhoneUseThisPhoneButtonLabel",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_FOUND_PHONE_USE_THIS_PHONE_BUTTON_LABEL));
strings->SetString(
"setupPairingPhoneFailedButtonLabel",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_PAIRING_PHONE_FAILED_BUTTON_LABEL));
// Step 3: Setup completed successfully.
strings->SetString(
"setupCompleteHeaderTitle",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TITLE));
strings->SetString(
"setupCompleteHeaderText",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_COMPLETE_HEADER_TEXT));
strings->SetString(
"setupCompleteTryItOutButtonLabel",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_COMPLETE_TRY_IT_OUT_BUTTON_LABEL));
strings->SetString(
"setupCompleteSettingsLinkText",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_COMPLETE_SETTINGS_LINK_TEXT));
// Error strings.
strings->SetString(
"setupErrorBluetoothUnavailable",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_UNAVAILBLE, device_type));
strings->SetString(
"setupErrorOffline",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_ERROR_OFFLINE, device_type));
strings->SetString(
"setupErrorFindingPhone",
l10n_util::GetStringUTF16(IDS_EASY_UNLOCK_SETUP_ERROR_FINDING_PHONE));
strings->SetString(
"setupErrorBluetoothConnectionFailed",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_ERROR_BLUETOOTH_CONNECTION_FAILED,
device_type));
strings->SetString(
"setupErrorConnectionToPhoneTimeout",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_ERROR_CONNECT_TO_PHONE_TIMEOUT,
device_type));
strings->SetString(
"setupErrorSyncPhoneState",
l10n_util::GetStringUTF16(
IDS_EASY_UNLOCK_SETUP_ERROR_SYNC_PHONE_STATE_FAILED));
strings->SetString(
"setupErrorConnectingToPhone",
l10n_util::GetStringFUTF16(
IDS_EASY_UNLOCK_SETUP_ERROR_CONNECTING_TO_PHONE, device_type));
// TODO(isherman): Remove this string once the app has been updated.
strings->SetString("setupIntroHeaderFootnote", base::string16());
SetResult(strings.release());
return true;
}
EasyUnlockPrivatePerformECDHKeyAgreementFunction::
EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
EasyUnlockPrivatePerformECDHKeyAgreementFunction::
~EasyUnlockPrivatePerformECDHKeyAgreementFunction() {}
bool EasyUnlockPrivatePerformECDHKeyAgreementFunction::RunAsync() {
scoped_ptr<easy_unlock_private::PerformECDHKeyAgreement::Params> params =
easy_unlock_private::PerformECDHKeyAgreement::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
GetCryptoDelegate(browser_context())->PerformECDHKeyAgreement(
params->private_key,
params->public_key,
base::Bind(&EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData,
this));
return true;
}
void EasyUnlockPrivatePerformECDHKeyAgreementFunction::OnData(
const std::string& secret_key) {
// TODO(tbarzic): Improve error handling.
if (!secret_key.empty()) {
results_ = easy_unlock_private::PerformECDHKeyAgreement::Results::Create(
secret_key);
}
SendResponse(true);
}
EasyUnlockPrivateGenerateEcP256KeyPairFunction::
EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
EasyUnlockPrivateGenerateEcP256KeyPairFunction::
~EasyUnlockPrivateGenerateEcP256KeyPairFunction() {}
bool EasyUnlockPrivateGenerateEcP256KeyPairFunction::RunAsync() {
GetCryptoDelegate(browser_context())->GenerateEcP256KeyPair(
base::Bind(&EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData,
this));
return true;
}
void EasyUnlockPrivateGenerateEcP256KeyPairFunction::OnData(
const std::string& private_key,
const std::string& public_key) {
// TODO(tbarzic): Improve error handling.
if (!public_key.empty() && !private_key.empty()) {
results_ = easy_unlock_private::GenerateEcP256KeyPair::Results::Create(
public_key, private_key);
}
SendResponse(true);
}
EasyUnlockPrivateCreateSecureMessageFunction::
EasyUnlockPrivateCreateSecureMessageFunction() {}
EasyUnlockPrivateCreateSecureMessageFunction::
~EasyUnlockPrivateCreateSecureMessageFunction() {}
bool EasyUnlockPrivateCreateSecureMessageFunction::RunAsync() {
scoped_ptr<easy_unlock_private::CreateSecureMessage::Params> params =
easy_unlock_private::CreateSecureMessage::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
GetCryptoDelegate(browser_context())->CreateSecureMessage(
params->payload,
params->key,
params->options.associated_data ?
*params->options.associated_data : std::string(),
params->options.public_metadata ?
*params->options.public_metadata : std::string(),
params->options.verification_key_id ?
*params->options.verification_key_id : std::string(),
params->options.encrypt_type,
params->options.sign_type,
base::Bind(&EasyUnlockPrivateCreateSecureMessageFunction::OnData,
this));
return true;
}
void EasyUnlockPrivateCreateSecureMessageFunction::OnData(
const std::string& message) {
// TODO(tbarzic): Improve error handling.
if (!message.empty()) {
results_ = easy_unlock_private::CreateSecureMessage::Results::Create(
message);
}
SendResponse(true);
}
EasyUnlockPrivateUnwrapSecureMessageFunction::
EasyUnlockPrivateUnwrapSecureMessageFunction() {}
EasyUnlockPrivateUnwrapSecureMessageFunction::
~EasyUnlockPrivateUnwrapSecureMessageFunction() {}
bool EasyUnlockPrivateUnwrapSecureMessageFunction::RunAsync() {
scoped_ptr<easy_unlock_private::UnwrapSecureMessage::Params> params =
easy_unlock_private::UnwrapSecureMessage::Params::Create(*args_);
EXTENSION_FUNCTION_VALIDATE(params);
GetCryptoDelegate(browser_context())->UnwrapSecureMessage(
params->secure_message,
params->key,
params->options.associated_data ?
*params->options.associated_data : std::string(),
params->options.encrypt_type,
params->options.sign_type,
base::Bind(&EasyUnlockPrivateUnwrapSecureMessageFunction::OnData,
this));
return true;
}
void EasyUnlockPrivateUnwrapSecureMessageFunction::OnData(
const std::string& data) {
// TODO(tbarzic): Improve error handling.
if (!data.empty())
results_ = easy_unlock_private::UnwrapSecureMessage::Results::Create(data);
SendResponse(true);
}
EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
~EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction() {}
bool EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::RunAsync() {
scoped_ptr<easy_unlock_private::SeekBluetoothDeviceByAddress::Params> params(
easy_unlock_private::SeekBluetoothDeviceByAddress::Params::Create(
*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
easy_unlock::SeekBluetoothDeviceByAddress(
params->device_address,
base::Bind(
&EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::
OnSeekCompleted,
this));
return true;
}
void EasyUnlockPrivateSeekBluetoothDeviceByAddressFunction::OnSeekCompleted(
const easy_unlock::SeekDeviceResult& seek_result) {
if (seek_result.success) {
SendResponse(true);
} else {
SetError(seek_result.error_message);
SendResponse(false);
}
}
EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction() {}
EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
~EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction() {}
void EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
ConnectToService(device::BluetoothDevice* device,
const device::BluetoothUUID& uuid) {
easy_unlock::ConnectToBluetoothServiceInsecurely(
device,
uuid,
base::Bind(&EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
OnConnect,
this),
base::Bind(&EasyUnlockPrivateConnectToBluetoothServiceInsecurelyFunction::
OnConnectError,
this));
}
EasyUnlockPrivateUpdateScreenlockStateFunction::
EasyUnlockPrivateUpdateScreenlockStateFunction() {}
EasyUnlockPrivateUpdateScreenlockStateFunction::
~EasyUnlockPrivateUpdateScreenlockStateFunction() {}
bool EasyUnlockPrivateUpdateScreenlockStateFunction::RunSync() {
scoped_ptr<easy_unlock_private::UpdateScreenlockState::Params> params(
easy_unlock_private::UpdateScreenlockState::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
EasyUnlockScreenlockStateHandler* screenlock_state_handler =
GetScreenlockStateHandler(browser_context());
if (screenlock_state_handler) {
screenlock_state_handler->ChangeState(
ToScreenlockStateHandlerState(params->state));
return true;
}
SetError("Not allowed");
return false;
}
EasyUnlockPrivateSetPermitAccessFunction::
EasyUnlockPrivateSetPermitAccessFunction() {
}
EasyUnlockPrivateSetPermitAccessFunction::
~EasyUnlockPrivateSetPermitAccessFunction() {
}
bool EasyUnlockPrivateSetPermitAccessFunction::RunSync() {
scoped_ptr<easy_unlock_private::SetPermitAccess::Params> params(
easy_unlock_private::SetPermitAccess::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
Profile* profile = Profile::FromBrowserContext(browser_context());
EasyUnlockService::Get(profile)
->SetPermitAccess(*params->permit_access.ToValue());
return true;
}
EasyUnlockPrivateGetPermitAccessFunction::
EasyUnlockPrivateGetPermitAccessFunction() {
}
EasyUnlockPrivateGetPermitAccessFunction::
~EasyUnlockPrivateGetPermitAccessFunction() {
}
bool EasyUnlockPrivateGetPermitAccessFunction::RunSync() {
Profile* profile = Profile::FromBrowserContext(browser_context());
const base::DictionaryValue* permit_value =
EasyUnlockService::Get(profile)->GetPermitAccess();
if (permit_value) {
scoped_ptr<easy_unlock_private::PermitRecord> permit =
easy_unlock_private::PermitRecord::FromValue(*permit_value);
results_ = easy_unlock_private::GetPermitAccess::Results::Create(*permit);
}
return true;
}
EasyUnlockPrivateClearPermitAccessFunction::
EasyUnlockPrivateClearPermitAccessFunction() {
}
EasyUnlockPrivateClearPermitAccessFunction::
~EasyUnlockPrivateClearPermitAccessFunction() {
}
bool EasyUnlockPrivateClearPermitAccessFunction::RunSync() {
Profile* profile = Profile::FromBrowserContext(browser_context());
EasyUnlockService::Get(profile)->ClearPermitAccess();
return true;
}
EasyUnlockPrivateSetRemoteDevicesFunction::
EasyUnlockPrivateSetRemoteDevicesFunction() {
}
EasyUnlockPrivateSetRemoteDevicesFunction::
~EasyUnlockPrivateSetRemoteDevicesFunction() {
}
bool EasyUnlockPrivateSetRemoteDevicesFunction::RunSync() {
scoped_ptr<easy_unlock_private::SetRemoteDevices::Params> params(
easy_unlock_private::SetRemoteDevices::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());
Profile* profile = Profile::FromBrowserContext(browser_context());
if (params->devices.empty()) {
EasyUnlockService::Get(profile)->ClearRemoteDevices();
} else {
base::ListValue devices;
for (size_t i = 0; i < params->devices.size(); ++i) {
devices.Append(params->devices[i]->ToValue().release());
}
EasyUnlockService::Get(profile)->SetRemoteDevices(devices);
}
return true;
}
EasyUnlockPrivateGetRemoteDevicesFunction::
EasyUnlockPrivateGetRemoteDevicesFunction() {
}
EasyUnlockPrivateGetRemoteDevicesFunction::
~EasyUnlockPrivateGetRemoteDevicesFunction() {
}
bool EasyUnlockPrivateGetRemoteDevicesFunction::RunSync() {
Profile* profile = Profile::FromBrowserContext(browser_context());
const base::ListValue* devices =
EasyUnlockService::Get(profile)->GetRemoteDevices();
SetResult(devices ? devices->DeepCopy() : new base::ListValue());
return true;
}
} // namespace api
} // namespace extensions