| // 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/supervised_user/legacy/supervised_user_registration_utility.h" |
| |
| #include <stdint.h> |
| |
| #include <utility> |
| |
| #include "base/bind.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/run_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/threading/sequenced_worker_pool.h" |
| #include "chrome/browser/supervised_user/legacy/supervised_user_refresh_token_fetcher.h" |
| #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service.h" |
| #include "chrome/browser/supervised_user/legacy/supervised_user_shared_settings_service_factory.h" |
| #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service.h" |
| #include "chrome/browser/supervised_user/legacy/supervised_user_sync_service_factory.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/prefs/scoped_user_pref_update.h" |
| #include "components/sync/model/attachments/attachment_id.h" |
| #include "components/sync/model/attachments/attachment_service_proxy_for_test.h" |
| #include "components/sync/model/sync_change.h" |
| #include "components/sync/model/sync_error_factory_mock.h" |
| #include "components/sync/protocol/sync.pb.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/test/test_browser_thread_bundle.h" |
| #include "content/public/test/test_utils.h" |
| #include "google_apis/gaia/google_service_auth_error.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| using sync_pb::ManagedUserSpecifics; |
| using syncer::SUPERVISED_USERS; |
| using syncer::SyncChange; |
| using syncer::SyncChangeList; |
| using syncer::SyncChangeProcessor; |
| using syncer::SyncData; |
| using syncer::SyncDataList; |
| using syncer::SyncError; |
| using syncer::SyncErrorFactory; |
| using syncer::SyncMergeResult; |
| |
| namespace { |
| |
| const char kSupervisedUserToken[] = "supervisedusertoken"; |
| |
| class MockChangeProcessor : public SyncChangeProcessor { |
| public: |
| MockChangeProcessor() {} |
| ~MockChangeProcessor() override {} |
| |
| // SyncChangeProcessor implementation: |
| SyncError ProcessSyncChanges(const base::Location& from_here, |
| const SyncChangeList& change_list) override; |
| |
| SyncDataList GetAllSyncData(syncer::ModelType type) const override { |
| return SyncDataList(); |
| } |
| |
| const SyncChangeList& changes() const { return change_list_; } |
| |
| private: |
| SyncChangeList change_list_; |
| }; |
| |
| SyncError MockChangeProcessor::ProcessSyncChanges( |
| const base::Location& from_here, |
| const SyncChangeList& change_list) { |
| change_list_ = change_list; |
| return SyncError(); |
| } |
| |
| class MockSupervisedUserRefreshTokenFetcher |
| : public SupervisedUserRefreshTokenFetcher { |
| public: |
| MockSupervisedUserRefreshTokenFetcher() {} |
| ~MockSupervisedUserRefreshTokenFetcher() override {} |
| |
| // SupervisedUserRefreshTokenFetcher implementation: |
| void Start(const std::string& supervised_user_id, |
| const std::string& device_name, |
| const TokenCallback& callback) override { |
| GoogleServiceAuthError error(GoogleServiceAuthError::NONE); |
| callback.Run(error, kSupervisedUserToken); |
| } |
| }; |
| |
| } // namespace |
| |
| class SupervisedUserRegistrationUtilityTest : public ::testing::Test { |
| public: |
| SupervisedUserRegistrationUtilityTest(); |
| ~SupervisedUserRegistrationUtilityTest() override; |
| |
| void TearDown() override; |
| |
| protected: |
| std::unique_ptr<SyncChangeProcessor> CreateChangeProcessor(); |
| std::unique_ptr<SyncErrorFactory> CreateErrorFactory(); |
| SyncData CreateRemoteData(const std::string& id, const std::string& name); |
| |
| SyncMergeResult StartInitialSync(); |
| |
| SupervisedUserRegistrationUtility::RegistrationCallback |
| GetRegistrationCallback(); |
| |
| SupervisedUserRegistrationUtility* GetRegistrationUtility(); |
| |
| void Acknowledge(); |
| |
| PrefService* prefs() { return profile_.GetTestingPrefService(); } |
| SupervisedUserSyncService* service() { return service_; } |
| SupervisedUserSharedSettingsService* shared_settings_service() { |
| return shared_settings_service_; |
| } |
| MockChangeProcessor* change_processor() { return change_processor_; } |
| |
| bool received_callback() const { return received_callback_; } |
| const GoogleServiceAuthError& error() const { return error_; } |
| const std::string& token() const { return token_; } |
| |
| private: |
| void OnSupervisedUserRegistered(const GoogleServiceAuthError& error, |
| const std::string& token); |
| |
| content::TestBrowserThreadBundle thread_bundle_; |
| base::RunLoop run_loop_; |
| TestingProfile profile_; |
| SupervisedUserSyncService* service_; |
| SupervisedUserSharedSettingsService* shared_settings_service_; |
| std::unique_ptr<SupervisedUserRegistrationUtility> registration_utility_; |
| |
| // Owned by the SupervisedUserSyncService. |
| MockChangeProcessor* change_processor_; |
| |
| // A unique ID for creating "remote" Sync data. |
| int64_t sync_data_id_; |
| |
| // Whether OnSupervisedUserRegistered has been called. |
| bool received_callback_; |
| |
| // Hold the registration result (either an error, or a token). |
| GoogleServiceAuthError error_; |
| std::string token_; |
| |
| base::WeakPtrFactory<SupervisedUserRegistrationUtilityTest> weak_ptr_factory_; |
| }; |
| |
| SupervisedUserRegistrationUtilityTest::SupervisedUserRegistrationUtilityTest() |
| : change_processor_(NULL), |
| sync_data_id_(0), |
| received_callback_(false), |
| error_(GoogleServiceAuthError::NUM_STATES), |
| weak_ptr_factory_(this) { |
| service_ = SupervisedUserSyncServiceFactory::GetForProfile(&profile_); |
| shared_settings_service_ = |
| SupervisedUserSharedSettingsServiceFactory::GetForBrowserContext( |
| &profile_); |
| } |
| |
| SupervisedUserRegistrationUtilityTest:: |
| ~SupervisedUserRegistrationUtilityTest() { |
| EXPECT_FALSE(weak_ptr_factory_.HasWeakPtrs()); |
| } |
| |
| void SupervisedUserRegistrationUtilityTest::TearDown() { |
| content::RunAllTasksUntilIdle(); |
| } |
| |
| std::unique_ptr<SyncChangeProcessor> |
| SupervisedUserRegistrationUtilityTest::CreateChangeProcessor() { |
| EXPECT_FALSE(change_processor_); |
| change_processor_ = new MockChangeProcessor(); |
| return std::unique_ptr<SyncChangeProcessor>(change_processor_); |
| } |
| |
| std::unique_ptr<SyncErrorFactory> |
| SupervisedUserRegistrationUtilityTest::CreateErrorFactory() { |
| return std::unique_ptr<SyncErrorFactory>(new syncer::SyncErrorFactoryMock()); |
| } |
| |
| SyncMergeResult SupervisedUserRegistrationUtilityTest::StartInitialSync() { |
| SyncDataList initial_sync_data; |
| SyncMergeResult result = |
| service()->MergeDataAndStartSyncing(SUPERVISED_USERS, |
| initial_sync_data, |
| CreateChangeProcessor(), |
| CreateErrorFactory()); |
| EXPECT_FALSE(result.error().IsSet()); |
| return result; |
| } |
| |
| SupervisedUserRegistrationUtility::RegistrationCallback |
| SupervisedUserRegistrationUtilityTest::GetRegistrationCallback() { |
| return base::Bind( |
| &SupervisedUserRegistrationUtilityTest::OnSupervisedUserRegistered, |
| weak_ptr_factory_.GetWeakPtr()); |
| } |
| |
| SupervisedUserRegistrationUtility* |
| SupervisedUserRegistrationUtilityTest::GetRegistrationUtility() { |
| if (registration_utility_.get()) |
| return registration_utility_.get(); |
| |
| std::unique_ptr<SupervisedUserRefreshTokenFetcher> token_fetcher( |
| new MockSupervisedUserRefreshTokenFetcher); |
| registration_utility_.reset(SupervisedUserRegistrationUtility::CreateImpl( |
| prefs(), std::move(token_fetcher), service(), shared_settings_service())); |
| return registration_utility_.get(); |
| } |
| |
| void SupervisedUserRegistrationUtilityTest::Acknowledge() { |
| SyncChangeList new_changes; |
| for (const SyncChange& sync_change : change_processor()->changes()) { |
| EXPECT_EQ(SyncChange::ACTION_ADD, sync_change.change_type()); |
| ::sync_pb::EntitySpecifics specifics = |
| sync_change.sync_data().GetSpecifics(); |
| EXPECT_FALSE(specifics.managed_user().acknowledged()); |
| specifics.mutable_managed_user()->set_acknowledged(true); |
| new_changes.push_back( |
| SyncChange(FROM_HERE, |
| SyncChange::ACTION_UPDATE, |
| SyncData::CreateRemoteData( |
| ++sync_data_id_, |
| specifics, |
| base::Time(), |
| syncer::AttachmentIdList(), |
| syncer::AttachmentServiceProxyForTest::Create()))); |
| } |
| service()->ProcessSyncChanges(FROM_HERE, new_changes); |
| |
| run_loop_.Run(); |
| } |
| |
| void SupervisedUserRegistrationUtilityTest::OnSupervisedUserRegistered( |
| const GoogleServiceAuthError& error, |
| const std::string& token) { |
| received_callback_ = true; |
| error_ = error; |
| token_ = token; |
| run_loop_.Quit(); |
| } |
| |
| TEST_F(SupervisedUserRegistrationUtilityTest, Register) { |
| StartInitialSync(); |
| GetRegistrationUtility()->Register( |
| SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId(), |
| SupervisedUserRegistrationInfo(base::ASCIIToUTF16("Dug"), 0), |
| GetRegistrationCallback()); |
| EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kSupervisedUsers)->size()); |
| Acknowledge(); |
| |
| EXPECT_TRUE(received_callback()); |
| EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); |
| EXPECT_FALSE(token().empty()); |
| } |
| |
| TEST_F(SupervisedUserRegistrationUtilityTest, RegisterBeforeInitialSync) { |
| GetRegistrationUtility()->Register( |
| SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId(), |
| SupervisedUserRegistrationInfo(base::ASCIIToUTF16("Nemo"), 5), |
| GetRegistrationCallback()); |
| EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kSupervisedUsers)->size()); |
| StartInitialSync(); |
| Acknowledge(); |
| |
| EXPECT_TRUE(received_callback()); |
| EXPECT_EQ(GoogleServiceAuthError::NONE, error().state()); |
| EXPECT_FALSE(token().empty()); |
| } |
| |
| TEST_F(SupervisedUserRegistrationUtilityTest, |
| SyncServiceShutdownBeforeRegFinish) { |
| StartInitialSync(); |
| GetRegistrationUtility()->Register( |
| SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId(), |
| SupervisedUserRegistrationInfo(base::ASCIIToUTF16("Remy"), 12), |
| GetRegistrationCallback()); |
| EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kSupervisedUsers)->size()); |
| service()->Shutdown(); |
| EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kSupervisedUsers)->size()); |
| EXPECT_TRUE(received_callback()); |
| EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, error().state()); |
| EXPECT_EQ(std::string(), token()); |
| } |
| |
| TEST_F(SupervisedUserRegistrationUtilityTest, StopSyncingBeforeRegFinish) { |
| StartInitialSync(); |
| GetRegistrationUtility()->Register( |
| SupervisedUserRegistrationUtility::GenerateNewSupervisedUserId(), |
| SupervisedUserRegistrationInfo(base::ASCIIToUTF16("Mike"), 17), |
| GetRegistrationCallback()); |
| EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kSupervisedUsers)->size()); |
| service()->StopSyncing(SUPERVISED_USERS); |
| EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kSupervisedUsers)->size()); |
| EXPECT_TRUE(received_callback()); |
| EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, error().state()); |
| EXPECT_EQ(std::string(), token()); |
| } |