blob: 60e4a3578c1666670710461924f047b542965882 [file] [log] [blame]
// Copyright 2013 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 <string>
#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/managed_mode/managed_user_refresh_token_fetcher.h"
#include "chrome/browser/managed_mode/managed_user_registration_service.h"
#include "chrome/browser/prefs/scoped_user_pref_update.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_pref_service_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_error_factory_mock.h"
#include "sync/protocol/sync.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
using sync_pb::ManagedUserSpecifics;
using syncer::MANAGED_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 kManagedUserToken[] = "managedusertoken";
class MockChangeProcessor : public SyncChangeProcessor {
public:
MockChangeProcessor() {}
virtual ~MockChangeProcessor() {}
// SyncChangeProcessor implementation:
virtual SyncError ProcessSyncChanges(
const tracked_objects::Location& from_here,
const SyncChangeList& change_list) OVERRIDE;
const SyncChangeList& changes() const { return change_list_; }
SyncChange GetChange(const std::string& id) const;
private:
SyncChangeList change_list_;
};
SyncError MockChangeProcessor::ProcessSyncChanges(
const tracked_objects::Location& from_here,
const SyncChangeList& change_list) {
change_list_ = change_list;
return SyncError();
}
SyncChange MockChangeProcessor::GetChange(const std::string& id) const {
for (SyncChangeList::const_iterator it = change_list_.begin();
it != change_list_.end(); ++it) {
if (it->sync_data().GetSpecifics().managed_user().id() == id)
return *it;
}
return SyncChange();
}
class MockManagedUserRefreshTokenFetcher
: public ManagedUserRefreshTokenFetcher {
public:
MockManagedUserRefreshTokenFetcher() {}
virtual ~MockManagedUserRefreshTokenFetcher() {}
// ManagedUserRefreshTokenFetcher implementation:
virtual void Start(const std::string& managed_user_id,
const string16& name,
const std::string& device_name,
const TokenCallback& callback) OVERRIDE {
GoogleServiceAuthError error(GoogleServiceAuthError::NONE);
callback.Run(error, kManagedUserToken);
}
};
} // namespace
class ManagedUserRegistrationServiceTest : public ::testing::Test {
public:
ManagedUserRegistrationServiceTest();
virtual ~ManagedUserRegistrationServiceTest();
virtual void TearDown() OVERRIDE;
protected:
scoped_ptr<SyncChangeProcessor> CreateChangeProcessor();
scoped_ptr<SyncErrorFactory> CreateErrorFactory();
SyncData CreateRemoteData(const std::string& id, const std::string& name);
SyncMergeResult StartInitialSync();
ManagedUserRegistrationService::RegistrationCallback
GetRegistrationCallback();
void Acknowledge();
void ResetService();
PrefService* prefs() { return &prefs_; }
ManagedUserRegistrationService* service() { return service_.get(); }
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 OnManagedUserRegistered(const GoogleServiceAuthError& error,
const std::string& token);
base::MessageLoop message_loop_;
base::RunLoop run_loop_;
base::WeakPtrFactory<ManagedUserRegistrationServiceTest> weak_ptr_factory_;
TestingPrefServiceSyncable prefs_;
scoped_ptr<ManagedUserRegistrationService> service_;
// Owned by the ManagedUserRegistrationService.
MockChangeProcessor* change_processor_;
// A unique ID for creating "remote" Sync data.
int64 sync_data_id_;
// Whether OnManagedUserRegistered has been called.
bool received_callback_;
// Hold the registration result (either an error, or a token).
GoogleServiceAuthError error_;
std::string token_;
};
ManagedUserRegistrationServiceTest::ManagedUserRegistrationServiceTest()
: weak_ptr_factory_(this),
change_processor_(NULL),
sync_data_id_(0),
received_callback_(false),
error_(GoogleServiceAuthError::NUM_STATES) {
ManagedUserRegistrationService::RegisterProfilePrefs(prefs_.registry());
scoped_ptr<ManagedUserRefreshTokenFetcher> token_fetcher(
new MockManagedUserRefreshTokenFetcher);
service_.reset(
new ManagedUserRegistrationService(&prefs_, token_fetcher.Pass()));
}
ManagedUserRegistrationServiceTest::~ManagedUserRegistrationServiceTest() {
EXPECT_FALSE(weak_ptr_factory_.HasWeakPtrs());
}
void ManagedUserRegistrationServiceTest::TearDown() {
content::BrowserThread::GetBlockingPool()->FlushForTesting();
base::RunLoop().RunUntilIdle();
}
scoped_ptr<SyncChangeProcessor>
ManagedUserRegistrationServiceTest::CreateChangeProcessor() {
EXPECT_FALSE(change_processor_);
change_processor_ = new MockChangeProcessor();
return scoped_ptr<SyncChangeProcessor>(change_processor_);
}
scoped_ptr<SyncErrorFactory>
ManagedUserRegistrationServiceTest::CreateErrorFactory() {
return scoped_ptr<SyncErrorFactory>(new syncer::SyncErrorFactoryMock());
}
SyncData ManagedUserRegistrationServiceTest::CreateRemoteData(
const std::string& id,
const std::string& name) {
::sync_pb::EntitySpecifics specifics;
specifics.mutable_managed_user()->set_id(id);
specifics.mutable_managed_user()->set_name(name);
specifics.mutable_managed_user()->set_acknowledged(true);
return SyncData::CreateRemoteData(++sync_data_id_, specifics, base::Time());
}
SyncMergeResult ManagedUserRegistrationServiceTest::StartInitialSync() {
SyncDataList initial_sync_data;
SyncMergeResult result =
service()->MergeDataAndStartSyncing(MANAGED_USERS,
initial_sync_data,
CreateChangeProcessor(),
CreateErrorFactory());
EXPECT_FALSE(result.error().IsSet());
return result;
}
ManagedUserRegistrationService::RegistrationCallback
ManagedUserRegistrationServiceTest::GetRegistrationCallback() {
return base::Bind(
&ManagedUserRegistrationServiceTest::OnManagedUserRegistered,
weak_ptr_factory_.GetWeakPtr());
}
void ManagedUserRegistrationServiceTest::Acknowledge() {
SyncChangeList new_changes;
const SyncChangeList& changes = change_processor()->changes();
for (SyncChangeList::const_iterator it = changes.begin(); it != changes.end();
++it) {
EXPECT_EQ(SyncChange::ACTION_ADD, it->change_type());
::sync_pb::EntitySpecifics specifics = it->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())));
}
service()->ProcessSyncChanges(FROM_HERE, new_changes);
run_loop_.Run();
}
void ManagedUserRegistrationServiceTest::ResetService() {
service_->StopSyncing(MANAGED_USERS);
service_->Shutdown();
service_.reset();
}
void ManagedUserRegistrationServiceTest::OnManagedUserRegistered(
const GoogleServiceAuthError& error,
const std::string& token) {
received_callback_ = true;
error_ = error;
token_ = token;
run_loop_.Quit();
}
TEST_F(ManagedUserRegistrationServiceTest, MergeEmpty) {
SyncMergeResult result = StartInitialSync();
EXPECT_EQ(0, result.num_items_added());
EXPECT_EQ(0, result.num_items_modified());
EXPECT_EQ(0, result.num_items_deleted());
EXPECT_EQ(0, result.num_items_before_association());
EXPECT_EQ(0, result.num_items_after_association());
EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
EXPECT_EQ(0u, change_processor()->changes().size());
ResetService();
}
TEST_F(ManagedUserRegistrationServiceTest, MergeExisting) {
const char kNameKey[] = "name";
const char kAcknowledgedKey[] = "acknowledged";
const char kUserId1[] = "aaaaa";
const char kUserId2[] = "bbbbb";
const char kUserId3[] = "ccccc";
const char kUserId4[] = "ddddd";
const char kName1[] = "Anchor";
const char kName2[] = "Buzz";
const char kName3[] = "Crush";
const char kName4[] = "Dory";
{
DictionaryPrefUpdate update(prefs(), prefs::kManagedUsers);
DictionaryValue* managed_users = update.Get();
DictionaryValue* dict = new DictionaryValue;
dict->SetString(kNameKey, kName1);
managed_users->Set(kUserId1, dict);
dict = new DictionaryValue;
dict->SetString(kNameKey, kName2);
dict->SetBoolean(kAcknowledgedKey, true);
managed_users->Set(kUserId2, dict);
}
SyncDataList initial_sync_data;
initial_sync_data.push_back(CreateRemoteData(kUserId2, kName2));
initial_sync_data.push_back(CreateRemoteData(kUserId3, kName3));
initial_sync_data.push_back(CreateRemoteData(kUserId4, kName4));
SyncMergeResult result =
service()->MergeDataAndStartSyncing(MANAGED_USERS,
initial_sync_data,
CreateChangeProcessor(),
CreateErrorFactory());
EXPECT_FALSE(result.error().IsSet());
EXPECT_EQ(2, result.num_items_added());
EXPECT_EQ(1, result.num_items_modified());
EXPECT_EQ(0, result.num_items_deleted());
EXPECT_EQ(2, result.num_items_before_association());
EXPECT_EQ(4, result.num_items_after_association());
const DictionaryValue* managed_users =
prefs()->GetDictionary(prefs::kManagedUsers);
EXPECT_EQ(4u, managed_users->size());
{
const DictionaryValue* managed_user = NULL;
ASSERT_TRUE(managed_users->GetDictionary(kUserId2, &managed_user));
ASSERT_TRUE(managed_user);
std::string name;
EXPECT_TRUE(managed_user->GetString(kNameKey, &name));
EXPECT_EQ(kName2, name);
bool acknowledged = false;
EXPECT_TRUE(managed_user->GetBoolean(kAcknowledgedKey, &acknowledged));
EXPECT_TRUE(acknowledged);
}
{
const DictionaryValue* managed_user = NULL;
ASSERT_TRUE(managed_users->GetDictionary(kUserId3, &managed_user));
ASSERT_TRUE(managed_user);
std::string name;
EXPECT_TRUE(managed_user->GetString(kNameKey, &name));
EXPECT_EQ(kName3, name);
bool acknowledged = false;
EXPECT_TRUE(managed_user->GetBoolean(kAcknowledgedKey, &acknowledged));
EXPECT_TRUE(acknowledged);
}
{
const DictionaryValue* managed_user = NULL;
ASSERT_TRUE(managed_users->GetDictionary(kUserId4, &managed_user));
ASSERT_TRUE(managed_user);
std::string name;
EXPECT_TRUE(managed_user->GetString(kNameKey, &name));
EXPECT_EQ(kName4, name);
bool acknowledged = false;
EXPECT_TRUE(managed_user->GetBoolean(kAcknowledgedKey, &acknowledged));
EXPECT_TRUE(acknowledged);
}
EXPECT_EQ(1u, change_processor()->changes().size());
{
SyncChange change = change_processor()->GetChange(kUserId1);
ASSERT_TRUE(change.IsValid());
EXPECT_EQ(SyncChange::ACTION_ADD, change.change_type());
const ManagedUserSpecifics& managed_user =
change.sync_data().GetSpecifics().managed_user();
EXPECT_EQ(kName1, managed_user.name());
EXPECT_FALSE(managed_user.acknowledged());
}
}
TEST_F(ManagedUserRegistrationServiceTest, Register) {
StartInitialSync();
service()->Register(ManagedUserRegistrationInfo(ASCIIToUTF16("Dug")),
GetRegistrationCallback());
EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
Acknowledge();
EXPECT_TRUE(received_callback());
EXPECT_EQ(GoogleServiceAuthError::NONE, error().state());
EXPECT_FALSE(token().empty());
}
TEST_F(ManagedUserRegistrationServiceTest, RegisterBeforeInitialSync) {
service()->Register(ManagedUserRegistrationInfo(ASCIIToUTF16("Nemo")),
GetRegistrationCallback());
EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
StartInitialSync();
Acknowledge();
EXPECT_TRUE(received_callback());
EXPECT_EQ(GoogleServiceAuthError::NONE, error().state());
EXPECT_FALSE(token().empty());
}
TEST_F(ManagedUserRegistrationServiceTest, Shutdown) {
StartInitialSync();
service()->Register(ManagedUserRegistrationInfo(ASCIIToUTF16("Remy")),
GetRegistrationCallback());
EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
ResetService();
EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
EXPECT_TRUE(received_callback());
EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, error().state());
EXPECT_EQ(std::string(), token());
}
TEST_F(ManagedUserRegistrationServiceTest, StopSyncing) {
StartInitialSync();
service()->Register(ManagedUserRegistrationInfo(ASCIIToUTF16("Mike")),
GetRegistrationCallback());
EXPECT_EQ(1u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
service()->StopSyncing(MANAGED_USERS);
EXPECT_EQ(0u, prefs()->GetDictionary(prefs::kManagedUsers)->size());
EXPECT_TRUE(received_callback());
EXPECT_EQ(GoogleServiceAuthError::REQUEST_CANCELED, error().state());
EXPECT_EQ(std::string(), token());
}