diff options
author | tengs <tengs@chromium.org> | 2015-07-06 16:30:39 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-06 23:32:01 +0000 |
commit | a8ff58440771425da799936e663b9c52b99d1157 (patch) | |
tree | bc3d8219b971d21f869f8e29c05c9e1b60f43502 /components/proximity_auth | |
parent | c18057cb698ccb16b0ab6c308926c32000f3dd52 (diff) | |
download | chromium_src-a8ff58440771425da799936e663b9c52b99d1157.zip chromium_src-a8ff58440771425da799936e663b9c52b99d1157.tar.gz chromium_src-a8ff58440771425da799936e663b9c52b99d1157.tar.bz2 |
Hook up CryptAuthEnrollmentManager to chrome://proximity-auth for testing.
Until CryptAuth enrollment is properly hooked up to Chrome, we temporarily
create a CryptAuthEnrollmentManager instance in the WebUI when it is created so
we can test it.
BUG=409158
TEST=manual
Review URL: https://codereview.chromium.org/1168743005
Cr-Commit-Position: refs/heads/master@{#337516}
Diffstat (limited to 'components/proximity_auth')
8 files changed, 388 insertions, 53 deletions
diff --git a/components/proximity_auth/webui/BUILD.gn b/components/proximity_auth/webui/BUILD.gn index c52a426..61a0805 100644 --- a/components/proximity_auth/webui/BUILD.gn +++ b/components/proximity_auth/webui/BUILD.gn @@ -5,6 +5,8 @@ # GYP version: components/proximity_auth.gypi:proximity_auth_webui static_library("webui") { sources = [ + "cryptauth_enroller_factory_impl.cc", + "cryptauth_enroller_factory_impl.h", "proximity_auth_ui.cc", "proximity_auth_ui.h", "proximity_auth_ui_delegate.h", diff --git a/components/proximity_auth/webui/cryptauth_enroller_factory_impl.cc b/components/proximity_auth/webui/cryptauth_enroller_factory_impl.cc new file mode 100644 index 0000000..e8c5ca2 --- /dev/null +++ b/components/proximity_auth/webui/cryptauth_enroller_factory_impl.cc @@ -0,0 +1,28 @@ +// Copyright 2015 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 "components/proximity_auth/webui/cryptauth_enroller_factory_impl.h" + +#include "components/proximity_auth/cryptauth/cryptauth_client.h" +#include "components/proximity_auth/cryptauth/cryptauth_enroller_impl.h" +#include "components/proximity_auth/cryptauth/secure_message_delegate.h" +#include "components/proximity_auth/webui/proximity_auth_ui_delegate.h" + +namespace proximity_auth { + +CryptAuthEnrollerFactoryImpl::CryptAuthEnrollerFactoryImpl( + ProximityAuthUIDelegate* delegate) + : delegate_(delegate) { +} + +CryptAuthEnrollerFactoryImpl::~CryptAuthEnrollerFactoryImpl() { +} + +scoped_ptr<CryptAuthEnroller> CryptAuthEnrollerFactoryImpl::CreateInstance() { + return make_scoped_ptr( + new CryptAuthEnrollerImpl(delegate_->CreateCryptAuthClientFactory(), + delegate_->CreateSecureMessageDelegate())); +} + +} // namespace proximity_auth diff --git a/components/proximity_auth/webui/cryptauth_enroller_factory_impl.h b/components/proximity_auth/webui/cryptauth_enroller_factory_impl.h new file mode 100644 index 0000000..5ab9bf2 --- /dev/null +++ b/components/proximity_auth/webui/cryptauth_enroller_factory_impl.h @@ -0,0 +1,35 @@ +// Copyright 2015 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. + +#ifndef COMPONENTS_PROXIMITY_AUTH_WEBUI_CRYPTAUTH_ENROLLER_FACTORY_IMPL_H +#define COMPONENTS_PROXIMITY_AUTH_WEBUI_CRYPTAUTH_ENROLLER_FACTORY_IMPL_H + +#include "base/memory/scoped_ptr.h" +#include "components/proximity_auth/cryptauth/cryptauth_enroller.h" + +namespace proximity_auth { + +class ProximityAuthUIDelegate; + +// Implementation of CryptAuthEnrollerFactory with dependencies on Chrome. +// TODO(tengs): Move this class out of the webui directory when we are ready to +// do enrollments in Chrome. +class CryptAuthEnrollerFactoryImpl : public CryptAuthEnrollerFactory { + public: + explicit CryptAuthEnrollerFactoryImpl(ProximityAuthUIDelegate* delegate); + ~CryptAuthEnrollerFactoryImpl() override; + + // CryptAuthEnrollerFactory: + scoped_ptr<CryptAuthEnroller> CreateInstance() override; + + private: + // |delegate_| is not owned and must outlive this instance. + ProximityAuthUIDelegate* const delegate_; + + DISALLOW_COPY_AND_ASSIGN(CryptAuthEnrollerFactoryImpl); +}; + +} // namespace proximity_auth + +#endif // COMPONENTS_PROXIMITY_AUTH_WEBUI_CRYPTAUTH_ENROLLER_FACTORY_IMPL_H diff --git a/components/proximity_auth/webui/proximity_auth_ui_delegate.h b/components/proximity_auth/webui/proximity_auth_ui_delegate.h index fd04210..6de61e7 100644 --- a/components/proximity_auth/webui/proximity_auth_ui_delegate.h +++ b/components/proximity_auth/webui/proximity_auth_ui_delegate.h @@ -8,9 +8,12 @@ #include "base/memory/scoped_ptr.h" #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" +class PrefService; + namespace proximity_auth { class CryptAuthClientFactory; +class SecureMessageDelegate; // A delegate used by the chrome://proximity-auth WebUI, used to get // implmentations with dependencies on chrome. @@ -18,6 +21,12 @@ class ProximityAuthUIDelegate { public: virtual ~ProximityAuthUIDelegate() {} + // Returns the PrefService used by the profile. + virtual PrefService* GetPrefService() = 0; + + // Returns the SecureMessageDelegate used by the system. + virtual scoped_ptr<SecureMessageDelegate> CreateSecureMessageDelegate() = 0; + // Constructs the CryptAuthClientFactory that can be used for API requests. virtual scoped_ptr<CryptAuthClientFactory> CreateCryptAuthClientFactory() = 0; diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.cc b/components/proximity_auth/webui/proximity_auth_webui_handler.cc index 4f51a9f..3e73c51 100644 --- a/components/proximity_auth/webui/proximity_auth_webui_handler.cc +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.cc @@ -6,10 +6,14 @@ #include "base/bind.h" #include "base/i18n/time_formatting.h" +#include "base/prefs/pref_service.h" +#include "base/time/default_clock.h" #include "base/values.h" #include "components/proximity_auth/cryptauth/base64url.h" +#include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" #include "components/proximity_auth/cryptauth/proto/cryptauth_api.pb.h" #include "components/proximity_auth/logging/logging.h" +#include "components/proximity_auth/webui/cryptauth_enroller_factory_impl.h" #include "components/proximity_auth/webui/proximity_auth_ui_delegate.h" #include "content/public/browser/web_ui.h" @@ -24,6 +28,13 @@ const char kLogMessageFileKey[] = "file"; const char kLogMessageLineKey[] = "line"; const char kLogMessageSeverityKey[] = "severity"; +// Keys in the JSON representation of a SyncState object for enrollment or +// device sync. +const char kSyncStateLastSuccessTime[] = "lastSuccessTime"; +const char kSyncStateNextRefreshTime[] = "nextRefreshTime"; +const char kSyncStateRecoveringFromFailure[] = "recoveringFromFailure"; +const char kSyncStateOperationInProgress[] = "operationInProgress"; + // Converts |log_message| to a raw dictionary value used as a JSON argument to // JavaScript functions. scoped_ptr<base::DictionaryValue> LogMessageToDictionary( @@ -88,12 +99,13 @@ scoped_ptr<base::DictionaryValue> IneligibleDeviceToDictionary( ProximityAuthWebUIHandler::ProximityAuthWebUIHandler( ProximityAuthUIDelegate* delegate) : delegate_(delegate), weak_ptr_factory_(this) { - LogBuffer::GetInstance()->AddObserver(this); cryptauth_client_factory_ = delegate_->CreateCryptAuthClientFactory(); } ProximityAuthWebUIHandler::~ProximityAuthWebUIHandler() { LogBuffer::GetInstance()->RemoveObserver(this); + if (enrollment_manager_) + enrollment_manager_->RemoveObserver(this); } void ProximityAuthWebUIHandler::RegisterMessages() { @@ -109,6 +121,18 @@ void ProximityAuthWebUIHandler::RegisterMessages() { "findEligibleUnlockDevices", base::Bind(&ProximityAuthWebUIHandler::FindEligibleUnlockDevices, base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "getEnrollmentState", + base::Bind(&ProximityAuthWebUIHandler::GetEnrollmentState, + base::Unretained(this))); + + web_ui()->RegisterMessageCallback( + "forceEnrollment", base::Bind(&ProximityAuthWebUIHandler::ForceEnrollment, + base::Unretained(this))); + + LogBuffer::GetInstance()->AddObserver(this); + InitEnrollmentManager(); } void ProximityAuthWebUIHandler::OnLogMessageAdded( @@ -123,12 +147,26 @@ void ProximityAuthWebUIHandler::OnLogBufferCleared() { web_ui()->CallJavascriptFunction("LogBufferInterface.onLogBufferCleared"); } +void ProximityAuthWebUIHandler::OnEnrollmentStarted() { + web_ui()->CallJavascriptFunction( + "SyncStateInterface.onEnrollmentStateChanged", + *GetEnrollmentStateDictionary()); +} + +void ProximityAuthWebUIHandler::OnEnrollmentFinished(bool success) { + scoped_ptr<base::DictionaryValue> enrollment_state = + GetEnrollmentStateDictionary(); + PA_LOG(INFO) << "Enrollment attempt completed with success=" << success + << ":\n" << *enrollment_state; + web_ui()->CallJavascriptFunction( + "SyncStateInterface.onEnrollmentStateChanged", *enrollment_state); +} + void ProximityAuthWebUIHandler::GetLogMessages(const base::ListValue* args) { base::ListValue json_logs; for (const auto& log : *LogBuffer::GetInstance()->logs()) { json_logs.Append(LogMessageToDictionary(log).release()); } - web_ui()->CallJavascriptFunction("LogBufferInterface.onGotLogMessages", json_logs); } @@ -141,7 +179,6 @@ void ProximityAuthWebUIHandler::ClearLogBuffer(const base::ListValue* args) { void ProximityAuthWebUIHandler::FindEligibleUnlockDevices( const base::ListValue* args) { - PA_LOG(INFO) << "Finding eligible unlock devices..."; cryptauth_client_ = cryptauth_client_factory_->CreateInstance(); cryptauth::FindEligibleUnlockDevicesRequest request; @@ -154,6 +191,74 @@ void ProximityAuthWebUIHandler::FindEligibleUnlockDevices( weak_ptr_factory_.GetWeakPtr())); } +void ProximityAuthWebUIHandler::ForceEnrollment(const base::ListValue* args) { + if (enrollment_manager_) { + enrollment_manager_->ForceEnrollmentNow( + cryptauth::INVOCATION_REASON_MANUAL); + } +} + +void ProximityAuthWebUIHandler::InitEnrollmentManager() { +#if defined(OS_CHROMEOS) + // TODO(tengs): We initialize a CryptAuthEnrollmentManager here for + // development and testing purposes until it is ready to be moved into Chrome. + // The public/private key pair has been generated and serialized in a previous + // session. + std::string user_public_key; + Base64UrlDecode( + "CAESRgohAD1lP_wgQ8XqVVwz4aK_89SqdvAQG5L_NZH5zXxwg5UbEiEAZFMlgCZ9h8OlyE4" + "QYKY5oiOBu0FmLSKeTAXEq2jnVJI=", + &user_public_key); + + std::string user_private_key; + Base64UrlDecode( + "MIIBeQIBADCCAQMGByqGSM49AgEwgfcCAQEwLAYHKoZIzj0BAQIhAP____8AAAABAAAAAAA" + "AAAAAAAAA________________MFsEIP____8AAAABAAAAAAAAAAAAAAAA______________" + "_8BCBaxjXYqjqT57PrvVV2mIa8ZR0GsMxTsPY7zjw-J9JgSwMVAMSdNgiG5wSTamZ44ROdJ" + "reBn36QBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li_hp_m47n60p8" + "D54WK84zV2sxXs7LtkBoN79R9QIhAP____8AAAAA__________-85vqtpxeehPO5ysL8YyV" + "RAgEBBG0wawIBAQQgKZ4Dsm5xe4p5U2XPGxjrG376ZWWIa9E6r0y1BdjIntyhRANCAAQ9ZT" + "_8IEPF6lVcM-Giv_PUqnbwEBuS_zWR-c18cIOVG2RTJYAmfYfDpchOEGCmOaIjgbtBZi0in" + "kwFxKto51SS", + &user_private_key); + + // This serialized DeviceInfo proto was previously captured from a real + // CryptAuth enrollment, and is replayed here for testing purposes. + std::string serialized_device_info; + Base64UrlDecode( + "IkoIARJGCiEAX_ZjLSq73EVcrarX-7l7No7nSP86GEC322ocSZKqUKwSIQDbEDu9KN7AgLM" + "v_lzZZNui9zSOgXCeDpLhS2tgrYVXijoEbGlua0IFZW4tVVNKSggBEkYKIQBf9mMtKrvcRV" + "ytqtf7uXs2judI_zoYQLfbahxJkqpQrBIhANsQO70o3sCAsy_-XNlk26L3NI6BcJ4OkuFLa" + "2CthVeKam9Nb3ppbGxhLzUuMCAoWDExOyBDck9TIHg4Nl82NCA3MTM0LjAuMCkgQXBwbGVX" + "ZWJLaXQvNTM3LjM2IChLSFRNTCwgbGlrZSBHZWNrbykgQ2hyb21lLzQ1LjAuMjQyMi4wIFN" + "hZmFyaS81MzcuMzZwLYoBAzEuMJABAZoBIG1rYWVtaWdob2xlYmNnY2hsa2JhbmttaWhrbm" + "9qZWFrsAHDPuoBHEJLZEluZWxFZk05VG1adGV3eTRGb19RV1Vicz2AAgKyBqIBQVBBOTFiS" + "FZDdlJJNGJFSXppMmFXOTBlZ044eHFBYkhWYnJwSVFuMTk3bWltd3RWWTZYN0JEcEI4Szg3" + "RjRubkJnejdLX1BQV2xkcUtDRVhiZkFiMGwyN1VaQXgtVjBWbEE4WlFwdkhETmpHVlh4RlV" + "WRDFNY1AzNTgtYTZ3eHRpVG5LQnpMTEVIT1F6Ujdpb0lUMzRtWWY1VmNhbmhPZDh3ugYgs9" + "7-c7qNUzzLeEqVCDXb_EaJ8wC3iie_Lpid44iuAh3CPo0CCugBCiMIARACGgi5wHHa82avM" + "ioQ7y8xhiUBs7Um73ZC1vQlzzIBABLAAeCqGnWF7RwtnmdfIQJoEqXoXrH1qLw4yqUAA1TW" + "M1qxTepJOdDHrh54eiejobW0SKpHqTlZIyiK3ObHAPdfzFum1l640RFdFGZTTTksZFqfD9O" + "dftoi0pMrApob4gXj8Pv2g22ArX55BiH56TkTIcDcEE3KKnA_2G0INT1y_clZvZfDw1n0WP" + "0Xdg1PLLCOb46WfDWUhHvUk3GzUce8xyxsjOkiZUNh8yvhFXaP2wJgVKVWInf0inuofo9Za" + "7p44hIgHgKJIr_4fuVs9Ojf0KcMzxoJTbFUGg58jglUAKFfJBLKPpMBeWEyOS5pQUdTNFZ1" + "bF9JVWY4YTJDSmJNbXFqaWpYUFYzaVV5dmJXSVRrR3d1bFRaVUs3RGVZczJtT0h5ZkQ1NWR" + "HRXEtdnJTdVc4VEZ2Z1haa2xhVEZTN0dqM2xCVUktSHd5Z0h6bHZHX2NGLWtzQmw0dXdveG" + "VPWE1hRlJ3WGJHVUU1Tm9sLS1mdkRIcGVZVnJR", + &serialized_device_info); + cryptauth::GcmDeviceInfo device_info; + device_info.ParseFromString(serialized_device_info); + + enrollment_manager_.reset(new CryptAuthEnrollmentManager( + make_scoped_ptr(new base::DefaultClock()), + make_scoped_ptr(new CryptAuthEnrollerFactoryImpl(delegate_)), + user_public_key, user_private_key, device_info, + delegate_->GetPrefService())); + enrollment_manager_->AddObserver(this); + enrollment_manager_->Start(); +#endif +} + void ProximityAuthWebUIHandler::OnCryptAuthClientError( const std::string& error_message) { PA_LOG(WARNING) << "CryptAuth request failed: " << error_message; @@ -180,4 +285,34 @@ void ProximityAuthWebUIHandler::OnFoundEligibleUnlockDevices( eligible_devices, ineligible_devices); } +void ProximityAuthWebUIHandler::GetEnrollmentState( + const base::ListValue* args) { + scoped_ptr<base::DictionaryValue> enrollment_state = + GetEnrollmentStateDictionary(); + PA_LOG(INFO) << "Got Enrollment State: \n" << *enrollment_state; + web_ui()->CallJavascriptFunction("SyncStateInterface.onGotEnrollmentState", + *enrollment_state); +} + +scoped_ptr<base::DictionaryValue> +ProximityAuthWebUIHandler::GetEnrollmentStateDictionary() { + scoped_ptr<base::DictionaryValue> enrollment_state( + new base::DictionaryValue()); + + if (!enrollment_manager_) + return enrollment_state; + + enrollment_state->SetDouble( + kSyncStateLastSuccessTime, + enrollment_manager_->GetLastEnrollmentTime().ToJsTime()); + enrollment_state->SetDouble( + kSyncStateNextRefreshTime, + enrollment_manager_->GetTimeToNextAttempt().InMillisecondsF()); + enrollment_state->SetBoolean(kSyncStateRecoveringFromFailure, + enrollment_manager_->IsRecoveringFromFailure()); + enrollment_state->SetBoolean(kSyncStateOperationInProgress, + enrollment_manager_->IsEnrollmentInProgress()); + return enrollment_state; +} + } // namespace proximity_auth diff --git a/components/proximity_auth/webui/proximity_auth_webui_handler.h b/components/proximity_auth/webui/proximity_auth_webui_handler.h index 59e56b9..b5eb7ed 100644 --- a/components/proximity_auth/webui/proximity_auth_webui_handler.h +++ b/components/proximity_auth/webui/proximity_auth_webui_handler.h @@ -6,7 +6,9 @@ #define COMPONENTS_PROXIMITY_AUTH_WEBUI_PROXIMITY_AUTH_WEBUI_HANDLER_H_ #include "base/memory/weak_ptr.h" +#include "base/values.h" #include "components/proximity_auth/cryptauth/cryptauth_client.h" +#include "components/proximity_auth/cryptauth/cryptauth_enrollment_manager.h" #include "components/proximity_auth/logging/log_buffer.h" #include "components/proximity_auth/webui/proximity_auth_ui_delegate.h" #include "content/public/browser/web_ui_message_handler.h" @@ -17,11 +19,10 @@ class ListValue; namespace proximity_auth { -class ProximityAuthUIDelegate; - // Handles messages from the chrome://proximity-auth page. class ProximityAuthWebUIHandler : public content::WebUIMessageHandler, - public LogBuffer::Observer { + public LogBuffer::Observer, + public CryptAuthEnrollmentManager::Observer { public: // |delegate| is not owned and must outlive this instance. explicit ProximityAuthWebUIHandler(ProximityAuthUIDelegate* delegate); @@ -35,10 +36,19 @@ class ProximityAuthWebUIHandler : public content::WebUIMessageHandler, void OnLogMessageAdded(const LogBuffer::LogMessage& log_message) override; void OnLogBufferCleared() override; + // CryptAuthEnrollmentManager::Observer: + void OnEnrollmentStarted() override; + void OnEnrollmentFinished(bool success) override; + // Message handler callbacks. void GetLogMessages(const base::ListValue* args); void ClearLogBuffer(const base::ListValue* args); void FindEligibleUnlockDevices(const base::ListValue* args); + void GetEnrollmentState(const base::ListValue* args); + void ForceEnrollment(const base::ListValue* args); + + // Initializes the CryptAuthEnrollmentManager, used for development purposes. + void InitEnrollmentManager(); // Called when a CryptAuth request fails. void OnCryptAuthClientError(const std::string& error_message); @@ -47,6 +57,9 @@ class ProximityAuthWebUIHandler : public content::WebUIMessageHandler, void OnFoundEligibleUnlockDevices( const cryptauth::FindEligibleUnlockDevicesResponse& response); + // Returns the current enrollment state that can be used as a JSON object. + scoped_ptr<base::DictionaryValue> GetEnrollmentStateDictionary(); + // The delegate used to fetch dependencies. Must outlive this instance. ProximityAuthUIDelegate* delegate_; @@ -56,6 +69,10 @@ class ProximityAuthWebUIHandler : public content::WebUIMessageHandler, // We only support one concurrent API call. scoped_ptr<CryptAuthClient> cryptauth_client_; + // TODO(tengs): These members are temporarily used for development. + scoped_ptr<PrefService> pref_service; + scoped_ptr<CryptAuthEnrollmentManager> enrollment_manager_; + base::WeakPtrFactory<ProximityAuthWebUIHandler> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ProximityAuthWebUIHandler); diff --git a/components/proximity_auth/webui/resources/local-state.html b/components/proximity_auth/webui/resources/local-state.html index 2cac823..a61489a 100644 --- a/components/proximity_auth/webui/resources/local-state.html +++ b/components/proximity_auth/webui/resources/local-state.html @@ -47,7 +47,7 @@ } .next-sync-icon { - color: green; + color: black; margin-right: 4px; } @@ -69,22 +69,25 @@ <div class="card-content layout vertical flex"> <div class="card-title">Enrollment</div> <div class="card-subtitle"> - <span>[[getLastSyncTimeString_(enrollmentInfo, - "Never enrolled")]]</span> + <span>[[ + getLastSyncTimeString_(enrollmentState_, "Never enrolled") + ]]</span> </div> <div class="next-refresh layout horizontal center flex"> <iron-icon class="next-sync-icon" - icon="icons:schedule" error-icon> + icon="[[getNextSyncIcon_(enrollmentState_)]]"> </iron-icon> - <span>[[getNextEnrollmentString_(enrollmentInfo)]]</span> + <span>[[getNextEnrollmentString_(enrollmentState_)]]</span> </div> </div> <iron-icon class="card-icon" - icon="[[getIconForLastAttempt_(enrollmentInfo)]]" - error-icon$="[[enrollmentInfo.lastAttemptFailed]]"> + icon="[[getIconForSuccess_(enrollmentState_)]]" + error-icon$="[[enrollmentState_.recoveringFromFailure]]"> </iron-icon> </div> - <paper-button class="self-start">Force Enroll</paper-button> + <paper-button class="self-start" on-click="forceEnrollment_"> + Force Enroll + </paper-button> </paper-material> <!-- Device Sync Info Card --> @@ -93,24 +96,27 @@ <div class="card-content layout vertical flex"> <div class="card-title">Device Sync</div> <div class="card-subtitle"> - <span>[[getLastSyncTimeString_(deviceSyncInfo, - "Never synced")]]</span> + <span>[[ + getLastSyncTimeString_(deviceSyncState_, "Never synced")]] + </span> </div> <div class="layout horizontal center flex"> - <iron-icon class="next-sync-icon" icon="icons:schedule"></iron-icon> - <span>[[getNextEnrollmentString_(deviceSyncInfo)]]</span> + <iron-icon class="next-sync-icon" + icon="[[getNextSyncIcon_(deviceSyncState_)]]"> + </iron-icon> + <span>[[getNextEnrollmentString_(deviceSyncState_)]]</span> </div> </div> <iron-icon class="card-icon" - icon="[[getIconForLastAttempt_(deviceSyncInfo)]]" - error-icon$="[[deviceSyncInfo.lastAttemptFailed]]"> + icon="[[getIconForSuccess_(deviceSyncState_)]]" + error-icon$="[[deviceSyncState_.recoveringFromFailure]]"> </iron-icon> </div> <paper-button class="self-start">Force Sync</paper-button> </paper-material> </div> - <device-list label="Unlock Keys" devices="[[unlockKeys]]"></device-list> + <device-list label="Unlock Keys" devices="[[unlockKeys_]]"></device-list> </template> <script src="local-state.js"></script> </local-state> diff --git a/components/proximity_auth/webui/resources/local-state.js b/components/proximity_auth/webui/resources/local-state.js index 6ee17eb..70ecb48 100644 --- a/components/proximity_auth/webui/resources/local-state.js +++ b/components/proximity_auth/webui/resources/local-state.js @@ -9,43 +9,40 @@ Polymer({ * The current CryptAuth enrollment status. * @type {{ * lastSuccessTime: ?number, - * nextRefreshTime: string, - * lastAttemptFailed: boolean, - * }} + * nextRefreshTime: ?number, + * recoveringFromFailure: boolean, + * operationInProgress: boolean, + * }} SyncState */ - enrollmentInfo: { + enrollmentState_: { type: Object, value: { lastSuccessTime: null, - nextRefreshTime: '90 days', - lastAttemptFailed: true + nextRefreshTime: null, + recoveringFromFailure: true, + operationInProgress: false, }, - notify: true, }, /** * The current CryptAuth device sync status. - * @type {{ - * lastSuccessTime: ?number, - * nextRefreshTime: string, - * lastAttemptFailed: boolean, - * }} + * @type {SyncState} */ - deviceSyncInfo: { + deviceSyncState_: { type: Object, value: { - lastSuccessTime: 'April 20 14:23', - nextRefreshTime: '15.5 hours', - lastAttemptFailed: false + lastSuccessTime: null, + nextRefreshTime: null, + recoveringFromFailure: true, + operationInProgress: false, }, - notify: true, }, /** * List of unlock keys that can unlock the local device. * @type {Array<DeviceInfo>} */ - unlockKeys: { + unlockKeys_: { type: Array, value: [ { @@ -63,33 +60,139 @@ Polymer({ }, }, ], - notify: true, }, }, /** - * @param {SyncInfo} syncInfo - * @param {string} neverSyncedString - * @return {string} + * Called when the page is about to be shown. + */ + activate: function() { + SyncStateInterface = this; + chrome.send('getEnrollmentState'); + }, + + /** + * Immediately forces an enrollment attempt. + */ + forceEnrollment_: function() { + chrome.send('forceEnrollment'); + }, + + /** + * Called when the enrollment state changes. + * @param {SyncState} enrollmentState + */ + onEnrollmentStateChanged: function(enrollmentState) { + this.enrollmentState_ = enrollmentState; + }, + + /** + * Called when the device sync state changes. + * @param {SyncState} deviceSyncState + */ + onDeviceSyncStateChanged: function(deviceSyncState) {}, + + /** + * Called for the chrome.send('getEnrollmentState') response. + * @param {SyncState} enrollmentState + */ + onGotEnrollmentState: function(enrollmentState) { + this.enrollmentState_ = enrollmentState; + }, + + /** + * Called for the chrome.send('getDeviceSyncState') response. + * @param {SyncState} enrollmentState */ - getLastSyncTimeString_: function(syncInfo, neverSyncedString) { - return syncInfo.lastSuccessTime || neverSyncedString; + onGotDeviceSyncState: function(deviceSyncState) {}, + + /** + * @param {SyncState} syncState The enrollment or device sync state. + * @param {string} neverSyncedString String returned if there has never been a + * last successful sync. + * @return {string} The formatted string of the last successful sync time. + */ + getLastSyncTimeString_: function(syncState, neverSyncedString) { + if (syncState.lastSuccessTime == 0) + return neverSyncedString; + var date = new Date(syncState.lastSuccessTime); + return date.toLocaleDateString() + ' ' + date.toLocaleTimeString(); }, /** - * @param {SyncInfo} syncInfo - * @return {string} + * @param {SyncState} syncState The enrollment or device sync state. + * @return {string} The formatted string to be displayed. */ - getNextEnrollmentString_: function(syncInfo) { - return syncInfo.nextRefreshTime + ' to refresh'; + getNextEnrollmentString_: function(syncState) { + var deltaMillis = syncState.nextRefreshTime; + if (deltaMillis == null) + return 'unknown'; + if (deltaMillis == 0) + return 'sync in progress...'; + + var seconds = deltaMillis / 1000; + if (seconds < 60) + return Math.round(seconds) + ' seconds to refresh'; + + var minutes = seconds / 60; + if (minutes < 60) + return Math.round(minutes) + ' minutes to refresh'; + + var hours = minutes / 60; + if (hours < 24) + return Math.round(hours) + ' hours to refresh'; + + var days = hours / 24; + return Math.round(days) + ' days to refresh'; }, /** - * @param {SyncInfo} syncInfo - * @return {string} + * @param {SyncState} syncState The enrollment or device sync state. + * @return {string} The icon to show for the current state. */ - getIconForLastAttempt_: function(syncInfo) { - return syncInfo.lastAttemptFailed ? + getNextSyncIcon_: function(syncState) { + return syncState.operationInProgress ? 'icons:refresh' : 'icons:schedule'; + }, + + /** + * @param {SyncState} syncState The enrollment or device sync state. + * @return {string} The icon id representing whether the last sync is + * successful. + */ + getIconForSuccess_: function(syncState) { + return syncState.recoveringFromFailure ? 'icons:error' : 'icons:cloud-done'; }, }); + +// Interface with the native WebUI component for the CryptAuthSync state (i.e. +// enrollment and device sync). +SyncStateInterface = { + /** + * Called when the enrollment state changes. For example, when a new + * enrollment is initiated. + * @type {function(SyncState)} + */ + onEnrollmentStateChanged: function(enrollmentState) {}, + + /** + * Called when the device state changes. For example, when a new device sync + * is initiated. + * @type {function(DeviceSyncState)} + */ + onDeviceSyncStateChanged: function(deviceSyncState) {}, + + /** + * Called in response to chrome.send('getEnrollmentState') with the current + * enrollment status of the user and device. + * @type {function(SyncState)} + */ + onGotEnrollmentState: function(enrollmentState) {}, + + /** + * Called in response to chrome.send('getDeviceState') with the current + * enrollment status of the user and device. + * @type {function(DeviceSyncState)} + */ + onGotDeviceSyncState: function(deviceSyncState) {}, +}; |