diff options
author | tengs <tengs@chromium.org> | 2015-08-06 10:48:21 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-06 17:48:54 +0000 |
commit | 2c23a9b29316138854f380210e318b76e3d4f759 (patch) | |
tree | 2269cd8f9c4ffef8a27c264a12e81fe7bc389bbd /components/proximity_auth | |
parent | 2a468782399cbbf81d9b9cfb52dd8bb407005c7f (diff) | |
download | chromium_src-2c23a9b29316138854f380210e318b76e3d4f759.zip chromium_src-2c23a9b29316138854f380210e318b76e3d4f759.tar.gz chromium_src-2c23a9b29316138854f380210e318b76e3d4f759.tar.bz2 |
Add toggling devices as unlock keys to chrome://proximity-auth.
To receive GCM messages from CryptAuth, this CL also sets the
device_software_package field to the same as the GCM app id during enrollment.
BUG=409158
TEST=manual
Review URL: https://codereview.chromium.org/1252323008
Cr-Commit-Position: refs/heads/master@{#342143}
Diffstat (limited to 'components/proximity_auth')
8 files changed, 207 insertions, 9 deletions
diff --git a/components/proximity_auth/cryptauth/cryptauth_device_manager.cc b/components/proximity_auth/cryptauth/cryptauth_device_manager.cc index 3e641bb..a7e11ac 100644 --- a/components/proximity_auth/cryptauth/cryptauth_device_manager.cc +++ b/components/proximity_auth/cryptauth/cryptauth_device_manager.cc @@ -170,10 +170,13 @@ void CryptAuthDeviceManager::OnGetMyDevicesSuccess( const cryptauth::GetMyDevicesResponse& response) { // Update the unlock keys stored in the user's prefs. scoped_ptr<base::ListValue> unlock_keys_pref(new base::ListValue()); + scoped_ptr<base::ListValue> devices_as_list(new base::ListValue()); for (const auto& device : response.devices()) { + devices_as_list->Append(UnlockKeyToDictionary(device)); if (device.unlock_key()) unlock_keys_pref->Append(UnlockKeyToDictionary(device)); } + PA_LOG(INFO) << "Devices Synced:\n" << *devices_as_list; bool unlock_keys_changed = !unlock_keys_pref->Equals( pref_service_->GetList(prefs::kCryptAuthDeviceSyncUnlockKeys)); diff --git a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc index 6c08073..888572e5 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager.cc @@ -8,6 +8,7 @@ #include "base/prefs/pref_service.h" #include "base/time/clock.h" #include "base/time/time.h" +#include "components/proximity_auth/cryptauth/base64url.h" #include "components/proximity_auth/cryptauth/cryptauth_enroller.h" #include "components/proximity_auth/cryptauth/pref_names.h" #include "components/proximity_auth/cryptauth/secure_message_delegate.h" @@ -33,6 +34,11 @@ const int kEnrollmentBaseRecoveryPeriodMinutes = 10; // The bound on the amount to jitter the period between enrollments. const double kEnrollmentMaxJitterRatio = 0.2; +// The value of the device_software_package field in the device info uploaded +// during enrollment. This value must be the same as the app id used for GCM +// registration. +const char kDeviceSoftwarePackage[] = "com.google.chrome.cryptauth"; + } // namespace CryptAuthEnrollmentManager::CryptAuthEnrollmentManager( @@ -176,7 +182,9 @@ void CryptAuthEnrollmentManager::OnSyncRequested( sync_request_ = sync_request.Pass(); - if (gcm_manager_->GetRegistrationId().empty()) { + if (gcm_manager_->GetRegistrationId().empty() || + pref_service_->GetInteger(prefs::kCryptAuthEnrollmentReason) == + cryptauth::INVOCATION_REASON_MANUAL) { gcm_manager_->RegisterWithGCM(); } else { DoCryptAuthEnrollment(); @@ -207,10 +215,23 @@ void CryptAuthEnrollmentManager::DoCryptAuthEnrollment() { invocation_reason = cryptauth::INVOCATION_REASON_FAILURE_RECOVERY; } - PA_LOG(INFO) << "Making enrollment with reason: " << invocation_reason; + // Fill in the current GCM registration id before enrolling, and explicitly + // make sure that the software package is the same as the GCM app id. + cryptauth::GcmDeviceInfo device_info(device_info_); + device_info.set_gcm_registration_id(gcm_manager_->GetRegistrationId()); + device_info.set_device_software_package(kDeviceSoftwarePackage); + + std::string public_key_b64; + Base64UrlEncode(user_public_key_, &public_key_b64); + PA_LOG(INFO) << "Making enrollment:\n" + << " public_key: " << public_key_b64 << "\n" + << " invocation_reason: " << invocation_reason << "\n" + << " gcm_registration_id: " + << device_info.gcm_registration_id(); + cryptauth_enroller_ = enroller_factory_->CreateInstance(); cryptauth_enroller_->Enroll( - user_public_key_, user_private_key_, device_info_, invocation_reason, + user_public_key_, user_private_key_, device_info, invocation_reason, base::Bind(&CryptAuthEnrollmentManager::OnEnrollmentFinished, weak_ptr_factory_.GetWeakPtr())); } diff --git a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc index f06a4df..33336ac 100644 --- a/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc +++ b/components/proximity_auth/cryptauth/cryptauth_enrollment_manager_unittest.cc @@ -339,10 +339,11 @@ TEST_F(ProximityAuthCryptAuthEnrollmentManagerTest, ForceEnrollment) { enrollment_manager_.Start(); EXPECT_CALL(*sync_scheduler(), ForceSync()); - enrollment_manager_.ForceEnrollmentNow(cryptauth::INVOCATION_REASON_MANUAL); + enrollment_manager_.ForceEnrollmentNow( + cryptauth::INVOCATION_REASON_SERVER_INITIATED); auto completion_callback = - FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_MANUAL); + FireSchedulerForEnrollment(cryptauth::INVOCATION_REASON_SERVER_INITIATED); clock_->SetNow(base::Time::FromDoubleT(kLaterTimeNow)); EXPECT_CALL(*this, OnEnrollmentFinishedProxy(true)); diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/components/proximity_auth/webui/proximity_auth_webui_handler.cc index a1a1319..a63671c 100644 --- a/components/proximity_auth/webui/proximity_auth_webui_handler.cc +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.cc @@ -124,6 +124,10 @@ void ProximityAuthWebUIHandler::RegisterMessages() { base::Unretained(this))); web_ui()->RegisterMessageCallback( + "toggleUnlockKey", base::Bind(&ProximityAuthWebUIHandler::ToggleUnlockKey, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( "findEligibleUnlockDevices", base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices, base::Unretained(this))); @@ -150,10 +154,10 @@ void ProximityAuthWebUIHandler::RegisterMessages() { base::Bind(&ProximityAuthWebUIHandler::ToggleConnection, base::Unretained(this))); + LogBuffer::GetInstance()->AddObserver(this); InitGCMManager(); InitEnrollmentManager(); InitDeviceManager(); - LogBuffer::GetInstance()->AddObserver(this); } void ProximityAuthWebUIHandler::OnLogMessageAdded( @@ -224,6 +228,32 @@ void ProximityAuthWebUIHandler::ClearLogBuffer(const base::ListValue* args) { LogBuffer::GetInstance()->Clear(); } +void ProximityAuthWebUIHandler::ToggleUnlockKey(const base::ListValue* args) { + std::string public_key_b64, public_key; + bool make_unlock_key; + if (args->GetSize() != 2 || !args->GetString(0, &public_key_b64) || + !args->GetBoolean(1, &make_unlock_key) || + !Base64UrlDecode(public_key_b64, &public_key)) { + PA_LOG(ERROR) << "Invalid arguments to toggleUnlockKey"; + return; + } + + cryptauth::ToggleEasyUnlockRequest request; + request.set_enable(make_unlock_key); + request.set_public_key(public_key); + *(request.mutable_device_classifier()) = delegate_->GetDeviceClassifier(); + + PA_LOG(INFO) << "Toggling unlock key:\n" + << " public_key: " << public_key_b64 << "\n" + << " make_unlock_key: " << make_unlock_key; + cryptauth_client_ = cryptauth_client_factory_->CreateInstance(); + cryptauth_client_->ToggleEasyUnlock( + request, base::Bind(&ProximityAuthWebUIHandler::OnEasyUnlockToggled, + weak_ptr_factory_.GetWeakPtr()), + base::Bind(&ProximityAuthWebUIHandler::OnCryptAuthClientError, + weak_ptr_factory_.GetWeakPtr())); +} + void ProximityAuthWebUIHandler::FindEligibleUnlockDevices( const base::ListValue* args) { cryptauth_client_ = cryptauth_client_factory_->CreateInstance(); @@ -305,6 +335,7 @@ void ProximityAuthWebUIHandler::ToggleConnection(const base::ListValue* args) { void ProximityAuthWebUIHandler::InitGCMManager() { gcm_manager_.reset(new CryptAuthGCMManagerImpl(delegate_->GetGCMDriver(), delegate_->GetPrefService())); + gcm_manager_->StartListening(); } void ProximityAuthWebUIHandler::InitEnrollmentManager() { @@ -384,6 +415,12 @@ void ProximityAuthWebUIHandler::OnCryptAuthClientError( web_ui()->CallJavascriptFunction("CryptAuthInterface.onError", error_string); } +void ProximityAuthWebUIHandler::OnEasyUnlockToggled( + const cryptauth::ToggleEasyUnlockResponse& response) { + web_ui()->CallJavascriptFunction("CryptAuthInterface.onUnlockKeyToggled"); + // TODO(tengs): Update the local state to reflect the toggle. +} + void ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices( const cryptauth::FindEligibleUnlockDevicesResponse& response) { base::ListValue eligible_devices; diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.h b/components/proximity_auth/webui/proximity_auth_webui_handler.h index d0e8907..4de4abf 100644 --- a/components/proximity_auth/webui/proximity_auth_webui_handler.h +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.h @@ -69,6 +69,7 @@ class ProximityAuthWebUIHandler : public content::WebUIMessageHandler, // Message handler callbacks. void GetLogMessages(const base::ListValue* args); void ClearLogBuffer(const base::ListValue* args); + void ToggleUnlockKey(const base::ListValue* args); void FindEligibleUnlockDevices(const base::ListValue* args); void FindReachableDevices(const base::ListValue* args); void GetLocalState(const base::ListValue* args); @@ -84,6 +85,9 @@ class ProximityAuthWebUIHandler : public content::WebUIMessageHandler, // Called when a CryptAuth request fails. void OnCryptAuthClientError(const std::string& error_message); + // Called when the toggleUnlock request succeeds. + void OnEasyUnlockToggled(const cryptauth::ToggleEasyUnlockResponse& response); + // Called when the findEligibleUnlockDevices request succeeds. void OnFoundEligibleUnlockDevices( const cryptauth::FindEligibleUnlockDevicesResponse& response); diff --git a/components/proximity_auth/webui/resources/cryptauth_interface.js b/components/proximity_auth/webui/resources/cryptauth_interface.js index c4a460c..4e22c38 100644 --- a/components/proximity_auth/webui/resources/cryptauth_interface.js +++ b/components/proximity_auth/webui/resources/cryptauth_interface.js @@ -23,7 +23,9 @@ CryptAuthInterface = { * Removes an observer. */ removeObserver: function(observer) { - CryptAuthInterface.observers_.remove(observer); + var index = CryptAuthInterface.observers_.indexOf(observer); + if (observer) + CryptAuthInterface.observers_.splice(index, 1); }, /** @@ -44,6 +46,14 @@ CryptAuthInterface = { }, /** + * Makes the device with |publicKey| an unlock key if |makeUnlockKey| is true. + * Otherwise, the device will be removed as an unlock key. + */ + toggleUnlockKey: function(publicKey, makeUnlockKey) { + chrome.send('toggleUnlockKey', [publicKey, makeUnlockKey]); + }, + + /** * Called by the browser when the API request fails. */ onError: function(errorMessage) { @@ -66,7 +76,7 @@ CryptAuthInterface = { }); }, - /** + /* * Called by the browser when the reachable devices flow completes * successfully. * @param {Array<DeviceInfo>} reachableDevices @@ -77,4 +87,14 @@ CryptAuthInterface = { observer.onGotReachableDevices(reachableDevices); }); }, + + /** + * Called by the browser when an unlock key is toggled. + */ + onUnlockKeyToggled: function() { + CryptAuthInterface.observers_.forEach(function(observer) { + if (observer.onUnlockKeyToggled != null) + observer.onUnlockKeyToggled(); + }); + }, }; diff --git a/components/proximity_auth/webui/resources/device-list.html b/components/proximity_auth/webui/resources/device-list.html index 15a5ecd..3b22dcc 100644 --- a/components/proximity_auth/webui/resources/device-list.html +++ b/components/proximity_auth/webui/resources/device-list.html @@ -4,8 +4,11 @@ <link href="chrome://resources/polymer/v1_0/iron-icons/hardware-icons.html" rel="import"> <link href="chrome://resources/polymer/v1_0/iron-icons/iron-icons.html" rel="import"> <link href="chrome://resources/polymer/v1_0/iron-icons/notification-icons.html" rel="import"> +<link href="chrome://resources/polymer/v1_0/paper-button/paper-button.html" rel="import"> +<link href="chrome://resources/polymer/v1_0/paper-dialog/paper-dialog.html" rel="import"> <link href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html" rel="import"> <link href="chrome://resources/polymer/v1_0/paper-material/paper-material.html" rel="import"> +<link href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html" rel="import"> <link href="chrome://resources/polymer/v1_0/polymer/polymer.html" rel="import"> <dom-module id="device-list"> @@ -72,16 +75,71 @@ line-height: 18px; padding: 8px 16px; } + + #unlock-key-dialog { + width: 500px; + } + + #dialog-text { + color: #7E7E7E; + } + + #dialog-buttons { + height: 36px; + display: flex; + flex-direction: row; + justify-content: flex-end; + margin: 8px; + padding: 0px; + color: #377EF3; + } + + #dialog-spinner { + width: 20px; + height: 20px; + padding-right: 14px; + } </style> <template> <div class="devices-label">[[label]]</div> + <paper-dialog id="unlock-key-dialog" + no-cancel-on-outside-click="true" + with-backdrop="true" + no-cancel-on-esc-key="true"> + <div id="dialog-text"> + <span hidden$="[[deviceForDialog_.unlockKey]]"> + Make <span>[[deviceForDialog_.friendlyDeviceName]]</span> an unlock + key. + </span> + <span hidden$="[[!deviceForDialog_.unlockKey]]"> + Remove <span>[[deviceForDialog_.friendlyDeviceName]]</span> as an + unlock key. + </span> + </div> + <div id="dialog-buttons"> + <paper-button dialog-dismiss disabled$="[[toggleUnlockKeyInProgress_]]"> + Cancel + </paper-button> + <paper-button id="unlock-key-button" on-click="toggleUnlockKey_" + disabled$="[[toggleUnlockKeyInProgress_]]"> + <span hidden$="[[deviceForDialog_.unlockKey]]"> + Make Unlock Key + </span> + <span hidden$="[[!deviceForDialog_.unlockKey]]"> + Remove Unlock Key + </span> + </paper-button> + </div> + </paper-dialog> + <paper-material> <template is="dom-repeat" items="[[devices]]"> <div class="item layout horizontal center"> <paper-icon-button class="end-icon" - icon="[[getIconForUnlockKey_(item)]]"> + icon="[[getIconForUnlockKey_(item)]]" + on-click="showUnlockKeyDialog_"> </paper-icon-button> <div class="info"> diff --git a/components/proximity_auth/webui/resources/device-list.js b/components/proximity_auth/webui/resources/device-list.js index 74ce87f..ae9375a 100644 --- a/components/proximity_auth/webui/resources/device-list.js +++ b/components/proximity_auth/webui/resources/device-list.js @@ -20,6 +20,60 @@ Polymer({ * @type {Array<DeviceInfo>} */ devices: Array, + + /** + * Set with the selected device when the unlock key dialog is opened. + */ + deviceForDialog_: { + type: Object, + value: null + }, + + /** + * True if currently toggling a device as an unlock key. + */ + toggleUnlockKeyInProgress_: { + type: Boolean, + value: false, + }, + }, + + /** + * Shows the toggle unlock key dialog when the toggle button is pressed for an + * item. + * @param {Event} event + */ + showUnlockKeyDialog_: function(event) { + this.deviceForDialog_ = event.model.item; + var dialog = this.querySelector('#unlock-key-dialog'); + dialog.open(); + }, + + /** + * Called when the unlock key dialog button is clicked to make the selected + * device an unlock key or remove it as an unlock key. + * @param {Event} event + */ + toggleUnlockKey_: function(event) { + if (!this.deviceForDialog_) + return; + this.toggleUnlockKeyInProgress_ = true; + CryptAuthInterface.addObserver(this); + + var publicKey = this.deviceForDialog_.publicKey; + var makeUnlockKey = !this.deviceForDialog_.unlockKey; + CryptAuthInterface.toggleUnlockKey(publicKey, makeUnlockKey); + }, + + /** + * Called when the toggling the unlock key completes, so we can close the + * dialog. + */ + onUnlockKeyToggled: function() { + this.toggleUnlockKeyInProgress_ = false; + CryptAuthInterface.removeObserver(this); + var dialog = this.querySelector('#unlock-key-dialog'); + dialog.close(); }, /** |