diff options
31 files changed, 376 insertions, 1768 deletions
diff --git a/chrome/browser/services/gcm/gcm_client_mock.cc b/chrome/browser/services/gcm/gcm_client_mock.cc index 4945a27..45f4349 100644 --- a/chrome/browser/services/gcm/gcm_client_mock.cc +++ b/chrome/browser/services/gcm/gcm_client_mock.cc @@ -13,21 +13,10 @@ namespace gcm { -namespace { - -// Converts the 8-byte prefix of a string into a uint64 value. -uint64 HashToUInt64(const std::string& hash) { - uint64 value; - DCHECK_GE(hash.size(), sizeof(value)); - memcpy(&value, hash.data(), sizeof(value)); - return base::HostToNet64(value); -} - -} // namespace - -GCMClientMock::GCMClientMock(Status status) - : status_(status), - simulate_server_error_(false) { +GCMClientMock::GCMClientMock(Status status, ErrorSimulation error_simulation) + : delegate_(NULL), + status_(status), + error_simulation_(error_simulation) { } GCMClientMock::~GCMClientMock() { @@ -38,60 +27,36 @@ void GCMClientMock::Initialize( const base::FilePath& store_path, const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner, const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter) { + url_request_context_getter, + Delegate* delegate) { + delegate_ = delegate; } -void GCMClientMock::SetUserDelegate(const std::string& username, - Delegate* delegate) { +void GCMClientMock::CheckOut() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - - if (delegate) - delegates_[username] = delegate; - else - delegates_.erase(username); } -void GCMClientMock::CheckIn(const std::string& username) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - - // Simulate the android_id and secret by some sort of hashing. - CheckinInfo checkin_info; - if (!simulate_server_error_) - checkin_info = GetCheckinInfoFromUsername(username); - - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&GCMClientMock::CheckInFinished, - base::Unretained(this), - username, - checkin_info)); -} - -void GCMClientMock::Register(const std::string& username, - const std::string& app_id, +void GCMClientMock::Register(const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); std::string registration_id; - if (!simulate_server_error_) + if (error_simulation_ == ALWAYS_SUCCEED) registration_id = GetRegistrationIdFromSenderIds(sender_ids); base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&GCMClientMock::RegisterFinished, base::Unretained(this), - username, app_id, registration_id)); } -void GCMClientMock::Unregister(const std::string& username, - const std::string& app_id) { +void GCMClientMock::Unregister(const std::string& app_id) { } -void GCMClientMock::Send(const std::string& username, - const std::string& app_id, +void GCMClientMock::Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); @@ -100,7 +65,6 @@ void GCMClientMock::Send(const std::string& username, FROM_HERE, base::Bind(&GCMClientMock::SendFinished, base::Unretained(this), - username, app_id, message.id)); } @@ -109,8 +73,7 @@ bool GCMClientMock::IsReady() const { return status_ == READY; } -void GCMClientMock::ReceiveMessage(const std::string& username, - const std::string& app_id, +void GCMClientMock::ReceiveMessage(const std::string& app_id, const IncomingMessage& message) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); @@ -119,13 +82,11 @@ void GCMClientMock::ReceiveMessage(const std::string& username, FROM_HERE, base::Bind(&GCMClientMock::MessageReceived, base::Unretained(this), - username, app_id, message)); } -void GCMClientMock::DeleteMessages(const std::string& username, - const std::string& app_id) { +void GCMClientMock::DeleteMessages(const std::string& app_id) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); content::BrowserThread::PostTask( @@ -133,7 +94,6 @@ void GCMClientMock::DeleteMessages(const std::string& username, FROM_HERE, base::Bind(&GCMClientMock::MessagesDeleted, base::Unretained(this), - username, app_id)); } @@ -150,15 +110,6 @@ void GCMClientMock::SetReady() { } // static -GCMClient::CheckinInfo GCMClientMock::GetCheckinInfoFromUsername( - const std::string& username) { - CheckinInfo checkin_info; - checkin_info.android_id = HashToUInt64(username); - checkin_info.secret = checkin_info.android_id / 10; - return checkin_info; -} - -// static std::string GCMClientMock::GetRegistrationIdFromSenderIds( const std::vector<std::string>& sender_ids) { // GCMProfileService normalizes the sender IDs by making them sorted. @@ -180,36 +131,15 @@ std::string GCMClientMock::GetRegistrationIdFromSenderIds( return registration_id; } -GCMClient::Delegate* GCMClientMock::GetDelegate( - const std::string& username) const { - std::map<std::string, Delegate*>::const_iterator iter = - delegates_.find(username); - return iter == delegates_.end() ? NULL : iter->second; -} - -void GCMClientMock::CheckInFinished(std::string username, - CheckinInfo checkin_info) { - GCMClient::Delegate* delegate = GetDelegate(username); - DCHECK(delegate); - delegate->OnCheckInFinished( - checkin_info, checkin_info.IsValid() ? SUCCESS : SERVER_ERROR); -} - -void GCMClientMock::RegisterFinished(std::string username, - std::string app_id, - std::string registrion_id) { - GCMClient::Delegate* delegate = GetDelegate(username); - DCHECK(delegate); - delegate->OnRegisterFinished( +void GCMClientMock::RegisterFinished(const std::string& app_id, + const std::string& registrion_id) { + delegate_->OnRegisterFinished( app_id, registrion_id, registrion_id.empty() ? SERVER_ERROR : SUCCESS); } -void GCMClientMock::SendFinished(std::string username, - std::string app_id, - std::string message_id) { - GCMClient::Delegate* delegate = GetDelegate(username); - DCHECK(delegate); - delegate->OnSendFinished(app_id, message_id, SUCCESS); +void GCMClientMock::SendFinished(const std::string& app_id, + const std::string& message_id) { + delegate_->OnSendFinished(app_id, message_id, SUCCESS); // Simulate send error if message id contains a hint. if (message_id.find("error") != std::string::npos) { @@ -217,41 +147,31 @@ void GCMClientMock::SendFinished(std::string username, FROM_HERE, base::Bind(&GCMClientMock::MessageSendError, base::Unretained(this), - username, app_id, message_id), base::TimeDelta::FromMilliseconds(200)); } } -void GCMClientMock::MessageReceived(std::string username, - std::string app_id, - IncomingMessage message) { - GCMClient::Delegate* delegate = GetDelegate(username); - if (delegate) - delegate->OnMessageReceived(app_id, message); +void GCMClientMock::MessageReceived(const std::string& app_id, + const IncomingMessage& message) { + if (delegate_) + delegate_->OnMessageReceived(app_id, message); } -void GCMClientMock::MessagesDeleted(std::string username, std::string app_id) { - GCMClient::Delegate* delegate = GetDelegate(username); - if (delegate) - delegate->OnMessagesDeleted(app_id); +void GCMClientMock::MessagesDeleted(const std::string& app_id) { + if (delegate_) + delegate_->OnMessagesDeleted(app_id); } -void GCMClientMock::MessageSendError(std::string username, - std::string app_id, - std::string message_id) { - GCMClient::Delegate* delegate = GetDelegate(username); - if (delegate) - delegate->OnMessageSendError(app_id, message_id, NETWORK_ERROR); +void GCMClientMock::MessageSendError(const std::string& app_id, + const std::string& message_id) { + if (delegate_) + delegate_->OnMessageSendError(app_id, message_id, NETWORK_ERROR); } void GCMClientMock::SetReadyOnIO() { - for (std::map<std::string, Delegate*>::const_iterator iter = - delegates_.begin(); - iter != delegates_.end(); ++iter) { - iter->second->OnGCMReady(); - } + delegate_->OnGCMReady(); } } // namespace gcm diff --git a/chrome/browser/services/gcm/gcm_client_mock.h b/chrome/browser/services/gcm/gcm_client_mock.h index 62397ee..485a6a8 100644 --- a/chrome/browser/services/gcm/gcm_client_mock.h +++ b/chrome/browser/services/gcm/gcm_client_mock.h @@ -5,8 +5,6 @@ #ifndef CHROME_BROWSER_SERVICES_GCM_GCM_CLIENT_MOCK_H_ #define CHROME_BROWSER_SERVICES_GCM_GCM_CLIENT_MOCK_H_ -#include <map> - #include "base/compiler_specific.h" #include "google_apis/gcm/gcm_client.h" @@ -19,7 +17,14 @@ class GCMClientMock : public GCMClient { READY }; - explicit GCMClientMock(Status status); + enum ErrorSimulation { + ALWAYS_SUCCEED, + FORCE_ERROR + }; + + // |status| denotes if the fake client is ready or not at the beginning. + // |error_simulation| denotes if we should simulate server error. + GCMClientMock(Status status, ErrorSimulation error_simulation); virtual ~GCMClientMock(); // Overridden from GCMClient: @@ -29,68 +34,45 @@ class GCMClientMock : public GCMClient { const base::FilePath& store_path, const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner, const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter) OVERRIDE; - virtual void SetUserDelegate(const std::string& username, - Delegate* delegate) OVERRIDE; - virtual void CheckIn(const std::string& username) OVERRIDE; - virtual void Register(const std::string& username, - const std::string& app_id, + url_request_context_getter, + Delegate* delegate) OVERRIDE; + virtual void CheckOut() OVERRIDE; + virtual void Register(const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids) OVERRIDE; - virtual void Unregister(const std::string& username, - const std::string& app_id) OVERRIDE; - virtual void Send(const std::string& username, - const std::string& app_id, + virtual void Unregister(const std::string& app_id) OVERRIDE; + virtual void Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) OVERRIDE; virtual bool IsReady() const OVERRIDE; // Simulate receiving something from the server. // Called on UI thread. - void ReceiveMessage(const std::string& username, - const std::string& app_id, + void ReceiveMessage(const std::string& app_id, const IncomingMessage& message); - void DeleteMessages(const std::string& username, const std::string& app_id); - - void set_simulate_server_error(bool simulate_server_error) { - simulate_server_error_ = simulate_server_error; - } + void DeleteMessages(const std::string& app_id); // Can only transition from non-ready to ready. void SetReady(); - static CheckinInfo GetCheckinInfoFromUsername(const std::string& username); static std::string GetRegistrationIdFromSenderIds( const std::vector<std::string>& sender_ids); private: - Delegate* GetDelegate(const std::string& username) const; - // Called on IO thread. - // TODO(fgorski): Update parameters to const ref. - void CheckInFinished(std::string username, CheckinInfo checkin_info); - void RegisterFinished(std::string username, - std::string app_id, - std::string registrion_id); - void SendFinished(std::string username, - std::string app_id, - std::string message_id); - void MessageReceived(std::string username, - std::string app_id, - IncomingMessage message); - void MessagesDeleted(std::string username, std::string app_id); - void MessageSendError(std::string username, - std::string app_id, - std::string message_id); + void RegisterFinished(const std::string& app_id, + const std::string& registrion_id); + void SendFinished(const std::string& app_id, const std::string& message_id); + void MessageReceived(const std::string& app_id, + const IncomingMessage& message); + void MessagesDeleted(const std::string& app_id); + void MessageSendError(const std::string& app_id, + const std::string& message_id); void SetReadyOnIO(); - std::map<std::string, Delegate*> delegates_; - + Delegate* delegate_; Status status_; - - // The testing code could set this to simulate the server error in order to - // test the error scenario. - bool simulate_server_error_; + ErrorSimulation error_simulation_; DISALLOW_COPY_AND_ASSIGN(GCMClientMock); }; diff --git a/chrome/browser/services/gcm/gcm_profile_service.cc b/chrome/browser/services/gcm/gcm_profile_service.cc index c294c51..b5c0ba8 100644 --- a/chrome/browser/services/gcm/gcm_profile_service.cc +++ b/chrome/browser/services/gcm/gcm_profile_service.cc @@ -102,11 +102,13 @@ class GCMProfileService::DelayedTaskController { // Adds a task that will be invoked once we're ready. void AddTask(const std::string& app_id, base::Closure task); - // Marks that GCM is ready. GCM is ready only when GCMClient is ready and - // the user check-in is completed. + // Sets GCM ready status. GCM is ready only when check-in is completed and + // the GCMClient is fully initialized. If it is set to ready for the first + // time, all the pending tasks for any ready apps will be run. void SetGCMReady(); - // Marks that the app is ready to have operations performed. + // Sets ready status for the app. If GCM is already ready, all the pending + // tasks for this app will be run. void SetAppReady(const std::string& app_id); // Returns true if it is ready to perform operations for an app. @@ -234,8 +236,6 @@ class GCMProfileService::IOWorker // Overridden from GCMClient::Delegate: // Called on IO thread. - virtual void OnCheckInFinished(const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) OVERRIDE; virtual void OnRegisterFinished(const std::string& app_id, const std::string& registration_id, GCMClient::Result result) OVERRIDE; @@ -249,19 +249,15 @@ class GCMProfileService::IOWorker virtual void OnMessageSendError(const std::string& app_id, const std::string& message_id, GCMClient::Result result) OVERRIDE; - virtual GCMClient::CheckinInfo GetCheckinInfo() const OVERRIDE; virtual void OnGCMReady() OVERRIDE; // Called on IO thread. void Initialize( - scoped_ptr<GCMClient> gcm_client, + GCMClientFactory* gcm_client_factory, const base::FilePath& store_path, const scoped_refptr<net::URLRequestContextGetter>& url_request_context_getter); - void SetUser(const std::string& username); - void RemoveUser(); - void CheckIn(); - void SetCheckinInfo(const GCMClient::CheckinInfo& checkin_info); + void Reset(); void CheckOut(); void Register(const std::string& app_id, const std::vector<std::string>& sender_ids, @@ -278,13 +274,6 @@ class GCMProfileService::IOWorker const base::WeakPtr<GCMProfileService> service_; scoped_ptr<GCMClient> gcm_client_; - - // The username (email address) of the signed-in user. - std::string username_; - - // The checkin info obtained from the server for the signed in user associated - // with the profile. - GCMClient::CheckinInfo checkin_info_; }; GCMProfileService::IOWorker::IOWorker( @@ -297,13 +286,13 @@ GCMProfileService::IOWorker::~IOWorker() { } void GCMProfileService::IOWorker::Initialize( - scoped_ptr<GCMClient> gcm_client, + GCMClientFactory* gcm_client_factory, const base::FilePath& store_path, const scoped_refptr<net::URLRequestContextGetter>& url_request_context_getter) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - gcm_client_ = gcm_client.Pass(); + gcm_client_ = gcm_client_factory->BuildInstance().Pass(); checkin_proto::ChromeBuildProto chrome_build_proto; chrome_build_proto.set_platform(GetPlatform()); @@ -320,7 +309,8 @@ void GCMProfileService::IOWorker::Initialize( gcm_client_->Initialize(chrome_build_proto, store_path, blocking_task_runner, - url_request_context_getter); + url_request_context_getter, + this); content::BrowserThread::PostTask( content::BrowserThread::UI, @@ -330,20 +320,12 @@ void GCMProfileService::IOWorker::Initialize( gcm_client_->IsReady())); } -void GCMProfileService::IOWorker::OnCheckInFinished( - const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) { +void GCMProfileService::IOWorker::Reset() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - checkin_info_ = checkin_info; - - content::BrowserThread::PostTask( - content::BrowserThread::UI, - FROM_HERE, - base::Bind(&GCMProfileService::CheckInFinished, - service_, - checkin_info_, - result)); + // GCMClient instance must be destroyed from the same thread where it was + // created. + gcm_client_.reset(); } void GCMProfileService::IOWorker::OnRegisterFinished( @@ -419,10 +401,6 @@ void GCMProfileService::IOWorker::OnMessageSendError( result)); } -GCMClient::CheckinInfo GCMProfileService::IOWorker::GetCheckinInfo() const { - return checkin_info_; -} - void GCMProfileService::IOWorker::OnGCMReady() { content::BrowserThread::PostTask( content::BrowserThread::UI, @@ -431,41 +409,11 @@ void GCMProfileService::IOWorker::OnGCMReady() { service_)); } -void GCMProfileService::IOWorker::SetUser(const std::string& username) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - DCHECK(username_.empty() && !username.empty()); - - username_ = username; - gcm_client_->SetUserDelegate(username_, this); -} - -void GCMProfileService::IOWorker::RemoveUser() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - - if (username_.empty()) - return; - gcm_client_->SetUserDelegate(username_, NULL); - username_.clear(); -} - -void GCMProfileService::IOWorker::CheckIn() { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - - gcm_client_->CheckIn(username_); -} - -void GCMProfileService::IOWorker::SetCheckinInfo( - const GCMClient::CheckinInfo& checkin_info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - - checkin_info_ = checkin_info; -} - void GCMProfileService::IOWorker::CheckOut() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - checkin_info_.Reset(); - RemoveUser(); + gcm_client_->CheckOut(); + gcm_client_.reset(); } void GCMProfileService::IOWorker::Register( @@ -473,16 +421,14 @@ void GCMProfileService::IOWorker::Register( const std::vector<std::string>& sender_ids, const std::string& cert) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - DCHECK(!username_.empty() && checkin_info_.IsValid()); - gcm_client_->Register(username_, app_id, cert, sender_ids); + gcm_client_->Register(app_id, cert, sender_ids); } void GCMProfileService::IOWorker::Unregister(const std::string& app_id) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - DCHECK(!username_.empty() && checkin_info_.IsValid()); - gcm_client_->Unregister(username_, app_id); + gcm_client_->Unregister(app_id); } void GCMProfileService::IOWorker::Send( @@ -490,9 +436,8 @@ void GCMProfileService::IOWorker::Send( const std::string& receiver_id, const GCMClient::OutgoingMessage& message) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - DCHECK(!username_.empty() && checkin_info_.IsValid()); - gcm_client_->Send(username_, app_id, receiver_id, message); + gcm_client_->Send(app_id, receiver_id, message); } GCMProfileService::RegistrationInfo::RegistrationInfo() { @@ -534,37 +479,22 @@ void GCMProfileService::RegisterProfilePrefs( prefs::kGCMChannelEnabled, on_by_default, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterUint64Pref( - prefs::kGCMUserAccountID, - 0, - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); - registry->RegisterStringPref( - prefs::kGCMUserToken, - "", - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); } GCMProfileService::GCMProfileService(Profile* profile) : profile_(profile), gcm_client_ready_(false), - checkin_info_read_(false), testing_delegate_(NULL), weak_ptr_factory_(this) { DCHECK(!profile->IsOffTheRecord()); } GCMProfileService::~GCMProfileService() { - if (username_.empty()) - return; - content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&GCMProfileService::IOWorker::RemoveUser, - io_worker_)); } -void GCMProfileService::Initialize(GCMClientFactory* gcm_client_factory) { - delayed_task_controller_.reset(new DelayedTaskController); +void GCMProfileService::Initialize( + scoped_ptr<GCMClientFactory> gcm_client_factory) { + gcm_client_factory_ = gcm_client_factory.Pass(); // This has to be done first since CheckIn depends on it. io_worker_ = new IOWorker(weak_ptr_factory_.GetWeakPtr()); @@ -573,33 +503,15 @@ void GCMProfileService::Initialize(GCMClientFactory* gcm_client_factory) { js_event_router_.reset(new extensions::GcmJsEventRouter(profile_)); #endif - scoped_ptr<GCMClient> gcm_client(gcm_client_factory->BuildInstance()); - scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = - profile_->GetRequestContext(); - - // This initializes GCMClient and also does the check to find out if GCMClient - // is ready. - content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&GCMProfileService::IOWorker::Initialize, - io_worker_, - base::Passed(&gcm_client), - profile_->GetPath().Append(chrome::kGCMStoreDirname), - url_request_context_getter)); - - // In case that the profile has been signed in before GCMProfileService is - // created. - SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_); - if (manager) - AddUser(manager->GetAuthenticatedUsername()); - registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL, content::Source<Profile>(profile_)); registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_SIGNED_OUT, content::Source<Profile>(profile_)); + registrar_.Add(this, + chrome::NOTIFICATION_PROFILE_DESTROYED, + content::Source<Profile>(profile_)); // TODO(jianli): move extension specific logic out of GCMProfileService. registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, @@ -607,6 +519,15 @@ void GCMProfileService::Initialize(GCMClientFactory* gcm_client_factory) { registrar_.Add(this, chrome:: NOTIFICATION_EXTENSION_UNINSTALLED, content::Source<Profile>(profile_)); + + // In case that the profile has been signed in before GCMProfileService is + // created. + SigninManagerBase* manager = SigninManagerFactory::GetForProfile(profile_); + if (manager) { + std::string username = manager->GetAuthenticatedUsername(); + if (!username.empty()) + CheckIn(username); + } } void GCMProfileService::Register(const std::string& app_id, @@ -647,19 +568,6 @@ void GCMProfileService::Register(const std::string& app_id, DoRegister(app_id, sender_ids, cert); } -void GCMProfileService::DoCheckIn() { - // No need to do check-in if the info has been read from prefs store. - if (checkin_info_read_) { - delayed_task_controller_->SetGCMReady(); - return; - } - - content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&GCMProfileService::IOWorker::CheckIn, io_worker_)); -} - void GCMProfileService::DoRegister(const std::string& app_id, const std::vector<std::string>& sender_ids, const std::string& cert) { @@ -763,12 +671,16 @@ void GCMProfileService::Observe(int type, case chrome::NOTIFICATION_GOOGLE_SIGNIN_SUCCESSFUL: { const GoogleServiceSigninSuccessDetails* signin_details = content::Details<GoogleServiceSigninSuccessDetails>(details).ptr(); - AddUser(signin_details->username); + // This could be called multiple times when the password changed. + if (username_ != signin_details->username) + CheckIn(signin_details->username); break; } case chrome::NOTIFICATION_GOOGLE_SIGNED_OUT: - username_.clear(); - RemoveUser(); + CheckOut(); + break; + case chrome::NOTIFICATION_PROFILE_DESTROYED: + ResetGCMClient(); break; case chrome::NOTIFICATION_EXTENSION_LOADED: { extensions::Extension* extension = @@ -790,62 +702,37 @@ void GCMProfileService::Observe(int type, } } -void GCMProfileService::AddUser(const std::string& username) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - // If re-signin occurs due to password change, there is no need to do - // check-in again. - if (username_ == username || username.empty()) - return; +void GCMProfileService::CheckIn(const std::string& username) { + DCHECK(!username.empty() && username_.empty()); username_ = username; + DCHECK(!delayed_task_controller_); + delayed_task_controller_.reset(new DelayedTaskController); + + // Let the IO thread create and initialize GCMClient. + scoped_refptr<net::URLRequestContextGetter> url_request_context_getter = + profile_->GetRequestContext(); content::BrowserThread::PostTask( content::BrowserThread::IO, FROM_HERE, - base::Bind(&GCMProfileService::IOWorker::SetUser, + base::Bind(&GCMProfileService::IOWorker::Initialize, io_worker_, - username_)); - - // Try to read persisted check-in info from the profile's prefs store. - PrefService* pref_service = profile_->GetPrefs(); - uint64 android_id = pref_service->GetUint64(prefs::kGCMUserAccountID); - std::string base64_token = pref_service->GetString(prefs::kGCMUserToken); - std::string encrypted_secret; - base::Base64Decode(base::StringPiece(base64_token), &encrypted_secret); - if (android_id && !encrypted_secret.empty()) { - std::string decrypted_secret; - Encryptor::DecryptString(encrypted_secret, &decrypted_secret); - uint64 secret = 0; - if (base::StringToUint64(decrypted_secret, &secret) && secret) { - checkin_info_read_ = true; - GCMClient::CheckinInfo checkin_info; - checkin_info.android_id = android_id; - checkin_info.secret = secret; - content::BrowserThread::PostTask( - content::BrowserThread::IO, - FROM_HERE, - base::Bind(&GCMProfileService::IOWorker::SetCheckinInfo, - io_worker_, - checkin_info)); - - if (testing_delegate_) - testing_delegate_->CheckInFinished(checkin_info, GCMClient::SUCCESS); - - return; - } - } - - // Check-in could only be initiated after GCMClient gets ready. - if (gcm_client_ready_) - DoCheckIn(); + gcm_client_factory_.get(), + profile_->GetPath().Append(chrome::kGCMStoreDirname), + url_request_context_getter)); } -void GCMProfileService::RemoveUser() { +void GCMProfileService::CheckOut() { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - PrefService* pref_service = profile_->GetPrefs(); - pref_service->ClearPref(prefs::kGCMUserAccountID); - pref_service->ClearPref(prefs::kGCMUserToken); + DCHECK(!username_.empty()); + username_.clear(); + + gcm_client_ready_ = false; + delayed_task_controller_.reset(); + register_callbacks_.clear(); + send_callbacks_.clear(); + registration_info_map_.clear(); content::BrowserThread::PostTask( content::BrowserThread::IO, @@ -853,6 +740,13 @@ void GCMProfileService::RemoveUser() { base::Bind(&GCMProfileService::IOWorker::CheckOut, io_worker_)); } +void GCMProfileService::ResetGCMClient() { + content::BrowserThread::PostTask( + content::BrowserThread::IO, + FROM_HERE, + base::Bind(&GCMProfileService::IOWorker::Reset, io_worker_)); +} + void GCMProfileService::EnsureAppReady(const std::string& app_id) { if (delayed_task_controller_->IsAppTracked(app_id)) return; @@ -892,31 +786,6 @@ void GCMProfileService::Unregister(const std::string& app_id) { app_id)); } -void GCMProfileService::CheckInFinished( - const GCMClient::CheckinInfo& checkin_info, GCMClient::Result result) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - - delayed_task_controller_->SetGCMReady(); - - // Save the check-in info into the profile's prefs store. - PrefService* pref_service = profile_->GetPrefs(); - pref_service->SetUint64(prefs::kGCMUserAccountID, checkin_info.android_id); - - // Encrypt the secret for persisting purpose. - std::string encrypted_secret; - Encryptor::EncryptString(base::Uint64ToString(checkin_info.secret), - &encrypted_secret); - - // |encrypted_secret| might contain binary data and our prefs store only - // works for the text. - std::string base64_token; - base::Base64Encode(encrypted_secret, &base64_token); - pref_service->SetString(prefs::kGCMUserToken, base64_token); - - if (testing_delegate_) - testing_delegate_->CheckInFinished(checkin_info, result); -} - void GCMProfileService::RegisterFinished(const std::string& app_id, const std::string& registration_id, GCMClient::Result result) { @@ -1004,7 +873,7 @@ void GCMProfileService::FinishInitializationOnUI(bool ready) { gcm_client_ready_ = ready; if (gcm_client_ready_) - DoCheckIn(); + delayed_task_controller_->SetGCMReady(); } void GCMProfileService::GCMClientReady() { @@ -1014,7 +883,7 @@ void GCMProfileService::GCMClientReady() { return; gcm_client_ready_ = true; - DoCheckIn(); + delayed_task_controller_->SetGCMReady(); } GCMEventRouter* GCMProfileService::GetEventRouter(const std::string& app_id) diff --git a/chrome/browser/services/gcm/gcm_profile_service.h b/chrome/browser/services/gcm/gcm_profile_service.h index ff6c511..03d26ac 100644 --- a/chrome/browser/services/gcm/gcm_profile_service.h +++ b/chrome/browser/services/gcm/gcm_profile_service.h @@ -51,8 +51,6 @@ class GCMProfileService : public BrowserContextKeyedService, class TestingDelegate { public: virtual GCMEventRouter* GetEventRouter() const = 0; - virtual void CheckInFinished(const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) = 0; }; // Returns true if the GCM support is enabled. @@ -64,7 +62,7 @@ class GCMProfileService : public BrowserContextKeyedService, explicit GCMProfileService(Profile* profile); virtual ~GCMProfileService(); - void Initialize(GCMClientFactory* gcm_client_factory); + void Initialize(scoped_ptr<GCMClientFactory> gcm_client_factory); // Registers |sender_id| for an app. A registration ID will be returned by // the GCM server. @@ -119,14 +117,17 @@ class GCMProfileService : public BrowserContextKeyedService, const content::NotificationSource& source, const content::NotificationDetails& details) OVERRIDE; - // Allows a signed-in user to use the GCM. If the check-in info can be found - // in the prefs store, use it directly. Otherwise, a check-in communication - // will be made with the GCM. - void AddUser(const std::string& username); + // Checks in with GCM by creating and initializing GCMClient when the profile + // has been signed in. + void CheckIn(const std::string& username); - // Stops the user from using the GCM after the user signs out. This simply - // removes the cached and persisted check-in info. - void RemoveUser(); + // Checks out of GCM when the profile has been signed out. This will erase + // all the cached and persisted data. + void CheckOut(); + + // Resets the GCMClient instance. This is called when the profile is being + // destroyed. + void ResetGCMClient(); // Ensures that the app is ready for GCM functions and events. void EnsureAppReady(const std::string& app_id); @@ -134,7 +135,6 @@ class GCMProfileService : public BrowserContextKeyedService, // Unregisters an app from using the GCM after it has been uninstalled. void Unregister(const std::string& app_id); - void DoCheckIn(); void DoRegister(const std::string& app_id, const std::vector<std::string>& sender_ids, const std::string& cert); @@ -143,8 +143,6 @@ class GCMProfileService : public BrowserContextKeyedService, const GCMClient::OutgoingMessage& message); // Callbacks posted from IO thread to UI thread. - void CheckInFinished(const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result); void RegisterFinished(const std::string& app_id, const std::string& registration_id, GCMClient::Result result); @@ -179,13 +177,12 @@ class GCMProfileService : public BrowserContextKeyedService, // The profile which owns this object. Profile* profile_; + // Used to creat the GCMClient instance. + scoped_ptr<GCMClientFactory> gcm_client_factory_; + // Flag to indicate if GCMClient is ready. bool gcm_client_ready_; - // Flag to indicate if the user check-in info has been read from the prefs - // store. - bool checkin_info_read_; - // The username of the signed-in profile. std::string username_; diff --git a/chrome/browser/services/gcm/gcm_profile_service_factory.cc b/chrome/browser/services/gcm/gcm_profile_service_factory.cc index 71e5546..aff75d8 100644 --- a/chrome/browser/services/gcm/gcm_profile_service_factory.cc +++ b/chrome/browser/services/gcm/gcm_profile_service_factory.cc @@ -41,8 +41,8 @@ BrowserContextKeyedService* GCMProfileServiceFactory::BuildServiceInstanceFor( if (!gcm::GCMProfileService::IsGCMEnabled(profile)) return NULL; GCMProfileService* service = new GCMProfileService(profile); - GCMClientFactory gcm_client_factory; - service->Initialize(&gcm_client_factory); + scoped_ptr<GCMClientFactory> gcm_client_factory(new GCMClientFactory); + service->Initialize(gcm_client_factory.Pass()); return service; } diff --git a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc index 96310b2..821f60b 100644 --- a/chrome/browser/services/gcm/gcm_profile_service_unittest.cc +++ b/chrome/browser/services/gcm/gcm_profile_service_unittest.cc @@ -73,6 +73,11 @@ class Waiter { run_loop_->Quit(); } + // Runs until UI loop becomes idle. + void PumpUILoop() { + base::MessageLoop::current()->RunUntilIdle(); + } + // Runs until IO loop becomes idle. void PumpIOLoop() { content::BrowserThread::PostTask( @@ -208,8 +213,11 @@ class FakeGCMEventRouter : public GCMEventRouter { class FakeGCMClientFactory : public GCMClientFactory { public: - explicit FakeGCMClientFactory(GCMClientMock::Status gcm_client_initial_status) + FakeGCMClientFactory( + GCMClientMock::Status gcm_client_initial_status, + GCMClientMock::ErrorSimulation gcm_client_error_simulation) : gcm_client_initial_status_(gcm_client_initial_status), + gcm_client_error_simulation_(gcm_client_error_simulation), gcm_client_(NULL) { } @@ -217,8 +225,8 @@ class FakeGCMClientFactory : public GCMClientFactory { } virtual scoped_ptr<GCMClient> BuildInstance() OVERRIDE { - DCHECK(!gcm_client_); - gcm_client_ = new GCMClientMock(gcm_client_initial_status_); + gcm_client_ = new GCMClientMock(gcm_client_initial_status_, + gcm_client_error_simulation_); return scoped_ptr<GCMClient>(gcm_client_); } @@ -226,6 +234,7 @@ class FakeGCMClientFactory : public GCMClientFactory { private: GCMClientMock::Status gcm_client_initial_status_; + GCMClientMock::ErrorSimulation gcm_client_error_simulation_; GCMClientMock* gcm_client_; DISALLOW_COPY_AND_ASSIGN(FakeGCMClientFactory); @@ -248,6 +257,7 @@ class GCMProfileServiceTestConsumer : public GCMProfileService::TestingDelegate{ extension_service_(NULL), signin_manager_(NULL), gcm_client_initial_status_(GCMClientMock::READY), + gcm_client_error_simulation_(GCMClientMock::ALWAYS_SUCCEED), registration_result_(GCMClient::SUCCESS), has_persisted_registration_info_(false), send_result_(GCMClient::SUCCESS) { @@ -267,9 +277,8 @@ class GCMProfileServiceTestConsumer : public GCMProfileService::TestingDelegate{ CommandLine::ForCurrentProcess(), base::FilePath(), false); extension_service_ = extension_system->Get(profile())->extension_service(); - // Allow a testing delegate to be passed to GCMProfileService instance. + // Enable GCM such that tests could be run on all channels. GCMProfileService::enable_gcm_for_testing_ = true; - CreateGCMProfileServiceInstance(); // Mock a GCMEventRouter. gcm_event_router_.reset(new FakeGCMEventRouter(waiter_)); @@ -324,20 +333,23 @@ class GCMProfileServiceTestConsumer : public GCMProfileService::TestingDelegate{ GCMProfileServiceFactory::GetInstance()->SetTestingFactoryAndUse( profile(), &GCMProfileServiceTestConsumer::BuildGCMProfileService)); gcm_profile_service->set_testing_delegate(this); - gcm_client_factory_.reset( - new FakeGCMClientFactory(gcm_client_initial_status_)); - gcm_profile_service->Initialize(gcm_client_factory_.get()); + scoped_ptr<GCMClientFactory> gcm_client_factory( + new FakeGCMClientFactory(gcm_client_initial_status_, + gcm_client_error_simulation_)); + gcm_profile_service->Initialize(gcm_client_factory.Pass()); + waiter_->PumpIOLoop(); } - void CheckIn(const std::string& username) { + void SignIn(const std::string& username) { signin_manager_->SignIn(username); + waiter_->PumpIOLoop(); + waiter_->PumpUILoop(); + } - // This will cause GCMProfileService to be created if not yet. This will - // also kick off the check-in if not yet. - GetGCMProfileService(); - - // Wait till the asynchronous check-in is done. - waiter_->WaitUntilCompleted(); + void SignOut() { + signin_manager_->SignOut(); + waiter_->PumpIOLoop(); + waiter_->PumpUILoop(); } void Register(const std::string& app_id, @@ -399,19 +411,23 @@ class GCMProfileServiceTestConsumer : public GCMProfileService::TestingDelegate{ } GCMClientMock* GetGCMClient() const { - return gcm_client_factory_->gcm_client(); + return static_cast<FakeGCMClientFactory*>( + GetGCMProfileService()->gcm_client_factory_.get())->gcm_client(); } const std::string& GetUsername() const { return GetGCMProfileService()->username_; } + bool IsGCMClientReady() const { + return GetGCMProfileService()->gcm_client_ready_; + } + bool ExistsCachedRegistrationInfo() const { return !GetGCMProfileService()->registration_info_map_.empty(); } Profile* profile() const { return profile_.get(); } - FakeSigninManager* signin_manager() const { return signin_manager_; } FakeGCMEventRouter* gcm_event_router() const { return gcm_event_router_.get(); } @@ -419,14 +435,15 @@ class GCMProfileServiceTestConsumer : public GCMProfileService::TestingDelegate{ void set_gcm_client_initial_status(GCMClientMock::Status status) { gcm_client_initial_status_ = status; } + void set_gcm_client_error_simulation(GCMClientMock::ErrorSimulation error) { + gcm_client_error_simulation_ = error; + } - GCMClient::CheckinInfo checkin_info() const { return checkin_info_; } const std::string& registration_id() const { return registration_id_; } GCMClient::Result registration_result() const { return registration_result_; } const std::string& send_message_id() const { return send_message_id_; } GCMClient::Result send_result() const { return send_result_; } - void clear_checkin_info() { checkin_info_.Reset(); } void clear_registration_result() { registration_id_.clear(); registration_result_ = GCMClient::UNKNOWN_ERROR; @@ -442,22 +459,14 @@ class GCMProfileServiceTestConsumer : public GCMProfileService::TestingDelegate{ return gcm_event_router_.get(); } - virtual void CheckInFinished(const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) OVERRIDE { - checkin_info_ = checkin_info; - waiter_->SignalCompleted(); - } - Waiter* waiter_; // Not owned. scoped_ptr<TestingProfile> profile_; ExtensionService* extension_service_; // Not owned. FakeSigninManager* signin_manager_; // Not owned. scoped_ptr<FakeGCMEventRouter> gcm_event_router_; - scoped_ptr<FakeGCMClientFactory> gcm_client_factory_; GCMClientMock::Status gcm_client_initial_status_; - - GCMClient::CheckinInfo checkin_info_; + GCMClientMock::ErrorSimulation gcm_client_error_simulation_; std::string registration_id_; GCMClient::Result registration_result_; @@ -515,6 +524,10 @@ class GCMProfileServiceTest : public testing::Test { waiter_.SignalCompleted(); } + void PumpUILoop() { + waiter_.PumpUILoop(); + } + void PumpIOLoop() { waiter_.PumpIOLoop(); } @@ -538,24 +551,6 @@ class GCMProfileServiceTest : public testing::Test { DISALLOW_COPY_AND_ASSIGN(GCMProfileServiceTest); }; -class ScopedGCMClientMockSimulateServerError { - public: - ScopedGCMClientMockSimulateServerError( - GCMProfileServiceTestConsumer* consumer) - : consumer_(consumer) { - consumer_->GetGCMClient()->set_simulate_server_error(true); - } - - ~ScopedGCMClientMockSimulateServerError() { - consumer_->GetGCMClient()->set_simulate_server_error(false); - } - - private: - GCMProfileServiceTestConsumer* consumer_; - - DISALLOW_COPY_AND_ASSIGN(ScopedGCMClientMockSimulateServerError); -}; - TEST_F(GCMProfileServiceTest, Incognito) { EXPECT_TRUE(GCMProfileServiceFactory::GetForProfile(profile())); @@ -571,49 +566,22 @@ TEST_F(GCMProfileServiceTest, Incognito) { } TEST_F(GCMProfileServiceTest, CreateGCMProfileServiceBeforeProfileSignIn) { - // This will cause GCMProfileService to be created. No check-in should be - // initiated at this moment since the profile has not been signed in yet. - consumer()->GetGCMProfileService(); + // Create GCMProfileService first. + consumer()->CreateGCMProfileServiceInstance(); EXPECT_TRUE(consumer()->GetUsername().empty()); - EXPECT_FALSE(consumer()->checkin_info().IsValid()); // Sign in to a profile. This will kick off the check-in. - consumer()->signin_manager()->SignIn(kTestingUsername); - - // Wait till the asynchronous check-in is done. - WaitUntilCompleted(); - - // Verify the check-in result. - EXPECT_TRUE(consumer()->checkin_info().IsValid()); - - GCMClient::CheckinInfo expected_checkin_info = - GCMClientMock::GetCheckinInfoFromUsername(kTestingUsername); - EXPECT_EQ(expected_checkin_info.android_id, - consumer()->checkin_info().android_id); - EXPECT_EQ(expected_checkin_info.secret, consumer()->checkin_info().secret); + consumer()->SignIn(kTestingUsername); + EXPECT_FALSE(consumer()->GetUsername().empty()); } TEST_F(GCMProfileServiceTest, CreateGCMProfileServiceAfterProfileSignIn) { // Sign in to a profile. This will not initiate the check-in. - consumer()->signin_manager()->SignIn(kTestingUsername); + consumer()->SignIn(kTestingUsername); - // This will cause GCMProfileService to be created and the check-in to be - // invoked. - consumer()->GetGCMProfileService(); + // Create GCMProfileService after sign-in. + consumer()->CreateGCMProfileServiceInstance(); EXPECT_FALSE(consumer()->GetUsername().empty()); - EXPECT_FALSE(consumer()->checkin_info().IsValid()); - - // Wait till the asynchronous check-in is done. - WaitUntilCompleted(); - - // Verify the check-in result. - EXPECT_TRUE(consumer()->checkin_info().IsValid()); - - GCMClient::CheckinInfo expected_checkin_info = - GCMClientMock::GetCheckinInfoFromUsername(kTestingUsername); - EXPECT_EQ(expected_checkin_info.android_id, - consumer()->checkin_info().android_id); - EXPECT_EQ(expected_checkin_info.secret, consumer()->checkin_info().secret); } TEST_F(GCMProfileServiceTest, RegsiterWhenNotSignedIn) { @@ -635,7 +603,7 @@ TEST_F(GCMProfileServiceTest, SendWhenNotSignedIn) { EXPECT_EQ(GCMClient::NOT_SIGNED_IN, consumer()->send_result()); } -// Tests single-profile. CheckIn is initiated by default. +// Tests single-profile. class GCMProfileServiceSingleProfileTest : public GCMProfileServiceTest { public: GCMProfileServiceSingleProfileTest() { @@ -647,56 +615,32 @@ class GCMProfileServiceSingleProfileTest : public GCMProfileServiceTest { virtual void SetUp() OVERRIDE { GCMProfileServiceTest::SetUp(); - consumer()->CheckIn(kTestingUsername); + consumer()->CreateGCMProfileServiceInstance(); + consumer()->SignIn(kTestingUsername); } }; -TEST_F(GCMProfileServiceSingleProfileTest, CheckInFromPrefsStore) { - // The first check-in should be successful. - EXPECT_TRUE(consumer()->checkin_info().IsValid()); - GCMClient::CheckinInfo saved_checkin_info = consumer()->checkin_info(); - consumer()->clear_checkin_info(); - - // Check-in should not reach the server. Forcing GCMClient server error should - // help catch this. - ScopedGCMClientMockSimulateServerError gcm_client_simulate_server_error( - consumer()); - - // Recreate GCMProfileService to test reading the check-in info from the - // prefs store. - consumer()->CreateGCMProfileServiceInstance(); - - EXPECT_EQ(saved_checkin_info.android_id, - consumer()->checkin_info().android_id); - EXPECT_EQ(saved_checkin_info.secret, consumer()->checkin_info().secret); -} - -TEST_F(GCMProfileServiceSingleProfileTest, CheckOut) { - EXPECT_TRUE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserAccountID)); - EXPECT_TRUE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserToken)); +TEST_F(GCMProfileServiceSingleProfileTest, SignOut) { + EXPECT_TRUE(consumer()->IsGCMClientReady()); // This will trigger check-out. - consumer()->signin_manager()->SignOut(); + consumer()->SignOut(); - EXPECT_FALSE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserAccountID)); - EXPECT_FALSE(profile()->GetPrefs()->HasPrefPath(prefs::kGCMUserToken)); + EXPECT_FALSE(consumer()->IsGCMClientReady()); } -TEST_F(GCMProfileServiceSingleProfileTest, CheckOutAndThenCheckIn) { - // The first check-in should be successful. - EXPECT_TRUE(consumer()->checkin_info().IsValid()); +TEST_F(GCMProfileServiceSingleProfileTest, SignOutAndThenSignIn) { + EXPECT_TRUE(consumer()->IsGCMClientReady()); // This will trigger check-out. - consumer()->signin_manager()->SignOut(); + consumer()->SignOut(); + + EXPECT_FALSE(consumer()->IsGCMClientReady()); // Sign-in with a different username. - consumer()->CheckIn(kTestingUsername2); + consumer()->SignIn(kTestingUsername2); - GCMClient::CheckinInfo expected_checkin_info = - GCMClientMock::GetCheckinInfoFromUsername(kTestingUsername2); - EXPECT_EQ(expected_checkin_info.android_id, - consumer()->checkin_info().android_id); - EXPECT_EQ(expected_checkin_info.secret, consumer()->checkin_info().secret); + EXPECT_TRUE(consumer()->IsGCMClientReady()); } TEST_F(GCMProfileServiceSingleProfileTest, Register) { @@ -810,17 +754,16 @@ TEST_F(GCMProfileServiceSingleProfileTest, ReadRegistrationFromStateStore) { // preparation to call register 2nd time. consumer()->clear_registration_result(); + // Register should not reach the server. Forcing GCMClient server error should + // help catch this. + consumer()->set_gcm_client_error_simulation(GCMClientMock::FORCE_ERROR); + // Simulate start-up by recreating GCMProfileService. consumer()->CreateGCMProfileServiceInstance(); // Simulate start-up by reloading extension. consumer()->ReloadExtension(extension); - // Register should not reach the server. Forcing GCMClient server error should - // help catch this. - ScopedGCMClientMockSimulateServerError gcm_client_simulate_server_error( - consumer()); - // This should read the registration info from the extension's state store. // We still need to wait since the reading from state store might happen at // the same time. @@ -872,7 +815,7 @@ TEST_F(GCMProfileServiceSingleProfileTest, TEST_F(GCMProfileServiceSingleProfileTest, RegisterAfterSignOut) { // This will trigger check-out. - consumer()->signin_manager()->SignOut(); + consumer()->SignOut(); std::vector<std::string> sender_ids; sender_ids.push_back("sender1"); @@ -925,7 +868,7 @@ TEST_F(GCMProfileServiceSingleProfileTest, Send) { TEST_F(GCMProfileServiceSingleProfileTest, SendAfterSignOut) { // This will trigger check-out. - consumer()->signin_manager()->SignOut(); + consumer()->SignOut(); GCMClient::OutgoingMessage message; message.id = "1"; @@ -965,8 +908,7 @@ TEST_F(GCMProfileServiceSingleProfileTest, MessageReceived) { GCMClient::IncomingMessage message; message.data["key1"] = "value1"; message.data["key2"] = "value2"; - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername, kTestingAppId, message); + consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, message); WaitUntilCompleted(); EXPECT_EQ(FakeGCMEventRouter::MESSAGE_EVENT, consumer()->gcm_event_router()->received_event()); @@ -974,42 +916,16 @@ TEST_F(GCMProfileServiceSingleProfileTest, MessageReceived) { EXPECT_TRUE(message.data == consumer()->gcm_event_router()->message().data); } -TEST_F(GCMProfileServiceSingleProfileTest, MessageReceivedAfterSignOut) { - // This will trigger check-out. - consumer()->signin_manager()->SignOut(); - - GCMClient::IncomingMessage message; - message.data["key1"] = "value1"; - message.data["key2"] = "value2"; - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername, kTestingAppId, message); - PumpIOLoop(); - - EXPECT_EQ(FakeGCMEventRouter::NO_EVENT, - consumer()->gcm_event_router()->received_event()); - EXPECT_TRUE(consumer()->gcm_event_router()->app_id().empty()); -} - TEST_F(GCMProfileServiceSingleProfileTest, MessagesDeleted) { - consumer()->GetGCMClient()->DeleteMessages(kTestingUsername, kTestingAppId); + consumer()->GetGCMClient()->DeleteMessages(kTestingAppId); WaitUntilCompleted(); EXPECT_EQ(FakeGCMEventRouter::MESSAGES_DELETED_EVENT, consumer()->gcm_event_router()->received_event()); EXPECT_EQ(kTestingAppId, consumer()->gcm_event_router()->app_id()); } -TEST_F(GCMProfileServiceSingleProfileTest, MessagesDeletedAfterSignOut) { - // This will trigger check-out. - consumer()->signin_manager()->SignOut(); - - consumer()->GetGCMClient()->DeleteMessages(kTestingUsername, kTestingAppId); - PumpIOLoop(); - - EXPECT_EQ(FakeGCMEventRouter::NO_EVENT, - consumer()->gcm_event_router()->received_event()); - EXPECT_TRUE(consumer()->gcm_event_router()->app_id().empty()); -} - +// Tests to make sure that GCMProfileService works for multiple profiles +// regardless how GCMClient is created. class GCMProfileServiceMultiProfileTest : public GCMProfileServiceTest { public: GCMProfileServiceMultiProfileTest() { @@ -1024,17 +940,12 @@ class GCMProfileServiceMultiProfileTest : public GCMProfileServiceTest { // Create a 2nd profile consumer. consumer2_.reset(new GCMProfileServiceTestConsumer(&waiter_)); - // This will cause GetGCMProfileService to be created for each profile. - consumer()->GetGCMProfileService(); - consumer2()->GetGCMProfileService(); + consumer()->CreateGCMProfileServiceInstance(); + consumer2()->CreateGCMProfileServiceInstance(); // Initiate check-in for each profile. - consumer2()->signin_manager()->SignIn(kTestingUsername2); - consumer()->signin_manager()->SignIn(kTestingUsername); - - // Wait till all the asynchronous check-ins are done. - WaitUntilCompleted(); - WaitUntilCompleted(); + consumer2()->SignIn(kTestingUsername2); + consumer()->SignIn(kTestingUsername); } virtual void TearDown() OVERRIDE { @@ -1050,20 +961,6 @@ class GCMProfileServiceMultiProfileTest : public GCMProfileServiceTest { scoped_ptr<GCMProfileServiceTestConsumer> consumer2_; }; -TEST_F(GCMProfileServiceMultiProfileTest, CheckIn) { - GCMClient::CheckinInfo expected_checkin_info = - GCMClientMock::GetCheckinInfoFromUsername(kTestingUsername); - EXPECT_EQ(expected_checkin_info.android_id, - consumer()->checkin_info().android_id); - EXPECT_EQ(expected_checkin_info.secret, consumer()->checkin_info().secret); - - expected_checkin_info = - GCMClientMock::GetCheckinInfoFromUsername(kTestingUsername2); - EXPECT_EQ(expected_checkin_info.android_id, - consumer2()->checkin_info().android_id); - EXPECT_EQ(expected_checkin_info.secret, consumer2()->checkin_info().secret); -} - TEST_F(GCMProfileServiceMultiProfileTest, Register) { // Register an app. std::vector<std::string> sender_ids; @@ -1141,14 +1038,12 @@ TEST_F(GCMProfileServiceMultiProfileTest, MessageReceived) { GCMClient::IncomingMessage message; message.data["key1"] = "value1"; message.data["key2"] = "value2"; - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername, kTestingAppId, message); + consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, message); // Trigger an incoming message for the same app in another profile. GCMClient::IncomingMessage message2; message2.data["foo"] = "bar"; - consumer2()->GetGCMClient()->ReceiveMessage( - kTestingUsername2, kTestingAppId, message2); + consumer2()->GetGCMClient()->ReceiveMessage(kTestingAppId, message2); WaitUntilCompleted(); WaitUntilCompleted(); @@ -1167,8 +1062,7 @@ TEST_F(GCMProfileServiceMultiProfileTest, MessageReceived) { GCMClient::IncomingMessage message3; message3.data["bar1"] = "foo1"; message3.data["bar2"] = "foo2"; - consumer2()->GetGCMClient()->ReceiveMessage( - kTestingUsername2, kTestingAppId2, message3); + consumer2()->GetGCMClient()->ReceiveMessage(kTestingAppId2, message3); WaitUntilCompleted(); @@ -1185,12 +1079,10 @@ TEST_F(GCMProfileServiceMultiProfileTest, MessageReceived) { // two apps in profile2; // 4) Send a message foe ach of two apps in profile2; // 5) Sign out of profile1. -// 6) The app in profile1 should not receive message and deleted_messages -// events; +// 6) Register/send stops working for profile1; // 7) The app in profile2 could still receive these events; // 8) Sign into profile1 with a different user. -// 9) The message to the signed-out user will be ingored. -// 10) The message to the new signed-in user will be routed. +// 9) The message to the new signed-in user will be routed. TEST_F(GCMProfileServiceMultiProfileTest, Combined) { // Register an app. std::vector<std::string> sender_ids; @@ -1238,8 +1130,7 @@ TEST_F(GCMProfileServiceMultiProfileTest, Combined) { GCMClient::IncomingMessage in_message; in_message.data["in1"] = "in_data1"; in_message.data["in1_2"] = "in_data1_2"; - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername, kTestingAppId, in_message); + consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, in_message); WaitUntilCompleted(); @@ -1253,14 +1144,12 @@ TEST_F(GCMProfileServiceMultiProfileTest, Combined) { // profile. GCMClient::IncomingMessage in_message2; in_message2.data["in2"] = "in_data2"; - consumer2()->GetGCMClient()->ReceiveMessage( - kTestingUsername2, kTestingAppId2, in_message2); + consumer2()->GetGCMClient()->ReceiveMessage(kTestingAppId2, in_message2); GCMClient::IncomingMessage in_message3; in_message3.data["in3"] = "in_data3"; in_message3.data["in3_2"] = "in_data3_2"; - consumer2()->GetGCMClient()->ReceiveMessage( - kTestingUsername2, kTestingAppId, in_message3); + consumer2()->GetGCMClient()->ReceiveMessage(kTestingAppId, in_message3); consumer2()->gcm_event_router()->clear_results(); WaitUntilCompleted(); @@ -1302,34 +1191,21 @@ TEST_F(GCMProfileServiceMultiProfileTest, Combined) { EXPECT_EQ(GCMClient::SUCCESS, consumer2()->send_result()); // Sign out of one profile. - consumer()->signin_manager()->SignOut(); - PumpIOLoop(); - - // Incoming message will be ingored for the signed-out profile. - GCMClient::IncomingMessage in_message4; - in_message4.data["in4"] = "in_data4"; - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername, kTestingAppId, in_message4); + consumer()->SignOut(); + // Register/send stops working for signed-out profile. consumer()->gcm_event_router()->clear_results(); - PumpIOLoop(); - - EXPECT_EQ(FakeGCMEventRouter::NO_EVENT, - consumer()->gcm_event_router()->received_event()); - EXPECT_TRUE(consumer()->gcm_event_router()->app_id().empty()); - - // Deleted messages event will be ingored for the signed-out profile. - consumer()->GetGCMClient()->DeleteMessages(kTestingUsername, kTestingAppId); - - PumpIOLoop(); + consumer()->Register(kTestingAppId, sender_ids); + EXPECT_TRUE(consumer()->registration_id().empty()); + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, consumer()->registration_result()); - EXPECT_EQ(FakeGCMEventRouter::NO_EVENT, - consumer()->gcm_event_router()->received_event()); - EXPECT_TRUE(consumer()->gcm_event_router()->app_id().empty()); + consumer()->gcm_event_router()->clear_results(); + consumer()->Send(kTestingAppId2, kUserId2, out_message3); + EXPECT_TRUE(consumer()->send_message_id().empty()); + EXPECT_EQ(GCMClient::NOT_SIGNED_IN, consumer()->send_result()); // Deleted messages event will go through for another signed-in profile. - consumer2()->GetGCMClient()->DeleteMessages( - kTestingUsername2, kTestingAppId2); + consumer2()->GetGCMClient()->DeleteMessages(kTestingAppId2); consumer2()->gcm_event_router()->clear_results(); WaitUntilCompleted(); @@ -1359,25 +1235,12 @@ TEST_F(GCMProfileServiceMultiProfileTest, Combined) { consumer2()->gcm_event_router()->send_result()); // Sign in with a different user. - consumer()->signin_manager()->SignIn(kTestingUsername3); - WaitUntilCompleted(); - - // Incoming message will still be ingored for the signed-out user. - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername, kTestingAppId, in_message4); - - consumer()->gcm_event_router()->clear_results(); - PumpIOLoop(); - - EXPECT_EQ(FakeGCMEventRouter::NO_EVENT, - consumer()->gcm_event_router()->received_event()); - EXPECT_TRUE(consumer()->gcm_event_router()->app_id().empty()); + consumer()->SignIn(kTestingUsername3); // Incoming message will go through for the new signed-in user. GCMClient::IncomingMessage in_message5; in_message5.data["in5"] = "in_data5"; - consumer()->GetGCMClient()->ReceiveMessage( - kTestingUsername3, kTestingAppId, in_message5); + consumer()->GetGCMClient()->ReceiveMessage(kTestingAppId, in_message5); consumer()->gcm_event_router()->clear_results(); WaitUntilCompleted(); diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 0de61a1..65a6fb2 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1303,10 +1303,6 @@ const char kProfileResetPromptMemento[] = "profile.reset_prompt_memento"; // The GCM channel's enabled state. const char kGCMChannelEnabled[] = "gcm.channel_enabled"; -// Stores the check-in info retrieved from the GCM server. -const char kGCMUserAccountID[] = "gcm.user.account_id"; -const char kGCMUserToken[] = "gcm.user.token"; - // *************** LOCAL STATE *************** // These are attached to the machine/installation diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 4eab84c..739d6d9 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -405,8 +405,6 @@ extern const char kLocalDiscoveryNotificationsEnabled[]; extern const char kProfileResetPromptMemento[]; extern const char kGCMChannelEnabled[]; -extern const char kGCMUserAccountID[]; -extern const char kGCMUserToken[]; // Local state prefs. Please add Profile prefs above instead. extern const char kCertRevocationCheckingEnabled[]; diff --git a/google_apis/gcm/base/mcs_message_unittest.cc b/google_apis/gcm/base/mcs_message_unittest.cc index 07f1d7d..4d4ef59 100644 --- a/google_apis/gcm/base/mcs_message_unittest.cc +++ b/google_apis/gcm/base/mcs_message_unittest.cc @@ -35,9 +35,8 @@ TEST_F(MCSMessageTest, Invalid) { } TEST_F(MCSMessageTest, InitInferTag) { - std::vector<int64> user_serial_numbers; scoped_ptr<mcs_proto::LoginRequest> login_request( - BuildLoginRequest(kAndroidId, kSecret, user_serial_numbers)); + BuildLoginRequest(kAndroidId, kSecret)); scoped_ptr<google::protobuf::MessageLite> login_copy( new mcs_proto::LoginRequest(*login_request)); MCSMessage message(*login_copy); @@ -54,9 +53,8 @@ TEST_F(MCSMessageTest, InitInferTag) { } TEST_F(MCSMessageTest, InitWithTag) { - std::vector<int64> user_serial_numbers; scoped_ptr<mcs_proto::LoginRequest> login_request( - BuildLoginRequest(kAndroidId, kSecret, user_serial_numbers)); + BuildLoginRequest(kAndroidId, kSecret)); scoped_ptr<google::protobuf::MessageLite> login_copy( new mcs_proto::LoginRequest(*login_request)); MCSMessage message(kLoginRequestTag, *login_copy); @@ -73,9 +71,8 @@ TEST_F(MCSMessageTest, InitWithTag) { } TEST_F(MCSMessageTest, InitPassOwnership) { - std::vector<int64> user_serial_numbers; scoped_ptr<mcs_proto::LoginRequest> login_request( - BuildLoginRequest(kAndroidId, kSecret, user_serial_numbers)); + BuildLoginRequest(kAndroidId, kSecret)); scoped_ptr<google::protobuf::MessageLite> login_copy( new mcs_proto::LoginRequest(*login_request)); MCSMessage message(kLoginRequestTag, diff --git a/google_apis/gcm/base/mcs_util.cc b/google_apis/gcm/base/mcs_util.cc index 581b1ea..54e1b29 100644 --- a/google_apis/gcm/base/mcs_util.cc +++ b/google_apis/gcm/base/mcs_util.cc @@ -45,17 +45,14 @@ const char kLoginDomain[] = "mcs.android.com"; const char kLoginDeviceIdPrefix[] = "android-"; const char kLoginSettingDefaultName[] = "new_vc"; const char kLoginSettingDefaultValue[] = "1"; -const char kLoginSettingMultiUserName[] = "u:f"; // Maximum amount of time to save an unsent outgoing message for. const int kMaxTTLSeconds = 4 * 7 * 24 * 60 * 60; // 4 weeks. } // namespace -scoped_ptr<mcs_proto::LoginRequest> BuildLoginRequest( - uint64 auth_id, - uint64 auth_token, - const std::vector<int64>& user_serial_numbers) { +scoped_ptr<mcs_proto::LoginRequest> BuildLoginRequest(uint64 auth_id, + uint64 auth_token) { // Create a hex encoded auth id for the device id field. std::string auth_id_hex; auth_id_hex = base::StringPrintf("%" PRIx64, auth_id); @@ -79,21 +76,9 @@ scoped_ptr<mcs_proto::LoginRequest> BuildLoginRequest( login_request->set_user(auth_id_str); login_request->set_use_rmq2(true); - std::string setting_name, setting_value; - if (user_serial_numbers.empty()) { - setting_name = kLoginSettingDefaultName; - setting_value = kLoginSettingDefaultValue; - } else { - setting_name = kLoginSettingMultiUserName; - for (size_t i = 0; i < user_serial_numbers.size(); ++i) { - if (i > 0) - setting_value += ","; - setting_value += base::Int64ToString(user_serial_numbers[i]); - } - } login_request->add_setting(); - login_request->mutable_setting(0)->set_name(setting_name); - login_request->mutable_setting(0)->set_value(setting_value); + login_request->mutable_setting(0)->set_name(kLoginSettingDefaultName); + login_request->mutable_setting(0)->set_value(kLoginSettingDefaultValue); return login_request.Pass(); } diff --git a/google_apis/gcm/base/mcs_util.h b/google_apis/gcm/base/mcs_util.h index 2688489..b053007 100644 --- a/google_apis/gcm/base/mcs_util.h +++ b/google_apis/gcm/base/mcs_util.h @@ -57,8 +57,7 @@ enum MCSIqStanzaExtension { // Builds a LoginRequest with the hardcoded local data. GCM_EXPORT scoped_ptr<mcs_proto::LoginRequest> BuildLoginRequest( uint64 auth_id, - uint64 auth_token, - const std::vector<int64>& user_serial_numbers); + uint64 auth_token); // Builds a StreamAck IqStanza message. GCM_EXPORT scoped_ptr<mcs_proto::IqStanza> BuildStreamAck(); diff --git a/google_apis/gcm/base/mcs_util_unittest.cc b/google_apis/gcm/base/mcs_util_unittest.cc index e932bc8..9b1a42b 100644 --- a/google_apis/gcm/base/mcs_util_unittest.cc +++ b/google_apis/gcm/base/mcs_util_unittest.cc @@ -18,17 +18,14 @@ const uint64 kAuthToken = 12345; // Build a login request protobuf. TEST(MCSUtilTest, BuildLoginRequest) { - std::vector<int64> user_serial_numbers; - user_serial_numbers.push_back(1LL); - user_serial_numbers.push_back(2LL); scoped_ptr<mcs_proto::LoginRequest> login_request = - BuildLoginRequest(kAuthId, kAuthToken, user_serial_numbers); + BuildLoginRequest(kAuthId, kAuthToken); ASSERT_EQ("login-1", login_request->id()); ASSERT_EQ(base::Uint64ToString(kAuthToken), login_request->auth_token()); ASSERT_EQ(base::Uint64ToString(kAuthId), login_request->user()); ASSERT_EQ("android-3d5c23dac2a1fa7c", login_request->device_id()); - ASSERT_EQ("u:f", login_request->setting(0).name()); - ASSERT_EQ("1,2", login_request->setting(0).value()); + ASSERT_EQ("new_vc", login_request->setting(0).name()); + ASSERT_EQ("1", login_request->setting(0).value()); // TODO(zea): test the other fields once they have valid values. } diff --git a/google_apis/gcm/engine/checkin_request.cc b/google_apis/gcm/engine/checkin_request.cc index b46415a..c8e8a8e 100644 --- a/google_apis/gcm/engine/checkin_request.cc +++ b/google_apis/gcm/engine/checkin_request.cc @@ -18,13 +18,13 @@ namespace { const char kCheckinURL[] = "https://android.clients.google.com/checkin"; const char kRequestContentType[] = "application/x-protobuf"; const int kRequestVersionValue = 2; +const int kDefaultUserSerialNumber = 0; } // namespace CheckinRequest::CheckinRequest( const CheckinRequestCallback& callback, const net::BackoffEntry::Policy& backoff_policy, const checkin_proto::ChromeBuildProto& chrome_build_proto, - int64 user_serial_number, uint64 android_id, uint64 security_token, net::URLRequestContextGetter* request_context_getter) @@ -34,7 +34,6 @@ CheckinRequest::CheckinRequest( chrome_build_proto_(chrome_build_proto), android_id_(android_id), security_token_(security_token), - user_serial_number_(user_serial_number), weak_ptr_factory_(this) { } @@ -46,7 +45,7 @@ void CheckinRequest::Start() { checkin_proto::AndroidCheckinRequest request; request.set_id(android_id_); request.set_security_token(security_token_); - request.set_user_serial_number(user_serial_number_); + request.set_user_serial_number(kDefaultUserSerialNumber); request.set_version(kRequestVersionValue); checkin_proto::AndroidCheckinProto* checkin = request.mutable_checkin(); diff --git a/google_apis/gcm/engine/checkin_request.h b/google_apis/gcm/engine/checkin_request.h index 548f0b8..ede7ffd 100644 --- a/google_apis/gcm/engine/checkin_request.h +++ b/google_apis/gcm/engine/checkin_request.h @@ -33,9 +33,8 @@ class GCM_EXPORT CheckinRequest : public net::URLFetcherDelegate { CheckinRequest(const CheckinRequestCallback& callback, const net::BackoffEntry::Policy& backoff_policy, const checkin_proto::ChromeBuildProto& chrome_build_proto, - int64 user_serial_number, uint64 android_id, - uint64 secret_token, + uint64 security_token, net::URLRequestContextGetter* request_context_getter); virtual ~CheckinRequest(); @@ -57,7 +56,6 @@ class GCM_EXPORT CheckinRequest : public net::URLFetcherDelegate { checkin_proto::ChromeBuildProto chrome_build_proto_; uint64 android_id_; uint64 security_token_; - int64 user_serial_number_; base::WeakPtrFactory<CheckinRequest> weak_ptr_factory_; diff --git a/google_apis/gcm/engine/checkin_request_unittest.cc b/google_apis/gcm/engine/checkin_request_unittest.cc index b618bbf..ba77f9f 100644 --- a/google_apis/gcm/engine/checkin_request_unittest.cc +++ b/google_apis/gcm/engine/checkin_request_unittest.cc @@ -50,7 +50,6 @@ const uint64 kBlankAndroidId = 999999UL; const uint64 kBlankSecurityToken = 999999UL; const char kChromeVersion[] = "Version String"; const uint64 kSecurityToken = 77; -const int64 kUserSerialNumber = 7; class CheckinRequestTest : public testing::Test { public: @@ -121,7 +120,6 @@ void CheckinRequestTest::CreateRequest(uint64 android_id, base::Unretained(this)), kDefaultBackoffPolicy, chrome_build_proto_, - kUserSerialNumber, android_id, security_token, url_request_context_getter_.get())); @@ -182,7 +180,6 @@ TEST_F(CheckinRequestTest, FetcherData) { EXPECT_EQ(kAndroidId, static_cast<uint64>(request_proto.id())); EXPECT_EQ(kSecurityToken, request_proto.security_token()); - EXPECT_EQ(kUserSerialNumber, request_proto.user_serial_number()); EXPECT_EQ(chrome_build_proto_.platform(), request_proto.checkin().chrome_build().platform()); EXPECT_EQ(chrome_build_proto_.chrome_version(), @@ -348,6 +345,7 @@ TEST_F(CheckinRequestTest, SuccessfulFirstTimeCheckin) { SetResponse(VALID_RESPONSE); CompleteFetch(); + EXPECT_TRUE(callback_called_); EXPECT_EQ(kAndroidId, android_id_); EXPECT_EQ(kSecurityToken, security_token_); } diff --git a/google_apis/gcm/engine/connection_handler_impl_unittest.cc b/google_apis/gcm/engine/connection_handler_impl_unittest.cc index d9f381b..5f0996a 100644 --- a/google_apis/gcm/engine/connection_handler_impl_unittest.cc +++ b/google_apis/gcm/engine/connection_handler_impl_unittest.cc @@ -67,9 +67,7 @@ std::string EncodeHandshakeRequest() { std::string result; const char version_byte[1] = {kMCSVersion}; result.append(version_byte, 1); - std::vector<int64> user_serial_numbers; - ScopedMessage login_request( - BuildLoginRequest(kAuthId, kAuthToken, user_serial_numbers)); + ScopedMessage login_request(BuildLoginRequest(kAuthId, kAuthToken)); result.append(EncodePacket(kLoginRequestTag, login_request->SerializeAsString())); return result; @@ -204,9 +202,8 @@ void GCMConnectionHandlerImplTest::Connect( base::Bind(&GCMConnectionHandlerImplTest::ConnectionContinuation, base::Unretained(this)))); EXPECT_FALSE(connection_handler()->CanSendMessage()); - std::vector<int64> user_serial_numbers; connection_handler_->Init( - *BuildLoginRequest(kAuthId, kAuthToken, user_serial_numbers), + *BuildLoginRequest(kAuthId, kAuthToken), socket_.get()); } diff --git a/google_apis/gcm/engine/mcs_client.cc b/google_apis/gcm/engine/mcs_client.cc index 127f9bf..0a0bfc9 100644 --- a/google_apis/gcm/engine/mcs_client.cc +++ b/google_apis/gcm/engine/mcs_client.cc @@ -192,9 +192,7 @@ void MCSClient::Initialize( } } -void MCSClient::Login(uint64 android_id, - uint64 security_token, - const std::vector<int64>& user_serial_numbers) { +void MCSClient::Login(uint64 android_id, uint64 security_token) { DCHECK_EQ(state_, LOADED); DCHECK(android_id_ == 0 || android_id_ == android_id); DCHECK(security_token_ == 0 || security_token_ == security_token); @@ -205,7 +203,6 @@ void MCSClient::Login(uint64 android_id, android_id_ = android_id; security_token_ = security_token; } - user_serial_numbers_ = user_serial_numbers; DCHECK(android_id_ != 0 || restored_unackeds_server_ids_.empty()); @@ -296,8 +293,7 @@ void MCSClient::ResetStateAndBuildLoginRequest( acked_server_ids_.clear(); // Then build the request, consuming all pending acknowledgments. - request->Swap(BuildLoginRequest( - android_id_, security_token_, user_serial_numbers_).get()); + request->Swap(BuildLoginRequest(android_id_, security_token_).get()); for (PersistentIdList::const_iterator iter = restored_unackeds_server_ids_.begin(); iter != restored_unackeds_server_ids_.end(); ++iter) { diff --git a/google_apis/gcm/engine/mcs_client.h b/google_apis/gcm/engine/mcs_client.h index 70f4f2e..036acb8 100644 --- a/google_apis/gcm/engine/mcs_client.h +++ b/google_apis/gcm/engine/mcs_client.h @@ -104,15 +104,12 @@ class GCM_EXPORT MCSClient { // Logs the client into the server. Client must be initialized. // |android_id| and |security_token| are optional if this is not a new - // client, else they must be non-zero. |user_serial_numbers| contains the - // serial numbers of all active users. + // client, else they must be non-zero. // Successful login will result in |message_received_callback| being invoked // with a valid LoginResponse. // Login failure (typically invalid id/token) will shut down the client, and // |initialization_callback| to be invoked with |success = false|. - virtual void Login(uint64 android_id, - uint64 security_token, - const std::vector<int64>& user_serial_numbers); + virtual void Login(uint64 android_id, uint64 security_token); // Sends a message, with or without reliable message queueing (RMQ) support. // Will asynchronously invoke the OnMessageSent callback regardless. @@ -208,9 +205,6 @@ class GCM_EXPORT MCSClient { uint64 android_id_; uint64 security_token_; - // The list of serial numbers of all active users when login occurs. - std::vector<int64> user_serial_numbers_; - // Factory for creating new connections and connection handlers. ConnectionFactory* connection_factory_; diff --git a/google_apis/gcm/engine/mcs_client_unittest.cc b/google_apis/gcm/engine/mcs_client_unittest.cc index 6bdce13..cc2e0f9 100644 --- a/google_apis/gcm/engine/mcs_client_unittest.cc +++ b/google_apis/gcm/engine/mcs_client_unittest.cc @@ -91,11 +91,6 @@ class MCSClientTest : public testing::Test { return &connection_factory_; } bool init_success() const { return init_success_; } - std::vector<int64> user_serial_numbers() const { - std::vector<int64> user_serial_numbers; - user_serial_numbers.push_back(1LL); - return user_serial_numbers; - } uint64 restored_android_id() const { return restored_android_id_; } uint64 restored_security_token() const { return restored_security_token_; } MCSMessage* received_message() const { return received_message_.get(); } @@ -181,13 +176,13 @@ void MCSClientTest::InitializeClient() { void MCSClientTest::LoginClient( const std::vector<std::string>& acknowledged_ids) { scoped_ptr<mcs_proto::LoginRequest> login_request = - BuildLoginRequest(kAndroidId, kSecurityToken, user_serial_numbers()); + BuildLoginRequest(kAndroidId, kSecurityToken); for (size_t i = 0; i < acknowledged_ids.size(); ++i) login_request->add_received_persistent_id(acknowledged_ids[i]); GetFakeHandler()->ExpectOutgoingMessage( MCSMessage(kLoginRequestTag, login_request.PassAs<const google::protobuf::MessageLite>())); - mcs_client_->Login(kAndroidId, kSecurityToken, user_serial_numbers()); + mcs_client_->Login(kAndroidId, kSecurityToken); run_loop_->Run(); run_loop_.reset(new base::RunLoop()); } @@ -342,7 +337,7 @@ TEST_F(MCSClientTest, SendMessageRMQWhileDisconnected) { GetFakeHandler()->ExpectOutgoingMessage( MCSMessage( kLoginRequestTag, - BuildLoginRequest(kAndroidId, kSecurityToken, user_serial_numbers()). + BuildLoginRequest(kAndroidId, kSecurityToken). PassAs<const google::protobuf::MessageLite>())); // The second (re)send. MCSMessage message2(BuildDataMessage("from", diff --git a/google_apis/gcm/engine/registration_request.cc b/google_apis/gcm/engine/registration_request.cc index 5635e5e..9e89bac 100644 --- a/google_apis/gcm/engine/registration_request.cc +++ b/google_apis/gcm/engine/registration_request.cc @@ -32,8 +32,6 @@ const char kCertKey[] = "cert"; const char kDeviceIdKey[] = "device"; const char kLoginHeader[] = "AidLogin"; const char kSenderKey[] = "sender"; -const char kUserAndroidIdKey[] = "X-GOOG.USER_AID"; -const char kUserSerialNumberKey[] = "device_user_id"; // Request validation constants. const size_t kMaxSenders = 100; @@ -80,15 +78,11 @@ bool ShouldRetryWithStatus(RegistrationRequest::Status status) { RegistrationRequest::RequestInfo::RequestInfo( uint64 android_id, uint64 security_token, - uint64 user_android_id, - int64 user_serial_number, const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids) : android_id(android_id), security_token(security_token), - user_android_id(user_android_id), - user_serial_number(user_serial_number), app_id(app_id), cert(cert), sender_ids(sender_ids) { @@ -147,16 +141,6 @@ void RegistrationRequest::Start() { } BuildFormEncoding(kSenderKey, senders, &body); - if (request_info_.user_serial_number != 0) { - DCHECK(request_info_.user_android_id != 0); - BuildFormEncoding(kUserSerialNumberKey, - base::Int64ToString(request_info_.user_serial_number), - &body); - BuildFormEncoding(kUserAndroidIdKey, - base::Uint64ToString(request_info_.user_android_id), - &body); - } - DVLOG(1) << "Performing registration for: " << request_info_.app_id; DVLOG(1) << "Registration request: " << body; url_fetcher_->SetUploadData(kRegistrationRequestContentType, body); diff --git a/google_apis/gcm/engine/registration_request.h b/google_apis/gcm/engine/registration_request.h index e21004e..2936350 100644 --- a/google_apis/gcm/engine/registration_request.h +++ b/google_apis/gcm/engine/registration_request.h @@ -57,8 +57,6 @@ class GCM_EXPORT RegistrationRequest : public net::URLFetcherDelegate { struct GCM_EXPORT RequestInfo { RequestInfo(uint64 android_id, uint64 security_token, - uint64 user_android_id, - int64 user_serial_number, const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids); @@ -68,10 +66,6 @@ class GCM_EXPORT RegistrationRequest : public net::URLFetcherDelegate { uint64 android_id; // Security token of the device. uint64 security_token; - // User's android ID. (Can be omitted in a single user scenario.) - uint64 user_android_id; - // User's serial number. (Can be omitted in a single user scenario.) - int64 user_serial_number; // Application ID. std::string app_id; // Certificate of the application. diff --git a/google_apis/gcm/engine/registration_request_unittest.cc b/google_apis/gcm/engine/registration_request_unittest.cc index ad4c400..178c135 100644 --- a/google_apis/gcm/engine/registration_request_unittest.cc +++ b/google_apis/gcm/engine/registration_request_unittest.cc @@ -22,8 +22,6 @@ const char kDeveloperId[] = "Project1"; const char kLoginHeader[] = "AidLogin"; const char kAppId[] = "TestAppId"; const uint64 kSecurityToken = 77UL; -const uint64 kUserAndroidId = 1111; -const int64 kUserSerialNumber = 1; // Backoff policy for testing registration request. const net::BackoffEntry::Policy kDefaultBackoffPolicy = { @@ -105,8 +103,6 @@ void RegistrationRequestTest::CreateRequest(const std::string& sender_ids) { request_.reset(new RegistrationRequest( RegistrationRequest::RequestInfo(kAndroidId, kSecurityToken, - kUserAndroidId, - kUserSerialNumber, kAppId, kCert, senders), @@ -161,8 +157,6 @@ TEST_F(RegistrationRequestTest, RequestDataPassedToFetcher) { expected_pairs["sender"] = kDeveloperId; expected_pairs["cert"] = kCert; expected_pairs["device"] = base::Uint64ToString(kAndroidId); - expected_pairs["device_user_id"] = base::Int64ToString(kUserSerialNumber); - expected_pairs["X-GOOG.USER_AID"] = base::Uint64ToString(kUserAndroidId); // Verify data was formatted properly. std::string upload_data = fetcher->upload_data(); diff --git a/google_apis/gcm/engine/user_list.cc b/google_apis/gcm/engine/user_list.cc deleted file mode 100644 index f2d57dc..0000000 --- a/google_apis/gcm/engine/user_list.cc +++ /dev/null @@ -1,222 +0,0 @@ -// 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 "google_apis/gcm/engine/user_list.h" - -#include "base/bind.h" -#include "base/files/file_path.h" -#include "base/location.h" -#include "base/logging.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/message_loop/message_loop_proxy.h" -#include "base/sequenced_task_runner.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_piece.h" -#include "third_party/leveldatabase/src/include/leveldb/db.h" - -namespace gcm { -const int64 kInvalidSerialNumber = -1; - -UserList::UserInfo::UserInfo() - : serial_number(kInvalidSerialNumber), - // TODO(jianli): support setting active state. - active(true), - delegate(NULL) { -} - -UserList::UserInfo::UserInfo(int64 serial_number) - : serial_number(serial_number), - active(true), - delegate(NULL) { -} - -UserList::UserInfo::UserInfo(GCMClient::Delegate* delegate, - const SetDelegateCallback& callback) - : serial_number(kInvalidSerialNumber), - active(true), - delegate(delegate), - callback(callback) { -} - -UserList::UserInfo::~UserInfo() { -} - -UserList::UserList(GCMStore* gcm_store) - : initialized_(false), - next_serial_number_(kInvalidSerialNumber), - gcm_store_(gcm_store) { -} - -UserList::~UserList() { -} - -void UserList::Initialize(const GCMStore::SerialNumberMappings& result) { - DCHECK(!initialized_); - DCHECK_GT(result.next_serial_number, 0); - - initialized_ = true; - next_serial_number_ = result.next_serial_number; - for (std::map<std::string, int64>::const_iterator iter = - result.user_serial_numbers.begin(); - iter != result.user_serial_numbers.end(); - ++iter) { - SetSerialNumber(iter->first, iter->second); - } - - for (UserInfoMap::iterator iter = delegates_.begin(); - iter != delegates_.end(); - ++iter) { - // Process only users with delegate and callback present. - if (iter->second.delegate && !iter->second.callback.is_null()) { - if (iter->second.serial_number == kInvalidSerialNumber) - AssignSerialNumber(iter->first); - else - OnSerialNumberReady(iter); - } - } -} - -void UserList::SetDelegate(const std::string& username, - GCMClient::Delegate* delegate, - const SetDelegateCallback& callback) { - DCHECK(!username.empty()); - DCHECK(delegate); - - UserInfoMap::iterator iter = delegates_.find(username); - if (iter != delegates_.end()) { - DCHECK(initialized_); - DCHECK(!iter->second.delegate); - iter->second.delegate = delegate; - iter->second.callback = callback; - } else { - delegates_.insert( - iter, - UserInfoMap::value_type(username, UserInfo(delegate, callback))); - } - - if (initialized_) { - UserInfoMap::iterator iter = delegates_.find(username); - if (iter->second.serial_number == kInvalidSerialNumber) - AssignSerialNumber(iter->first); - else - OnSerialNumberReady(iter); - } -} - -void UserList::AssignSerialNumber(const std::string& username) { - DCHECK(initialized_); - DCHECK_EQ(delegates_.count(username), 1UL); - DCHECK_EQ(delegates_[username].serial_number, kInvalidSerialNumber); - - // Start by incrementing the |next_serial_number_| and persist it in the GCM - // store. - int64 serial_number = next_serial_number_++; - gcm_store_->SetNextSerialNumber( - serial_number, - base::Bind(&UserList::IncrementSerialNumberCompleted, - base::Unretained(this), - username, - serial_number)); -} - -void UserList::IncrementSerialNumberCompleted(const std::string& username, - int64 user_serial_number, - bool success) { - // TODO(fgorski): Introduce retry logic. - if (!success) - DCHECK(success) << "Updating the next serial number failed."; - - SetSerialNumber(username, user_serial_number); - gcm_store_->AddUserSerialNumber( - username, - user_serial_number, - base::Bind(&UserList::AssignSerialNumberCompleted, - base::Unretained(this), - username)); -} - -void UserList::AssignSerialNumberCompleted(const std::string& username, - bool success) { - // TODO(fgorski): Introduce retry logic. - if (!success) { - DVLOG(1) << "It was not possible to persist username to serial number" - << " mapping for username: " << username; - return; - } - - UserInfoMap::iterator iter = delegates_.find(username); - DCHECK(iter != delegates_.end()); - OnSerialNumberReady(iter); -} - -void UserList::OnSerialNumberReady(const UserInfoMap::iterator& iter) { - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(iter->second.callback, - iter->first, - iter->second.serial_number)); - iter->second.callback.Reset(); -} - -void UserList::SetSerialNumber(const std::string& username, - int64 serial_number) { - DCHECK(!username.empty()); - DCHECK_GT(serial_number, 0L); - - UserInfoMap::iterator iter = delegates_.find(username); - if (iter != delegates_.end()) { - DCHECK_EQ(iter->second.serial_number, kInvalidSerialNumber); - iter->second.serial_number = serial_number; - } else { - delegates_.insert( - iter, UserInfoMap::value_type(username, UserInfo(serial_number))); - } -} - -GCMClient::Delegate* UserList::GetDelegateBySerialNumber(int64 serial_number) - const { - for (UserInfoMap::const_iterator iter = delegates_.begin(); - iter != delegates_.end(); - ++iter) { - if (iter->second.serial_number == serial_number) - return iter->second.delegate; - } - return NULL; -} - -std::vector<GCMClient::Delegate*> UserList::GetAllDelegates() const { - std::vector<GCMClient::Delegate*> delegates; - for (UserInfoMap::const_iterator iter = delegates_.begin(); - iter != delegates_.end(); ++iter) { - if (iter->second.delegate) - delegates.push_back(iter->second.delegate); - } - return delegates; -} - -GCMClient::Delegate* UserList::GetDelegateByUsername( - const std::string& username) const { - UserInfoMap::const_iterator iter = delegates_.find(username); - return iter != delegates_.end() ? iter->second.delegate : NULL; -} - -int64 UserList::GetSerialNumberForUsername(const std::string& username) const { - UserInfoMap::const_iterator iter = delegates_.find(username); - return iter != delegates_.end() ? iter->second.serial_number - : kInvalidSerialNumber; -} - -std::vector<int64> UserList::GetAllActiveUserSerialNumbers() const { - std::vector<int64> user_serial_numbers; - for (UserInfoMap::const_iterator iter = delegates_.begin(); - iter != delegates_.end(); ++iter) { - if (iter->second.active && - iter->second.serial_number != kInvalidSerialNumber) - user_serial_numbers.push_back(iter->second.serial_number); - } - return user_serial_numbers; -} - -} // namespace gcm diff --git a/google_apis/gcm/engine/user_list.h b/google_apis/gcm/engine/user_list.h deleted file mode 100644 index 7aa9536..0000000 --- a/google_apis/gcm/engine/user_list.h +++ /dev/null @@ -1,110 +0,0 @@ -// 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. - -#ifndef GOOGLE_APIS_GCM_ENGINE_USER_LIST_H_ -#define GOOGLE_APIS_GCM_ENGINE_USER_LIST_H_ - -#include <map> -#include <string> -#include <vector> - -#include "base/callback.h" -#include "google_apis/gcm/engine/gcm_store.h" -#include "google_apis/gcm/gcm_client.h" - -namespace gcm { - -GCM_EXPORT extern const int64 kInvalidSerialNumber; - -// UserList stores mappings between usernames, serial numbers and delegates to -// enable dispatching messages to applications. -class GCM_EXPORT UserList { - public: - // A callback used by SetDelegate method to return a |user_serial_number| - // assigned to the delegate identified by |username|. - typedef base::Callback<void(const std::string& username, - int64 user_serial_number)> SetDelegateCallback; - - explicit UserList(GCMStore* gcm_store); - ~UserList(); - - // Initializes the User List with a set of mappings and next serial number. - void Initialize(const GCMStore::SerialNumberMappings& result); - - // Sets a user delegate for |username|. It will create a new entry for the - // user if one does not exist. - void SetDelegate(const std::string& username, - GCMClient::Delegate* delegate, - const SetDelegateCallback& callback); - - // Returns a delegate for the user identified by |serial_number| or NULL, if - // a matching delegate was not found. - GCMClient::Delegate* GetDelegateBySerialNumber(int64 serial_number) const; - - // Returns a delegate for the user identified by |username| or NULL, if a - // matching delegate was not found. - GCMClient::Delegate* GetDelegateByUsername(const std::string& username) const; - - // Returns all delegates. - std::vector<GCMClient::Delegate*> GetAllDelegates() const; - - // Gets the serial number assigned to a specified |username|, if one is - // assigned, the value will be positive. If there is no matching delegate or - // it is not yet assigned a serial number, the result will be equal to - // kInvalidSerialNumber. - int64 GetSerialNumberForUsername(const std::string& username) const; - - // Returns serial numbers of all active users. - std::vector<int64> GetAllActiveUserSerialNumbers() const; - - private: - friend class UserListTest; - - struct UserInfo { - UserInfo(); - explicit UserInfo(int64 serial_number); - UserInfo(GCMClient::Delegate* delegate, - const SetDelegateCallback& callback); - ~UserInfo(); - - int64 serial_number; - bool active; - // Delegate related to the username. Not owned by the UserDelegate. - GCMClient::Delegate* delegate; - SetDelegateCallback callback; - }; - typedef std::map<std::string, UserInfo> UserInfoMap; - - // Assigns a serial number to the user identitified by |username|. - void AssignSerialNumber(const std::string& username); - - // A callback invoked once the Backend is done updating the next serial - // number. - void IncrementSerialNumberCompleted(const std::string& username, - int64 user_serial_number, - bool success); - - // Callback for serial number completion. - void AssignSerialNumberCompleted(const std::string& username, bool success); - - // Concludes the process of setting a delegate by running a callback with - // |username| and |serial_number| assigned to that |username|. It will also - // reset the callback, so that it is not called again. - void OnSerialNumberReady(const UserInfoMap::iterator& iter); - - // Sets the serial number related to the username. It expects the entry to not - // exist yet and will create it. - void SetSerialNumber(const std::string& username, int64 serial_number); - - bool initialized_; - int64 next_serial_number_; - UserInfoMap delegates_; - GCMStore* gcm_store_; - - DISALLOW_COPY_AND_ASSIGN(UserList); -}; - -} // namespace gcm - -#endif // GOOGLE_APIS_GCM_ENGINE_USER_LIST_H_ diff --git a/google_apis/gcm/engine/user_list_unittest.cc b/google_apis/gcm/engine/user_list_unittest.cc deleted file mode 100644 index b8c4c62..0000000 --- a/google_apis/gcm/engine/user_list_unittest.cc +++ /dev/null @@ -1,370 +0,0 @@ -// 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 "google_apis/gcm/engine/user_list.h" - -#include <string> -#include <vector> - -#include "base/bind.h" -#include "base/callback_forward.h" -#include "base/files/file_path.h" -#include "base/files/scoped_temp_dir.h" -#include "base/memory/scoped_ptr.h" -#include "base/message_loop/message_loop.h" -#include "base/run_loop.h" -#include "google_apis/gcm/engine/gcm_store_impl.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace gcm { - -namespace { - -class GCMClientDelegate : public GCMClient::Delegate { - public: - explicit GCMClientDelegate(const std::string& username); - virtual ~GCMClientDelegate(); - - const std::string& GetUsername() const { return username_; } - - // Overrides of GCMClientDelegate: - virtual void OnCheckInFinished(const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) OVERRIDE {} - virtual void OnRegisterFinished(const std::string& app_id, - const std::string& registration_id, - GCMClient::Result result) OVERRIDE {} - virtual void OnSendFinished(const std::string& app_id, - const std::string& message_id, - GCMClient::Result result) OVERRIDE {} - virtual void OnMessageReceived(const std::string& app_id, - const GCMClient::IncomingMessage& message) - OVERRIDE {} - virtual void OnMessagesDeleted(const std::string& app_id) OVERRIDE {} - virtual void OnMessageSendError(const std::string& app_id, - const std::string& message_id, - GCMClient::Result result) OVERRIDE {} - virtual GCMClient::CheckinInfo GetCheckinInfo() const OVERRIDE { - return GCMClient::CheckinInfo(); - } - virtual void OnGCMReady() OVERRIDE {} - - private: - std::string username_; -}; - -} // namespace - -class UserListTest : public testing::Test { - public: - UserListTest(); - virtual ~UserListTest(); - - virtual void SetUp() OVERRIDE; - - static size_t GetListSize(const UserList* user_list); - void SetDelegateCallback(const std::string& username, - int64 user_serial_number); - - scoped_ptr<UserList> BuildUserList(); - - void PumpLoop(); - - void UpdateCallback(bool success); - - void Initialize(UserList* user_list, scoped_ptr<GCMStore::LoadResult> result); - - void ResetLoop(); - - protected: - int64 last_assigned_serial_number_; - std::string last_assigned_username_; - scoped_ptr<GCMStore> gcm_store_; - - private: - base::ScopedTempDir temp_directory_; - base::MessageLoop message_loop_; - scoped_ptr<base::RunLoop> run_loop_; -}; - -UserListTest::UserListTest() - : last_assigned_serial_number_(gcm::kInvalidSerialNumber) {} - -UserListTest::~UserListTest() {} - -void UserListTest::SetUp() { - ASSERT_TRUE(temp_directory_.CreateUniqueTempDir()); -} - -// static -size_t UserListTest::GetListSize(const UserList* user_list) { - return user_list->delegates_.size(); -} - -void UserListTest::SetDelegateCallback(const std::string& username, - int64 user_serial_number) { - last_assigned_username_ = username; - last_assigned_serial_number_ = user_serial_number; - ResetLoop(); -} - -scoped_ptr<UserList> UserListTest::BuildUserList() { - gcm_store_.reset(new GCMStoreImpl(true, - temp_directory_.path(), - message_loop_.message_loop_proxy())); - return scoped_ptr<UserList>(new UserList(gcm_store_.get())); -} - -void UserListTest::Initialize(UserList* user_list, - scoped_ptr<GCMStore::LoadResult> result) { - ASSERT_TRUE(result->success); - user_list->Initialize(result->serial_number_mappings); - ResetLoop(); -} - -void UserListTest::ResetLoop() { - if (run_loop_ && run_loop_->running()) - run_loop_->Quit(); -} - -void UserListTest::PumpLoop() { - run_loop_.reset(new base::RunLoop); - run_loop_->Run(); -} - -void UserListTest::UpdateCallback(bool success) { ASSERT_TRUE(success); } - -GCMClientDelegate::GCMClientDelegate(const std::string& username) - : username_(username) {} - -GCMClientDelegate::~GCMClientDelegate() {} - -// Make sure it is possible to add a delegate, and that it is assigned a serial -// number. -TEST_F(UserListTest, SetDelegateAndCheckSerialNumberAssignment) { - scoped_ptr<UserList> user_list(BuildUserList()); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // First adding a delegate. - scoped_ptr<GCMClientDelegate> delegate(new GCMClientDelegate("test_user_1")); - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - // Verify the record was created. - EXPECT_EQ(1u, GetListSize(user_list.get())); - // Verify username and serial number were assigned. - EXPECT_EQ(delegate->GetUsername(), last_assigned_username_); - EXPECT_NE(gcm::kInvalidSerialNumber, last_assigned_serial_number_); - // Check that a serial number was assigned to delegate. - EXPECT_EQ(last_assigned_serial_number_, - user_list->GetSerialNumberForUsername(delegate->GetUsername())); -} - -// Get the delegate that was added to the list by both serial number and -// username. -TEST_F(UserListTest, GetDelegate) { - scoped_ptr<UserList> user_list(BuildUserList()); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // Start by adding a delegate and a serial number. - scoped_ptr<GCMClientDelegate> delegate(new GCMClientDelegate("test_user_1")); - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - EXPECT_EQ(delegate.get(), - user_list->GetDelegateBySerialNumber(last_assigned_serial_number_)); - EXPECT_EQ(delegate.get(), - user_list->GetDelegateByUsername(last_assigned_username_)); -} - -// Make sure that correct mapping between username of the delegate and a serial -// number is preserved when loading the user list. Also verify that setting a -// delegate after load works correctly. (Finds the existing mapping entry.) -TEST_F(UserListTest, LoadUserEntrySetDelegate) { - scoped_ptr<UserList> user_list(BuildUserList()); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // Start by adding a delegate and a serial number. - scoped_ptr<GCMClientDelegate> delegate(new GCMClientDelegate("test_user_1")); - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - // Reload the GCM User List. - user_list = BuildUserList().Pass(); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // Verify a single record was loaded, with matching username, but no delegate. - EXPECT_EQ(1u, GetListSize(user_list.get())); - int64 serial_number = - user_list->GetSerialNumberForUsername(delegate->GetUsername()); - EXPECT_EQ(last_assigned_serial_number_, serial_number); - EXPECT_EQ(NULL, user_list->GetDelegateBySerialNumber(serial_number)); - EXPECT_EQ(NULL, user_list->GetDelegateByUsername(delegate->GetUsername())); - - // After loading is complete, Delegates will start adding itself looking for - // their serial numbers. Check that correct matches are found and new records - // not created. - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - EXPECT_EQ(1u, GetListSize(user_list.get())); - serial_number = - user_list->GetSerialNumberForUsername(delegate->GetUsername()); - EXPECT_EQ(last_assigned_serial_number_, serial_number); - EXPECT_EQ(delegate.get(), - user_list->GetDelegateBySerialNumber(serial_number)); - EXPECT_EQ(delegate.get(), - user_list->GetDelegateByUsername(delegate->GetUsername())); -} - -// Check that it is possible to add multiple delegates to the user list. -TEST_F(UserListTest, AddMultipleDelegates) { - scoped_ptr<UserList> user_list(BuildUserList()); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // Start by adding a delegate and a serial number. - scoped_ptr<GCMClientDelegate> delegate1(new GCMClientDelegate("test_user_1")); - user_list->SetDelegate( - delegate1->GetUsername(), - delegate1.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - int64 serial_number1 = last_assigned_serial_number_; - - scoped_ptr<GCMClientDelegate> delegate2(new GCMClientDelegate("test_user_2")); - user_list->SetDelegate( - delegate2->GetUsername(), - delegate2.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - int64 serial_number2 = last_assigned_serial_number_; - - // Ensuring that serial numbers are different. - EXPECT_EQ(2u, GetListSize(user_list.get())); - - // Reading the user entries. - user_list = BuildUserList().Pass(); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // Serial numbers stay the same, but there are no delegates assigned. - EXPECT_EQ(2u, GetListSize(user_list.get())); - EXPECT_EQ(NULL, user_list->GetDelegateByUsername(delegate1->GetUsername())); - EXPECT_EQ(NULL, user_list->GetDelegateBySerialNumber(serial_number1)); - EXPECT_EQ(NULL, user_list->GetDelegateByUsername(delegate2->GetUsername())); - EXPECT_EQ(NULL, user_list->GetDelegateBySerialNumber(serial_number2)); - - // Setting and checking a delegate on the second user. - user_list->SetDelegate( - delegate2->GetUsername(), - delegate2.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - // First user still does not have a delegate. - EXPECT_EQ(NULL, user_list->GetDelegateByUsername(delegate1->GetUsername())); - EXPECT_EQ(NULL, user_list->GetDelegateBySerialNumber(serial_number1)); - // Second user has a delegate set. - EXPECT_EQ(delegate2.get(), - user_list->GetDelegateByUsername(delegate2->GetUsername())); - EXPECT_EQ(delegate2.get(), - user_list->GetDelegateBySerialNumber(serial_number2)); -} - -// Adding a delegate before the user list is initialized. Verifies that serial -// number assignment is postponed until after initialization. -TEST_F(UserListTest, AddDelegateThenInitializeWithoutSerialNumber) { - scoped_ptr<UserList> user_list(BuildUserList()); - - // Add a delegate first. - scoped_ptr<GCMClientDelegate> delegate(new GCMClientDelegate("test_user_1")); - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - - EXPECT_EQ(gcm::kInvalidSerialNumber, last_assigned_serial_number_); - EXPECT_EQ("", last_assigned_username_); - - // Now run the initialization. - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - // Need to pump twice, due to initialization triggering additional set of - // callbacks to be run. - PumpLoop(); - PumpLoop(); - - EXPECT_EQ(last_assigned_serial_number_, - user_list->GetSerialNumberForUsername(delegate->GetUsername())); - EXPECT_EQ(delegate->GetUsername(), last_assigned_username_); -} - -// Adding a delegate that already has a serial number on a subsequent restart of -// the user list and prior to initialization. Expects to assing correct serial -// number based on existing mappings. -TEST_F(UserListTest, AddDelegateThenInitializeWithSerialNumber) { - scoped_ptr<UserList> user_list(BuildUserList()); - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - PumpLoop(); - - // First add a delegate to the list so that serial number is persisted. - scoped_ptr<GCMClientDelegate> delegate(new GCMClientDelegate("test_user_1")); - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - PumpLoop(); - - last_assigned_serial_number_ = gcm::kInvalidSerialNumber; - last_assigned_username_ = ""; - - // Resetting the user list to make sure it is not initialized. - user_list = BuildUserList().Pass(); - - // Add a delegate again, this time no callback is expected until the list is - // initialized. - user_list->SetDelegate( - delegate->GetUsername(), - delegate.get(), - base::Bind(&UserListTest::SetDelegateCallback, base::Unretained(this))); - - // Now run the initialization. - gcm_store_->Load(base::Bind( - &UserListTest::Initialize, base::Unretained(this), user_list.get())); - // Need to pump twice, due to initialization triggering additional set of - // callbacks to be run. - PumpLoop(); - PumpLoop(); - - EXPECT_EQ(last_assigned_serial_number_, - user_list->GetSerialNumberForUsername(delegate->GetUsername())); - EXPECT_EQ(delegate->GetUsername(), last_assigned_username_); -} - -} // namespace gcm diff --git a/google_apis/gcm/gcm.gyp b/google_apis/gcm/gcm.gyp index da5b9da..7eeedf9 100644 --- a/google_apis/gcm/gcm.gyp +++ b/google_apis/gcm/gcm.gyp @@ -64,8 +64,6 @@ 'engine/mcs_client.h', 'engine/registration_request.cc', 'engine/registration_request.h', - 'engine/user_list.cc', - 'engine/user_list.h', 'gcm_client.cc', 'gcm_client.h', 'gcm_client_impl.cc', @@ -135,7 +133,6 @@ 'engine/heartbeat_manager_unittest.cc', 'engine/mcs_client_unittest.cc', 'engine/registration_request_unittest.cc', - 'engine/user_list_unittest.cc', 'gcm_client_impl_unittest.cc' ] }, diff --git a/google_apis/gcm/gcm_client.h b/google_apis/gcm/gcm_client.h index c9203e8..02a243b 100644 --- a/google_apis/gcm/gcm_client.h +++ b/google_apis/gcm/gcm_client.h @@ -76,29 +76,10 @@ class GCM_EXPORT GCMClient { MessageData data; }; - // The check-in info for the user. Returned by the server. - struct GCM_EXPORT CheckinInfo { - CheckinInfo() : android_id(0), secret(0) {} - bool IsValid() const { return android_id != 0 && secret != 0; } - void Reset() { - android_id = 0; - secret = 0; - } - - uint64 android_id; - uint64 secret; - }; - // A delegate interface that allows the GCMClient instance to interact with // its caller, i.e. notifying asynchronous event. class Delegate { public: - // Called when the user has been checked in successfully or an error occurs. - // |checkin_info|: valid if the CheckIn(..) completed successfully. - // |result|: the type of the error if an error occured, success otherwise. - virtual void OnCheckInFinished(const CheckinInfo& checkin_info, - Result result) = 0; - // Called when the registration completed successfully or an error occurs. // |app_id|: application ID. // |registration_id|: non-empty if the registration completed successfully. @@ -134,11 +115,6 @@ class GCM_EXPORT GCMClient { const std::string& message_id, Result result) = 0; - // Returns the checkin info associated with this user. The delegate class - // is expected to persist the checkin info that is provided by - // OnCheckInFinished. - virtual CheckinInfo GetCheckinInfo() const = 0; - // Called when the GCM becomes ready. To get to this state, GCMClient // finished loading from the GCM store and retrieved the device check-in // from the server if it hadn't yet. @@ -149,54 +125,47 @@ class GCM_EXPORT GCMClient { virtual ~GCMClient(); // Begins initialization of the GCM Client. + // |chrome_build_proto|: chrome info, i.e., version, channel and etc. + // |store_path|: path to the GCM store. + // |blocking_task_runner|: for running blocking file tasks. + // |url_request_context_getter|: for url requests. + // |delegate|: the delegate whose methods will be called asynchronously in + // response to events and messages. virtual void Initialize( const checkin_proto::ChromeBuildProto& chrome_build_proto, const base::FilePath& store_path, const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner, const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter) = 0; - - // Sets the delegate to interact with related to a specific user. - // |username|: the username (email address) used to check in with the server. - // |delegate|: the delegate whose methods will be called asynchronously in - // response to events and messages. - virtual void SetUserDelegate(const std::string& username, - Delegate* delegate) = 0; + url_request_context_getter, + Delegate* delegate) = 0; - // Checks in the user to use GCM. If the device has not been checked in, it - // will be done first. - // |username|: the username (email address) used to check in with the server. - virtual void CheckIn(const std::string& username) = 0; + // Checks out of the GCM service. This will erase all the cached and persisted + // data. + virtual void CheckOut() = 0; // Registers the application for GCM. Delegate::OnRegisterFinished will be // called asynchronously upon completion. - // |username|: the username (email address) passed in CheckIn(..). // |app_id|: application ID. // |cert|: SHA-1 of public key of the application, in base16 format. // |sender_ids|: list of IDs of the servers that are allowed to send the // messages to the application. These IDs are assigned by the // Google API Console. - virtual void Register(const std::string& username, - const std::string& app_id, + virtual void Register(const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids) = 0; // Unregisters the application from GCM when it is uninstalled. // Delegate::OnUnregisterFinished will be called asynchronously upon // completion. - // |username|: the username (email address) passed in CheckIn(..). // |app_id|: application ID. - virtual void Unregister(const std::string& username, - const std::string& app_id) = 0; + virtual void Unregister(const std::string& app_id) = 0; // Sends a message to a given receiver. Delegate::OnSendFinished will be // called asynchronously upon completion. - // |username|: the username (email address) passed in CheckIn(..). // |app_id|: application ID. // |receiver_id|: registration ID of the receiver party. // |message|: message to be sent. - virtual void Send(const std::string& username, - const std::string& app_id, + virtual void Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) = 0; diff --git a/google_apis/gcm/gcm_client_impl.cc b/google_apis/gcm/gcm_client_impl.cc index 549569c..20fc976 100644 --- a/google_apis/gcm/gcm_client_impl.cc +++ b/google_apis/gcm/gcm_client_impl.cc @@ -18,7 +18,6 @@ #include "google_apis/gcm/engine/gcm_store_impl.h" #include "google_apis/gcm/engine/mcs_client.h" #include "google_apis/gcm/engine/registration_request.h" -#include "google_apis/gcm/engine/user_list.h" #include "google_apis/gcm/protocol/mcs.pb.h" #include "net/http/http_network_session.h" #include "net/url_request/url_request_context.h" @@ -73,6 +72,7 @@ const char kMessageTypeKey[] = "message_type"; const char kMessageTypeSendErrorKey[] = "send_error"; const char kSendErrorMessageIdKey[] = "google.message_id"; const char kSendMessageFromValue[] = "gcm@chrome.com"; +const int64 kDefaultUserSerialNumber = 0LL; GCMClient::Result ToGCMClientResult(MCSClient::MessageSendStatus status) { switch (status) { @@ -108,29 +108,10 @@ MessageType DecodeMessageType(const std::string& value) { } // namespace -GCMClientImpl::PendingRegistrationKey::PendingRegistrationKey( - const std::string& username, const std::string& app_id) - : username(username), - app_id(app_id) { -} - -GCMClientImpl::PendingRegistrationKey::~PendingRegistrationKey() { -} - -bool GCMClientImpl::PendingRegistrationKey::operator<( - const PendingRegistrationKey& rhs) const { - if (username < rhs.username) - return true; - if (username > rhs.username) - return false; - return app_id < rhs.app_id; -} - GCMClientImpl::GCMClientImpl() : state_(UNINITIALIZED), clock_(new base::DefaultClock()), url_request_context_getter_(NULL), - pending_checkins_deleter_(&pending_checkins_), pending_registrations_deleter_(&pending_registrations_), weak_ptr_factory_(this) { } @@ -143,9 +124,11 @@ void GCMClientImpl::Initialize( const base::FilePath& path, const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner, const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter) { + url_request_context_getter, + Delegate* delegate) { DCHECK_EQ(UNINITIALIZED, state_); DCHECK(url_request_context_getter); + DCHECK(delegate); chrome_build_proto_.CopyFrom(chrome_build_proto); url_request_context_getter_ = url_request_context_getter; @@ -153,7 +136,8 @@ void GCMClientImpl::Initialize( gcm_store_.reset(new GCMStoreImpl(false, path, blocking_task_runner)); gcm_store_->Load(base::Bind(&GCMClientImpl::OnLoadCompleted, weak_ptr_factory_.GetWeakPtr())); - user_list_.reset(new UserList(gcm_store_.get())); + + delegate_ = delegate; // |mcs_client_| might already be set for testing at this point. No need to // create a |connection_factory_|. @@ -184,15 +168,13 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) { return; } - user_list_->Initialize(result->serial_number_mappings); - device_checkin_info_.android_id = result->device_android_id; device_checkin_info_.secret = result->device_security_token; InitializeMCSClient(result.Pass()); if (!device_checkin_info_.IsValid()) { device_checkin_info_.Reset(); state_ = INITIAL_DEVICE_CHECKIN; - StartCheckin(0, device_checkin_info_); + StartCheckin(device_checkin_info_); return; } @@ -228,19 +210,14 @@ void GCMClientImpl::OnReady() { state_ = READY; StartMCSLogin(); - std::vector<Delegate*> delegates = user_list_->GetAllDelegates(); - for (size_t i = 0; i < delegates.size(); ++i) - delegates[i]->OnGCMReady(); + delegate_->OnGCMReady(); } void GCMClientImpl::StartMCSLogin() { DCHECK_EQ(READY, state_); DCHECK(device_checkin_info_.IsValid()); - std::vector<int64> user_serial_numbers = - user_list_->GetAllActiveUserSerialNumbers(); mcs_client_->Login(device_checkin_info_.android_id, - device_checkin_info_.secret, - user_serial_numbers); + device_checkin_info_.secret); } void GCMClientImpl::ResetState() { @@ -248,58 +225,27 @@ void GCMClientImpl::ResetState() { // TODO(fgorski): reset all of the necessart objects and start over. } -void GCMClientImpl::StartCheckin(int64 user_serial_number, - const CheckinInfo& checkin_info) { - DCHECK_EQ(0U, pending_checkins_.count(user_serial_number)); - CheckinRequest* checkin_request = +void GCMClientImpl::StartCheckin(const CheckinInfo& checkin_info) { + checkin_request_.reset( new CheckinRequest( base::Bind(&GCMClientImpl::OnCheckinCompleted, - weak_ptr_factory_.GetWeakPtr(), - user_serial_number), + weak_ptr_factory_.GetWeakPtr()), kDefaultBackoffPolicy, chrome_build_proto_, - user_serial_number, checkin_info.android_id, checkin_info.secret, - url_request_context_getter_); - pending_checkins_[user_serial_number] = checkin_request; - checkin_request->Start(); + url_request_context_getter_)); + checkin_request_->Start(); } -void GCMClientImpl::OnCheckinCompleted(int64 user_serial_number, - uint64 android_id, +void GCMClientImpl::OnCheckinCompleted(uint64 android_id, uint64 security_token) { + checkin_request_.reset(); + CheckinInfo checkin_info; checkin_info.android_id = android_id; checkin_info.secret = security_token; - // Delete the checkin request. - PendingCheckins::iterator iter = pending_checkins_.find(user_serial_number); - DCHECK(iter != pending_checkins_.end()); - delete iter->second; - pending_checkins_.erase(iter); - - if (user_serial_number == 0) { - OnDeviceCheckinCompleted(checkin_info); - return; - } - - Delegate* delegate = - user_list_->GetDelegateBySerialNumber(user_serial_number); - - // Check if the user was removed while checkin was in progress. - if (!delegate) { - DVLOG(1) << "Delegate for serial number: " << user_serial_number - << " not found after checkin completed."; - return; - } - - // TODO(fgorski): Add a reasonable Result here. It is possible that we are - // missing the right parameter on the CheckinRequest level. - delegate->OnCheckInFinished(checkin_info, SUCCESS); -} - -void GCMClientImpl::OnDeviceCheckinCompleted(const CheckinInfo& checkin_info) { if (!checkin_info.IsValid()) { // TODO(fgorski): I don't think a retry here will help, we should probalby // start over. By checking in with (0, 0). @@ -324,126 +270,72 @@ void GCMClientImpl::SetDeviceCredentialsCallback(bool success) { DCHECK(success); } -void GCMClientImpl::SetUserDelegate(const std::string& username, - Delegate* delegate) { - DCHECK(!username.empty()); - DCHECK(delegate); - user_list_->SetDelegate( - username, - delegate, - base::Bind(&GCMClientImpl::SetDelegateCompleted, - weak_ptr_factory_.GetWeakPtr())); -} - -void GCMClientImpl::SetDelegateCompleted(const std::string& username, - int64 user_serial_number) { - Delegate* delegate = user_list_->GetDelegateByUsername(username); - DCHECK(delegate); - if (state_ == READY) { - delegate->OnGCMReady(); - return; - } -} - -void GCMClientImpl::CheckIn(const std::string& username) { - DCHECK_EQ(state_, READY); - Delegate* delegate = user_list_->GetDelegateByUsername(username); - DCHECK(delegate); - int64 serial_number = user_list_->GetSerialNumberForUsername(username); - DCHECK_NE(serial_number, kInvalidSerialNumber); - StartCheckin(serial_number, delegate->GetCheckinInfo()); +void GCMClientImpl::CheckOut() { + // TODO(jianli): to be implemented. + delegate_ = NULL; } -void GCMClientImpl::Register(const std::string& username, - const std::string& app_id, +void GCMClientImpl::Register(const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids) { DCHECK_EQ(state_, READY); - Delegate* delegate = user_list_->GetDelegateByUsername(username); - DCHECK(delegate); - int64 user_serial_number = user_list_->GetSerialNumberForUsername(username); - DCHECK(user_serial_number); RegistrationRequest::RequestInfo request_info( device_checkin_info_.android_id, device_checkin_info_.secret, - delegate->GetCheckinInfo().android_id, - user_serial_number, app_id, cert, sender_ids); - PendingRegistrationKey registration_key(username, app_id); - DCHECK_EQ(0u, pending_registrations_.count(registration_key)); + DCHECK_EQ(0u, pending_registrations_.count(app_id)); RegistrationRequest* registration_request = new RegistrationRequest(request_info, kDefaultBackoffPolicy, base::Bind(&GCMClientImpl::OnRegisterCompleted, weak_ptr_factory_.GetWeakPtr(), - registration_key), + app_id), url_request_context_getter_); - pending_registrations_[registration_key] = registration_request; + pending_registrations_[app_id] = registration_request; registration_request->Start(); } -void GCMClientImpl::OnRegisterCompleted( - const PendingRegistrationKey& registration_key, - RegistrationRequest::Status status, - const std::string& registration_id) { - Delegate* delegate = user_list_->GetDelegateByUsername( - registration_key.username); - // Check if the user was removed while registration was in progress. - if (!delegate) { - DVLOG(1) << "Delegate for username: " << registration_key.username - << " not found after registration completed."; - return; - } - - std::string app_id = registration_key.app_id; - - if (status == RegistrationRequest::INVALID_SENDER) { - delegate->OnRegisterFinished( - app_id, std::string(), GCMClientImpl::INVALID_PARAMETER); - return; +void GCMClientImpl::OnRegisterCompleted(const std::string& app_id, + RegistrationRequest::Status status, + const std::string& registration_id) { + DCHECK(delegate_); + + Result result; + PendingRegistrations::iterator iter = pending_registrations_.find(app_id); + if (iter == pending_registrations_.end()) + result = UNKNOWN_ERROR; + else if (status == RegistrationRequest::INVALID_SENDER) + result = INVALID_PARAMETER; + else if (registration_id.empty()) + result = SERVER_ERROR; + else + result = SUCCESS; + + delegate_->OnRegisterFinished( + app_id, result == SUCCESS ? registration_id : std::string(), result); + + if (iter != pending_registrations_.end()) { + delete iter->second; + pending_registrations_.erase(iter); } - - if (registration_id.empty()) { - delegate->OnRegisterFinished( - app_id, std::string(), GCMClient::SERVER_ERROR); - return; - } - - PendingRegistrations::iterator iter = - pending_registrations_.find(registration_key); - if (iter == pending_registrations_.end()) { - delegate->OnRegisterFinished( - app_id, std::string(), GCMClient::UNKNOWN_ERROR); - return; - } - - delete iter->second; - pending_registrations_.erase(iter); - - delegate->OnRegisterFinished(app_id, registration_id, GCMClient::SUCCESS); } -void GCMClientImpl::Unregister(const std::string& username, - const std::string& app_id) { +void GCMClientImpl::Unregister(const std::string& app_id) { } -void GCMClientImpl::Send(const std::string& username, - const std::string& app_id, +void GCMClientImpl::Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) { DCHECK_EQ(state_, READY); - int64 serial_number = user_list_->GetSerialNumberForUsername(username); - DCHECK_NE(serial_number, kInvalidSerialNumber); mcs_proto::DataMessageStanza stanza; stanza.set_ttl(message.time_to_live); stanza.set_sent(clock_->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond); stanza.set_id(message.id); - stanza.set_device_user_id(serial_number); stanza.set_from(kSendMessageFromValue); stanza.set_to(receiver_id); stanza.set_category(app_id); @@ -484,15 +376,8 @@ void GCMClientImpl::OnMessageSentToMCS(int64 user_serial_number, const std::string& app_id, const std::string& message_id, MCSClient::MessageSendStatus status) { - Delegate* delegate = - user_list_->GetDelegateBySerialNumber(user_serial_number); - - // Check if the user was removed while message sending was in progress. - if (!delegate) { - DVLOG(1) << "Delegate for serial number: " << user_serial_number - << " not found after checkin completed."; - return; - } + DCHECK_EQ(user_serial_number, kDefaultUserSerialNumber); + DCHECK(delegate_); // TTL_EXCEEDED is singled out here, because it can happen long time after the // message was sent. That is why it comes as |OnMessageSendError| event rather @@ -504,9 +389,9 @@ void GCMClientImpl::OnMessageSentToMCS(int64 user_serial_number, // successfully. // TODO(jianli): Consider adding UMA for this status. if (status == MCSClient::TTL_EXCEEDED) - delegate->OnMessageSendError(app_id, message_id, GCMClient::TTL_EXCEEDED); + delegate_->OnMessageSendError(app_id, message_id, GCMClient::TTL_EXCEEDED); else if (status != MCSClient::SENT) - delegate->OnSendFinished(app_id, message_id, ToGCMClientResult(status)); + delegate_->OnSendFinished(app_id, message_id, ToGCMClientResult(status)); } void GCMClientImpl::OnMCSError() { @@ -528,33 +413,25 @@ void GCMClientImpl::HandleIncomingMessage(const gcm::MCSMessage& message) { incoming_message.data[key] = data_message_stanza.app_data(i).value(); } - int64 user_serial_number = data_message_stanza.device_user_id(); - Delegate* delegate = - user_list_->GetDelegateBySerialNumber(user_serial_number); - if (!delegate) { - DVLOG(1) << "Delegate for serial number: " << user_serial_number - << " not found."; - return; - } + DCHECK_EQ(data_message_stanza.device_user_id(), kDefaultUserSerialNumber); + DCHECK(delegate_); - DVLOG(1) << "Found delegate for serial number: " << user_serial_number; switch (message_type) { case DATA_MESSAGE: - delegate->OnMessageReceived(data_message_stanza.category(), - incoming_message); + delegate_->OnMessageReceived(data_message_stanza.category(), + incoming_message); break; case DELETED_MESSAGES: - delegate->OnMessagesDeleted(data_message_stanza.category()); + delegate_->OnMessagesDeleted(data_message_stanza.category()); break; case SEND_ERROR: NotifyDelegateOnMessageSendError( - delegate, data_message_stanza.category(), incoming_message); + delegate_, data_message_stanza.category(), incoming_message); break; case UNKNOWN: default: // Treat default the same as UNKNOWN. DVLOG(1) << "Unknown message_type received. Message ignored. " - << "App ID: " << data_message_stanza.category() << ", " - << "User serial number: " << user_serial_number << "."; + << "App ID: " << data_message_stanza.category() << "."; break; } } diff --git a/google_apis/gcm/gcm_client_impl.h b/google_apis/gcm/gcm_client_impl.h index bcd111b..3e59702 100644 --- a/google_apis/gcm/gcm_client_impl.h +++ b/google_apis/gcm/gcm_client_impl.h @@ -35,7 +35,7 @@ namespace gcm { class CheckinRequest; class ConnectionFactory; class GCMClientImplTest; -class UserList; +class RegistrationRequest; // Implements the GCM Client. It is used to coordinate MCS Client (communication // with MCS) and other pieces of GCM infrastructure like Registration and @@ -52,18 +52,14 @@ class GCM_EXPORT GCMClientImpl : public GCMClient { const base::FilePath& store_path, const scoped_refptr<base::SequencedTaskRunner>& blocking_task_runner, const scoped_refptr<net::URLRequestContextGetter>& - url_request_context_getter) OVERRIDE; - virtual void SetUserDelegate(const std::string& username, - Delegate* delegate) OVERRIDE; - virtual void CheckIn(const std::string& username) OVERRIDE; - virtual void Register(const std::string& username, - const std::string& app_id, + url_request_context_getter, + Delegate* delegate) OVERRIDE; + virtual void CheckOut() OVERRIDE; + virtual void Register(const std::string& app_id, const std::string& cert, const std::vector<std::string>& sender_ids) OVERRIDE; - virtual void Unregister(const std::string& username, - const std::string& app_id) OVERRIDE; - virtual void Send(const std::string& username, - const std::string& app_id, + virtual void Unregister(const std::string& app_id) OVERRIDE; + virtual void Send(const std::string& app_id, const std::string& receiver_id, const OutgoingMessage& message) OVERRIDE; virtual bool IsReady() const OVERRIDE; @@ -81,27 +77,23 @@ class GCM_EXPORT GCMClientImpl : public GCMClient { READY, }; - // Collection of pending checkin requests. Keys are serial numbers of the - // users as assigned by the user_list_. Values are pending checkin requests to - // obtain android IDs and security tokens for the users. - typedef std::map<int64, CheckinRequest*> PendingCheckins; - - // A pair of |username| and |app_id| identifying a pending - // RegistrationRequest. - struct PendingRegistrationKey { - PendingRegistrationKey(const std::string& username, - const std::string& app_id); - ~PendingRegistrationKey(); - bool operator<(const PendingRegistrationKey& rhs) const; - - std::string username; - std::string app_id; + // The check-in info for the user. Returned by the server. + struct GCM_EXPORT CheckinInfo { + CheckinInfo() : android_id(0), secret(0) {} + bool IsValid() const { return android_id != 0 && secret != 0; } + void Reset() { + android_id = 0; + secret = 0; + } + + uint64 android_id; + uint64 secret; }; - // Collection of pending registration requests. Keys are pairs of |username| - // and |app_id|, while values are pending registration requests to obtain a - // registration ID for requesting application. - typedef std::map<PendingRegistrationKey, RegistrationRequest*> + // Collection of pending registration requests. Keys are app_id, while values + // are pending registration requests to obtain a registration ID for + // requesting application. + typedef std::map<std::string, RegistrationRequest*> PendingRegistrations; friend class GCMClientImplTest; @@ -132,33 +124,22 @@ class GCM_EXPORT GCMClientImpl : public GCMClient { // delegates. void OnReady(); - // Startes a checkin request for a user with specified |serial_number|. - // Checkin info can be invalid, in which case it is considered a first time - // checkin. - void StartCheckin(int64 user_serial_number, - const CheckinInfo& checkin_info); - // Completes the checkin request for the specified |serial_number|. + // Starts a first time device checkin. + void StartCheckin(const CheckinInfo& checkin_info); + // Completes the device checkin request. // |android_id| and |security_token| are expected to be non-zero or an error // is triggered. Function also cleans up the pending checkin. - void OnCheckinCompleted(int64 user_serial_number, - uint64 android_id, + void OnCheckinCompleted(uint64 android_id, uint64 security_token); - // Completes the checkin request for a device (serial number of 0). - void OnDeviceCheckinCompleted(const CheckinInfo& checkin_info); // Callback for persisting device credentials in the |gcm_store_|. void SetDeviceCredentialsCallback(bool success); // Completes the registration request. - void OnRegisterCompleted(const PendingRegistrationKey& registration_key, + void OnRegisterCompleted(const std::string& app_id, RegistrationRequest::Status status, const std::string& registration_id); - // Callback for setting a delegate on a |user_list_|. Informs that the - // delegate with matching |username| was assigned a |user_serial_number|. - void SetDelegateCompleted(const std::string& username, - int64 user_serial_number); - // Handles incoming data message and dispatches it the a relevant user // delegate. void HandleIncomingMessage(const gcm::MCSMessage& message); @@ -179,6 +160,8 @@ class GCM_EXPORT GCMClientImpl : public GCMClient { // State of the GCM Client Implementation. State state_; + Delegate* delegate_; + // Device checkin info (android ID and security token used by device). CheckinInfo device_checkin_info_; @@ -194,10 +177,6 @@ class GCM_EXPORT GCMClientImpl : public GCMClient { // serial number mappings. scoped_ptr<GCMStore> gcm_store_; - // Keeps the mappings of user's serial numbers and assigns new serial numbers - // once a user delegate is added for the first time. - scoped_ptr<UserList> user_list_; - scoped_refptr<net::HttpNetworkSession> network_session_; net::BoundNetLog net_log_; scoped_ptr<ConnectionFactory> connection_factory_; @@ -206,9 +185,7 @@ class GCM_EXPORT GCMClientImpl : public GCMClient { // Controls receiving and sending of packets and reliable message queueing. scoped_ptr<MCSClient> mcs_client_; - // Currently pending checkins. GCMClientImpl owns the CheckinRequests. - PendingCheckins pending_checkins_; - STLValueDeleter<PendingCheckins> pending_checkins_deleter_; + scoped_ptr<CheckinRequest> checkin_request_; // Currently pending registrations. GCMClientImpl owns the // RegistrationRequests. diff --git a/google_apis/gcm/gcm_client_impl_unittest.cc b/google_apis/gcm/gcm_client_impl_unittest.cc index 3f482f4..b048778 100644 --- a/google_apis/gcm/gcm_client_impl_unittest.cc +++ b/google_apis/gcm/gcm_client_impl_unittest.cc @@ -28,7 +28,6 @@ namespace { enum LastEvent { NONE, LOADING_COMPLETED, - CHECKIN_COMPLETED, REGISTRATION_COMPLETED, MESSAGE_SEND_ERROR, MESSAGE_RECEIVED, @@ -38,9 +37,6 @@ enum LastEvent { const uint64 kDeviceAndroidId = 54321; const uint64 kDeviceSecurityToken = 12345; const char kRegistrationResponsePrefix[] = "token="; -const char kUsername[] = "test"; -const uint64 kUserAndroidId = 67890; -const uint64 kUserSecurityToken = 9876; // Helper for building arbitrary data messages. MCSMessage BuildDownstreamMessage( @@ -48,7 +44,6 @@ MCSMessage BuildDownstreamMessage( const std::string& app_id, const std::map<std::string, std::string>& data) { mcs_proto::DataMessageStanza data_message; - data_message.set_device_user_id(1); data_message.set_from(project_id); data_message.set_category(app_id); for (std::map<std::string, std::string>::const_iterator iter = data.begin(); @@ -66,9 +61,7 @@ class FakeMCSClient : public MCSClient { FakeMCSClient(base::Clock* clock, ConnectionFactory* connection_factory); virtual ~FakeMCSClient(); - virtual void Login(uint64 android_id, - uint64 security_token, - const std::vector<int64>& user_serial_numbers) OVERRIDE; + virtual void Login(uint64 android_id, uint64 security_token) OVERRIDE; virtual void SendMessage(const MCSMessage& message) OVERRIDE; void set_gcm_store(GCMStore* gcm_store); @@ -101,9 +94,7 @@ void FakeMCSClient::set_gcm_store(GCMStore* gcm_store) { SetGCMStoreForTesting(gcm_store); } -void FakeMCSClient::Login(uint64 android_id, - uint64 security_token, - const std::vector<int64>& user_serial_numbers) { +void FakeMCSClient::Login(uint64 android_id, uint64 security_token) { last_android_id_ = android_id; last_security_token_ = security_token; } @@ -134,8 +125,6 @@ class GCMClientImplTest : public testing::Test, void CompleteRegistration(const std::string& registration_id); // GCMClient::Delegate overrides (for verification). - virtual void OnCheckInFinished(const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) OVERRIDE; virtual void OnRegisterFinished(const std::string& app_id, const std::string& registration_id, GCMClient::Result result) OVERRIDE; @@ -149,13 +138,8 @@ class GCMClientImplTest : public testing::Test, virtual void OnMessageSendError(const std::string& app_id, const std::string& message_id, GCMClient::Result result) OVERRIDE; - virtual GCMClient::CheckinInfo GetCheckinInfo() const OVERRIDE { - return checkin_info_; - } virtual void OnGCMReady() OVERRIDE; - void SetCheckinInfo(uint64 android_id, uint64 security_token); - GCMClientImpl* gcm_client() const { return gcm_client_.get(); } FakeMCSClient* mcs_client() const { return reinterpret_cast<FakeMCSClient*>(gcm_client_->mcs_client_.get()); @@ -168,9 +152,6 @@ class GCMClientImplTest : public testing::Test, } const std::string& last_message_id() const { return last_message_id_; } GCMClient::Result last_result() const { return last_result_; } - const GCMClient::CheckinInfo& last_checkin_info() const { - return last_checkin_info_; - } const GCMClient::IncomingMessage& last_message() const { return last_message_; } @@ -193,11 +174,9 @@ class GCMClientImplTest : public testing::Test, std::string last_registration_id_; std::string last_message_id_; GCMClient::Result last_result_; - GCMClient::CheckinInfo last_checkin_info_; GCMClient::IncomingMessage last_message_; scoped_ptr<GCMClientImpl> gcm_client_; - GCMClient::CheckinInfo checkin_info_; scoped_ptr<FakeConnectionFactory> connection_factory_; base::MessageLoop message_loop_; @@ -223,8 +202,6 @@ void GCMClientImplTest::SetUp() { run_loop_.reset(new base::RunLoop); BuildGCMClient(); InitializeGCMClient(); - gcm_client()->SetUserDelegate(kUsername, this); - PumpLoop(); } void GCMClientImplTest::PumpLoop() { @@ -289,7 +266,8 @@ void GCMClientImplTest::InitializeGCMClient() { gcm_client_->Initialize(chrome_build_proto, temp_directory_.path(), message_loop_.message_loop_proxy(), - url_request_context_getter_); + url_request_context_getter_, + this); #if defined(OS_MACOSX) // On OSX, prevent the Keychain permissions popup during unit tests. Encryptor::UseMockKeychain(true); // Must be after Initialize. @@ -298,7 +276,6 @@ void GCMClientImplTest::InitializeGCMClient() { mcs_client()->set_gcm_store(gcm_client_->gcm_store_.get()); PumpLoopUntilIdle(); CompleteCheckin(kDeviceAndroidId, kDeviceSecurityToken); - PumpLoopUntilIdle(); } void GCMClientImplTest::ReceiveMessageFromMCS(const MCSMessage& message) { @@ -310,15 +287,6 @@ void GCMClientImplTest::OnGCMReady() { QuitLoop(); } -void GCMClientImplTest::OnCheckInFinished( - const GCMClient::CheckinInfo& checkin_info, - GCMClient::Result result) { - last_event_ = CHECKIN_COMPLETED; - last_checkin_info_.android_id = checkin_info.android_id; - last_checkin_info_.secret = checkin_info.secret; - last_result_ = result; -} - void GCMClientImplTest::OnMessageReceived( const std::string& registration_id, const GCMClient::IncomingMessage& message) { @@ -355,34 +323,16 @@ int64 GCMClientImplTest::CurrentTime() { return clock()->Now().ToInternalValue() / base::Time::kMicrosecondsPerSecond; } -void GCMClientImplTest::SetCheckinInfo( - uint64 android_id, - uint64 security_token) { - checkin_info_.android_id = android_id; - checkin_info_.secret = security_token; -} - TEST_F(GCMClientImplTest, LoadingCompleted) { EXPECT_EQ(LOADING_COMPLETED, last_event()); EXPECT_EQ(kDeviceAndroidId, mcs_client()->last_android_id()); EXPECT_EQ(kDeviceSecurityToken, mcs_client()->last_security_token()); } -TEST_F(GCMClientImplTest, CheckInUser) { - gcm_client()->CheckIn(kUsername); - CompleteCheckin(kUserAndroidId, kUserSecurityToken); - - EXPECT_EQ(CHECKIN_COMPLETED, last_event()); - EXPECT_EQ(kUserAndroidId, last_checkin_info().android_id); - EXPECT_EQ(kUserSecurityToken, last_checkin_info().secret); - EXPECT_EQ(GCMClient::SUCCESS, last_result()); -} - TEST_F(GCMClientImplTest, RegisterApp) { std::vector<std::string> senders; senders.push_back("sender"); - SetCheckinInfo(kUserAndroidId, kUserSecurityToken); - gcm_client()->Register(kUsername, "app_id", "cert", senders); + gcm_client()->Register("app_id", "cert", senders); CompleteRegistration("reg_id"); EXPECT_EQ(REGISTRATION_COMPLETED, last_event()); @@ -442,7 +392,7 @@ TEST_F(GCMClientImplTest, SendMessage) { message.id = "007"; message.time_to_live = 500; message.data["key"] = "value"; - gcm_client()->Send(kUsername, "app_id", "project_id", message); + gcm_client()->Send("app_id", "project_id", message); EXPECT_EQ(kDataMessageStanzaTag, mcs_client()->last_message_tag()); EXPECT_EQ("app_id", mcs_client()->last_data_message_stanza().category()); @@ -450,7 +400,6 @@ TEST_F(GCMClientImplTest, SendMessage) { EXPECT_EQ(500, mcs_client()->last_data_message_stanza().ttl()); EXPECT_EQ(CurrentTime(), mcs_client()->last_data_message_stanza().sent()); EXPECT_EQ("007", mcs_client()->last_data_message_stanza().id()); - EXPECT_EQ(1, mcs_client()->last_data_message_stanza().device_user_id()); EXPECT_EQ("gcm@chrome.com", mcs_client()->last_data_message_stanza().from()); EXPECT_EQ("project_id", mcs_client()->last_data_message_stanza().to()); EXPECT_EQ("key", mcs_client()->last_data_message_stanza().app_data(0).key()); diff --git a/google_apis/gcm/tools/mcs_probe.cc b/google_apis/gcm/tools/mcs_probe.cc index b0de673..28e6fd3 100644 --- a/google_apis/gcm/tools/mcs_probe.cc +++ b/google_apis/gcm/tools/mcs_probe.cc @@ -79,7 +79,6 @@ const net::BackoffEntry::Policy kDefaultBackoffPolicy = { // Default values used to communicate with the check-in server. const char kChromeVersion[] = "Chrome MCS Probe"; -const int64 kUserSerialNumber = 1; // The default server to communicate with. const char kMCSServerHost[] = "mtalk.google.com"; @@ -89,7 +88,6 @@ const uint16 kMCSServerPort = 5228; const char kRMQFileName[] = "rmq_file"; const char kAndroidIdSwitch[] = "android_id"; const char kSecretSwitch[] = "secret"; -const char kEnableMultiUserSwitch[] = "enable-multi-user"; const char kLogFileSwitch[] = "log-file"; const char kIgnoreCertSwitch[] = "ignore-certs"; const char kServerHostSwitch[] = "host"; @@ -223,7 +221,6 @@ class MCSProbe { uint64 secret_; std::string server_host_; int server_port_; - bool enable_multi_user_; // Network state. scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; @@ -260,7 +257,6 @@ MCSProbe::MCSProbe( android_id_(0), secret_(0), server_port_(0), - enable_multi_user_(false), url_request_context_getter_(url_request_context_getter), file_thread_("FileThread") { if (command_line.HasSwitch(kRMQFileName)) { @@ -274,9 +270,6 @@ MCSProbe::MCSProbe( base::StringToUint64(command_line.GetSwitchValueASCII(kSecretSwitch), &secret_); } - if (command_line.HasSwitch(kEnableMultiUserSwitch)) { - enable_multi_user_ = true; - } server_host_ = kMCSServerHost; if (command_line.HasSwitch(kServerHostSwitch)) { server_host_ = command_line.GetSwitchValueASCII(kServerHostSwitch); @@ -430,7 +423,6 @@ void MCSProbe::CheckIn() { base::Bind(&MCSProbe::OnCheckInCompleted, base::Unretained(this)), kDefaultBackoffPolicy, chrome_build_proto, - kUserSerialNumber, 0, 0, url_request_context_getter_.get())); @@ -456,10 +448,7 @@ void MCSProbe::OnCheckInCompleted(uint64 android_id, uint64 secret) { void MCSProbe::StartMCSLogin() { LOG(INFO) << "MCS login initiated."; - std::vector<int64> user_serial_numbers; - if (enable_multi_user_) - user_serial_numbers.push_back(1LL); - mcs_client_->Login(android_id_, secret_, user_serial_numbers); + mcs_client_->Login(android_id_, secret_); } int MCSProbeMain(int argc, char* argv[]) { |