diff options
11 files changed, 243 insertions, 0 deletions
diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc index fd4e97d..d122c63 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.cc @@ -776,5 +776,29 @@ bool EasyUnlockPrivateShowErrorBubbleFunction::RunSync() { return true; } +EasyUnlockPrivateSetAutoPairingResultFunction:: + EasyUnlockPrivateSetAutoPairingResultFunction() { +} + +EasyUnlockPrivateSetAutoPairingResultFunction:: + ~EasyUnlockPrivateSetAutoPairingResultFunction() { +} + +bool EasyUnlockPrivateSetAutoPairingResultFunction::RunSync() { + scoped_ptr<easy_unlock_private::SetAutoPairingResult::Params> params = + easy_unlock_private::SetAutoPairingResult::Params::Create(*args_); + EXTENSION_FUNCTION_VALIDATE(params); + + std::string error_message; + if (params->result.error_message) + error_message = *params->result.error_message; + + Profile* profile = Profile::FromBrowserContext(browser_context()); + EasyUnlockService::Get(profile) + ->SetAutoPairingResult(params->result.success, error_message); + + return true; +} + } // namespace api } // namespace extensions diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h index 8f366c6..7ce6450 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h @@ -368,6 +368,22 @@ class EasyUnlockPrivateShowErrorBubbleFunction : public SyncExtensionFunction { DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateShowErrorBubbleFunction); }; +class EasyUnlockPrivateSetAutoPairingResultFunction + : public SyncExtensionFunction { + public: + DECLARE_EXTENSION_FUNCTION("easyUnlockPrivate.setAutoPairingResult", + EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT) + EasyUnlockPrivateSetAutoPairingResultFunction(); + + private: + ~EasyUnlockPrivateSetAutoPairingResultFunction() override; + + // SyncExtensionFunction: + bool RunSync() override; + + DISALLOW_COPY_AND_ASSIGN(EasyUnlockPrivateSetAutoPairingResultFunction); +}; + } // namespace api } // namespace extensions diff --git a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc index cf6bd96..6248cb9 100644 --- a/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc +++ b/chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api_chromeos_unittest.cc @@ -2,15 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <string> + #include "base/bind.h" +#include "base/message_loop/message_loop.h" #include "base/strings/stringprintf.h" #include "base/values.h" #include "chrome/browser/extensions/api/easy_unlock_private/easy_unlock_private_api.h" #include "chrome/browser/extensions/extension_api_unittest.h" #include "chrome/browser/extensions/extension_function_test_utils.h" +#include "chrome/browser/extensions/extension_system_factory.h" +#include "chrome/browser/extensions/test_extension_prefs.h" +#include "chrome/browser/extensions/test_extension_system.h" +#include "chrome/browser/signin/easy_unlock_service_factory.h" +#include "chrome/browser/signin/easy_unlock_service_regular.h" #include "chrome/common/extensions/api/easy_unlock_private.h" +#include "chrome/common/extensions/extension_constants.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_easy_unlock_client.h" +#include "extensions/browser/event_router.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -22,6 +32,7 @@ using extensions::api::EasyUnlockPrivateGenerateEcP256KeyPairFunction; using extensions::api::EasyUnlockPrivatePerformECDHKeyAgreementFunction; using extensions::api::EasyUnlockPrivateCreateSecureMessageFunction; using extensions::api::EasyUnlockPrivateUnwrapSecureMessageFunction; +using extensions::api::EasyUnlockPrivateSetAutoPairingResultFunction; // Converts a string to a base::BinaryValue value whose buffer contains the // string data without the trailing '\0'. @@ -392,5 +403,117 @@ TEST_F(EasyUnlockPrivateApiTest, UnwrapSecureMessage_AsymmetricSign) { EXPECT_EQ(expected_result, GetSingleBinaryResultAsString(function.get())); } +struct AutoPairingResult { + AutoPairingResult() : success(false) {} + + void SetResult(bool success, const std::string& error) { + this->success = success; + this->error = error; + } + + bool success; + std::string error; +}; + +// Test factory to register EasyUnlockService. +KeyedService* BuildTestEasyUnlockService(content::BrowserContext* context) { + return new EasyUnlockServiceRegular(static_cast<Profile*>(context)); +} + +// A fake EventRouter that logs event it dispatches for testing. +class FakeEventRouter : public extensions::EventRouter { + public: + FakeEventRouter(Profile* profile, extensions::ExtensionPrefs* extension_prefs) + : EventRouter(profile, extension_prefs), + event_count_(0) {} + + void DispatchEventToExtension(const std::string& extension_id, + scoped_ptr<extensions::Event> event) override { + ++event_count_; + last_extension_id_ = extension_id; + last_event_name_ = event ? event->event_name : std::string(); + } + + int event_count() const { return event_count_; } + const std::string& last_extension_id() const { return last_extension_id_; } + const std::string& last_event_name() const { return last_event_name_; } + + private: + int event_count_; + std::string last_extension_id_; + std::string last_event_name_; +}; + +// A fake ExtensionSystem that returns a FakeEventRouter for event_router(). +class FakeExtensionSystem : public extensions::TestExtensionSystem { + public: + explicit FakeExtensionSystem(Profile* profile) + : TestExtensionSystem(profile), + prefs_(new extensions::TestExtensionPrefs( + base::MessageLoopProxy::current())) { + fake_event_router_.reset(new FakeEventRouter(profile, prefs_->prefs())); + } + + extensions::EventRouter* event_router() override { + return fake_event_router_.get(); + } + + private: + scoped_ptr<extensions::TestExtensionPrefs> prefs_; + scoped_ptr<FakeEventRouter> fake_event_router_; +}; + +// Factory function to register for the ExtensionSystem. +KeyedService* BuildFakeExtensionSystem(content::BrowserContext* profile) { + return new FakeExtensionSystem(static_cast<Profile*>(profile)); +} + +TEST_F(EasyUnlockPrivateApiTest, AutoPairing) { + EasyUnlockServiceFactory::GetInstance()->SetTestingFactoryAndUse( + profile(), &BuildTestEasyUnlockService); + FakeExtensionSystem* fake_extension_system = + static_cast<FakeExtensionSystem*>( + extensions::ExtensionSystemFactory::GetInstance() + ->SetTestingFactoryAndUse(profile(), &BuildFakeExtensionSystem)); + FakeEventRouter* event_router = + static_cast<FakeEventRouter*>(fake_extension_system->event_router()); + + AutoPairingResult result; + + // Dispatch OnStartAutoPairing event on EasyUnlockService::StartAutoPairing. + EasyUnlockService* service = EasyUnlockService::Get(profile()); + service->StartAutoPairing(base::Bind(&AutoPairingResult::SetResult, + base::Unretained(&result))); + EXPECT_EQ(1, event_router->event_count()); + EXPECT_EQ(extension_misc::kEasyUnlockAppId, + event_router->last_extension_id()); + EXPECT_EQ( + extensions::api::easy_unlock_private::OnStartAutoPairing::kEventName, + event_router->last_event_name()); + + // Test SetAutoPairingResult call with failure. + scoped_refptr<EasyUnlockPrivateSetAutoPairingResultFunction> function( + new EasyUnlockPrivateSetAutoPairingResultFunction()); + ASSERT_TRUE(extension_function_test_utils::RunFunction( + function.get(), + "[{\"success\":false, \"errorMessage\":\"fake_error\"}]", + browser(), + extension_function_test_utils::NONE)); + EXPECT_EQ(false, result.success); + EXPECT_EQ("fake_error", result.error); + + // Test SetAutoPairingResult call with success. + service->StartAutoPairing(base::Bind(&AutoPairingResult::SetResult, + base::Unretained(&result))); + function = new EasyUnlockPrivateSetAutoPairingResultFunction(); + ASSERT_TRUE(extension_function_test_utils::RunFunction( + function.get(), + "[{\"success\":true}]", + browser(), + extension_function_test_utils::NONE)); + EXPECT_EQ(true, result.success); + EXPECT_TRUE(result.error.empty()); +} + } // namespace diff --git a/chrome/browser/signin/easy_unlock_service.h b/chrome/browser/signin/easy_unlock_service.h index df6a213..ad45ed5 100644 --- a/chrome/browser/signin/easy_unlock_service.h +++ b/chrome/browser/signin/easy_unlock_service.h @@ -8,6 +8,7 @@ #include <set> #include <string> +#include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" @@ -126,6 +127,14 @@ class EasyUnlockService : public KeyedService { // Records metrics for password based flow for the given user. virtual void RecordPasswordLoginEvent(const std::string& user_id) const = 0; + // Starts auto pairing. + typedef base::Callback<void(bool success, const std::string& error)> + AutoPairingResultCallback; + virtual void StartAutoPairing(const AutoPairingResultCallback& callback) = 0; + + // Sets auto pairing result. + virtual void SetAutoPairingResult(bool success, const std::string& error) = 0; + // Whether easy unlock is allowed to be used. If the controlling preference // is set (from policy), this returns the preference value. Otherwise, it is // permitted either the flag is enabled or its field trial is enabled. diff --git a/chrome/browser/signin/easy_unlock_service_regular.cc b/chrome/browser/signin/easy_unlock_service_regular.cc index c6e9ca2..025fc00 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.cc +++ b/chrome/browser/signin/easy_unlock_service_regular.cc @@ -17,6 +17,7 @@ #include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/extensions/app_launch_params.h" #include "chrome/browser/ui/extensions/application_launch.h" +#include "chrome/common/extensions/api/easy_unlock_private.h" #include "chrome/common/extensions/extension_constants.h" #include "chrome/common/pref_names.h" #include "chromeos/login/user_names.h" @@ -27,6 +28,7 @@ #include "components/signin/core/browser/profile_oauth2_token_service.h" #include "components/signin/core/browser/signin_manager.h" #include "content/public/browser/browser_thread.h" +#include "extensions/browser/event_router.h" #include "extensions/browser/extension_system.h" #include "extensions/common/constants.h" @@ -253,6 +255,34 @@ void EasyUnlockServiceRegular::RecordPasswordLoginEvent( NOTREACHED(); } +void EasyUnlockServiceRegular::StartAutoPairing( + const AutoPairingResultCallback& callback) { + if (!auto_pairing_callback_.is_null()) { + LOG(ERROR) + << "Start auto pairing when there is another auto pairing requested."; + callback.Run(false, std::string()); + return; + } + + auto_pairing_callback_ = callback; + + scoped_ptr<base::ListValue> args(new base::ListValue()); + scoped_ptr<extensions::Event> event(new extensions::Event( + extensions::api::easy_unlock_private::OnStartAutoPairing::kEventName, + args.Pass())); + extensions::EventRouter::Get(profile())->DispatchEventWithLazyListener( + extension_misc::kEasyUnlockAppId, event.Pass()); +} + +void EasyUnlockServiceRegular::SetAutoPairingResult( + bool success, + const std::string& error) { + DCHECK(!auto_pairing_callback_.is_null()); + + auto_pairing_callback_.Run(success, error); + auto_pairing_callback_.Reset(); +} + void EasyUnlockServiceRegular::InitializeInternal() { registrar_.Init(profile()->GetPrefs()); registrar_.Add( diff --git a/chrome/browser/signin/easy_unlock_service_regular.h b/chrome/browser/signin/easy_unlock_service_regular.h index 9bcf90a..b3f6fb8 100644 --- a/chrome/browser/signin/easy_unlock_service_regular.h +++ b/chrome/browser/signin/easy_unlock_service_regular.h @@ -7,6 +7,7 @@ #include <string> +#include "base/callback.h" #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/prefs/pref_change_registrar.h" @@ -57,6 +58,8 @@ class EasyUnlockServiceRegular : public EasyUnlockService { void RecordEasySignInOutcome(const std::string& user_id, bool success) const override; void RecordPasswordLoginEvent(const std::string& user_id) const override; + void StartAutoPairing(const AutoPairingResultCallback& callback) override; + void SetAutoPairingResult(bool success, const std::string& error) override; void InitializeInternal() override; void ShutdownInternal() override; bool IsAllowedInternal() const override; @@ -98,6 +101,8 @@ class EasyUnlockServiceRegular : public EasyUnlockService { TurnOffFlowStatus turn_off_flow_status_; scoped_ptr<proximity_auth::CryptAuthClient> cryptauth_client_; + AutoPairingResultCallback auto_pairing_callback_; + base::WeakPtrFactory<EasyUnlockServiceRegular> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(EasyUnlockServiceRegular); diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc index 42dbac9..af89d11 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.cc @@ -257,6 +257,17 @@ void EasyUnlockServiceSignin::RecordPasswordLoginEvent( DVLOG(1) << "EasySignIn password login event, event=" << event; } +void EasyUnlockServiceSignin::StartAutoPairing( + const AutoPairingResultCallback& callback) { + NOTREACHED(); +} + +void EasyUnlockServiceSignin::SetAutoPairingResult( + bool success, + const std::string& error) { + NOTREACHED(); +} + void EasyUnlockServiceSignin::InitializeInternal() { if (chromeos::LoginState::Get()->IsUserLoggedIn()) return; diff --git a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h index 45b4352..0126eff 100644 --- a/chrome/browser/signin/easy_unlock_service_signin_chromeos.h +++ b/chrome/browser/signin/easy_unlock_service_signin_chromeos.h @@ -72,6 +72,8 @@ class EasyUnlockServiceSignin : public EasyUnlockService, void RecordEasySignInOutcome(const std::string& user_id, bool success) const override; void RecordPasswordLoginEvent(const std::string& user_id) const override; + void StartAutoPairing(const AutoPairingResultCallback& callback) override; + void SetAutoPairingResult(bool success, const std::string& error) override; void InitializeInternal() override; void ShutdownInternal() override; bool IsAllowedInternal() const override; diff --git a/chrome/common/extensions/api/easy_unlock_private.idl b/chrome/common/extensions/api/easy_unlock_private.idl index 08dd2ca..3e2ad14 100644 --- a/chrome/common/extensions/api/easy_unlock_private.idl +++ b/chrome/common/extensions/api/easy_unlock_private.idl @@ -171,6 +171,15 @@ namespace easyUnlockPrivate { long height; }; + // Auto pairing reuslt. + dictionary AutoPairingResult { + // Whether the auto pairing is completed successfully. + boolean success; + + // Optional error message to indicate the failure. + DOMString? errorMessage; + }; + // Callback for crypto methods that return a single array buffer. callback DataCallback = void(optional ArrayBuffer data); @@ -358,6 +367,14 @@ namespace easyUnlockPrivate { Range link_range, DOMString link_target, Rect anchorRect); + + // Sets the result of auto pairing triggered from onStartAutoPairing + // event. If auto pairing is completed successfully, |result.success| + // should be true so that Easy bootstrap flow would finish and starts + // the user session. Otherwise, |result.success| is set to false with + // an optional error message to be displayed to the user. + static void setAutoPairingResult(AutoPairingResult result, + optional EmptyCallback callback); }; interface Events { @@ -365,5 +382,9 @@ namespace easyUnlockPrivate { // Easy unlock service is updated. // |userInfo| The updated user information. static void onUserInfoUpdated(UserInfo userInfo); + + // Event fired at the end of Easy bootstrap to start auto pairing so + // that a proper cryptohome key could be generated for the user. + static void onStartAutoPairing(); }; }; diff --git a/extensions/browser/extension_function_histogram_value.h b/extensions/browser/extension_function_histogram_value.h index 70ac406..90c53ba 100644 --- a/extensions/browser/extension_function_histogram_value.h +++ b/extensions/browser/extension_function_histogram_value.h @@ -1017,6 +1017,7 @@ enum HistogramValue { NETWORKING_CONFIG_FINISHAUTHENTICATION, PLATFORMKEYSINTERNAL_SELECTCLIENTCERTIFICATES, CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID, + EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT, // Last entry: Add new entries above and ensure to update // tools/metrics/histograms/histograms.xml. ENUM_BOUNDARY diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index d4340ef..004792d 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -47633,6 +47633,7 @@ Therefore, the affected-histogram name has to have at least one dot in it. <int value="956" label="NETWORKING_CONFIG_FINISHAUTHENTICATION"/> <int value="957" label="PLATFORMKEYSINTERNAL_SELECTCLIENTCERTIFICATES"/> <int value="958" label="CRYPTOTOKENPRIVATE_CANORIGINASSERTAPPID"/> + <int value="959" label="EASYUNLOCKPRIVATE_SETAUTOPAIRINGRESULT"/> </enum> <enum name="ExtensionInstallCause" type="int"> |