diff options
author | jianli <jianli@chromium.org> | 2015-05-26 16:24:47 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-05-26 23:25:26 +0000 |
commit | 7a0c9b6d322d0a501fc114d3854df944fc059f0f (patch) | |
tree | ab8af00aaa656b0288ae748f007baa3dfb0c370f /components/gcm_driver/instance_id | |
parent | 45ab39af3cc293e150158bf06515a47319db9f79 (diff) | |
download | chromium_src-7a0c9b6d322d0a501fc114d3854df944fc059f0f.zip chromium_src-7a0c9b6d322d0a501fc114d3854df944fc059f0f.tar.gz chromium_src-7a0c9b6d322d0a501fc114d3854df944fc059f0f.tar.bz2 |
Support getting and deleting token for Instance ID.
GCM's registration and unregistration request have been refactored to
support token requests for Instance ID.
BUG=477084
TEST=new tests
Review URL: https://codereview.chromium.org/1137463003
Cr-Commit-Position: refs/heads/master@{#331475}
Diffstat (limited to 'components/gcm_driver/instance_id')
6 files changed, 370 insertions, 58 deletions
diff --git a/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.cc b/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.cc index 2a50a03..6b09da0 100644 --- a/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.cc +++ b/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.cc @@ -6,6 +6,9 @@ #include "base/bind.h" #include "base/message_loop/message_loop.h" +#include "base/rand_util.h" +#include "base/strings/string_number_conversions.h" +#include "components/gcm_driver/gcm_client.h" namespace instance_id { @@ -15,14 +18,15 @@ FakeGCMDriverForInstanceID::FakeGCMDriverForInstanceID() { FakeGCMDriverForInstanceID::~FakeGCMDriverForInstanceID() { } -gcm::InstanceIDStore* FakeGCMDriverForInstanceID::GetInstanceIDStore() { +gcm::InstanceIDHandler* FakeGCMDriverForInstanceID::GetInstanceIDHandler() { return this; } void FakeGCMDriverForInstanceID::AddInstanceIDData( const std::string& app_id, - const std::string& instance_id_data) { - instance_id_data_[app_id] = instance_id_data; + const std::string& instance_id, + const std::string& extra_data) { + instance_id_data_[app_id] = std::make_pair(instance_id, extra_data); } void FakeGCMDriverForInstanceID::RemoveInstanceIDData( @@ -32,14 +36,50 @@ void FakeGCMDriverForInstanceID::RemoveInstanceIDData( void FakeGCMDriverForInstanceID::GetInstanceIDData( const std::string& app_id, - const gcm::InstanceIDStore::GetInstanceIDDataCallback& callback) { - std::string data; + const GetInstanceIDDataCallback& callback) { auto iter = instance_id_data_.find(app_id); - if (iter != instance_id_data_.end()) - data = iter->second; + std::string instance_id; + std::string extra_data; + if (iter != instance_id_data_.end()) { + instance_id = iter->second.first; + extra_data = iter->second.second; + } base::MessageLoop::current()->PostTask( FROM_HERE, - base::Bind(callback, data)); + base::Bind(callback, instance_id, extra_data)); +} + +void FakeGCMDriverForInstanceID::GetToken( + const std::string& app_id, + const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options, + const GetTokenCallback& callback) { + std::string token; + std::string key = app_id + authorized_entity + scope; + auto iter = tokens_.find(key); + if (iter != tokens_.end()) { + token = iter->second; + } else { + token = base::Uint64ToString(base::RandUint64()); + tokens_[key] = token; + } + + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(callback, token, gcm::GCMClient::SUCCESS)); +} + +void FakeGCMDriverForInstanceID::DeleteToken( + const std::string& app_id, + const std::string& authorized_entity, + const std::string& scope, + const DeleteTokenCallback& callback) { + std::string key = app_id + authorized_entity + scope; + tokens_.erase(key); + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(callback, gcm::GCMClient::SUCCESS)); } } // namespace instance_id diff --git a/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h b/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h index d5f9dd1..9d6b77a 100644 --- a/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h +++ b/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h @@ -7,6 +7,7 @@ #include <map> #include <string> +#include <utility> #include "base/compiler_specific.h" #include "base/macros.h" @@ -15,24 +16,35 @@ namespace instance_id { class FakeGCMDriverForInstanceID : public gcm::FakeGCMDriver, - public gcm::InstanceIDStore { + public gcm::InstanceIDHandler { public: FakeGCMDriverForInstanceID(); ~FakeGCMDriverForInstanceID() override; // FakeGCMDriver overrides: - gcm::InstanceIDStore* GetInstanceIDStore() override; - - // InstanceIDStore overrides: + gcm::InstanceIDHandler* GetInstanceIDHandler() override; + + // InstanceIDHandler overrides: + void GetToken(const std::string& app_id, + const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options, + const GetTokenCallback& callback) override; + void DeleteToken(const std::string& app_id, + const std::string& authorized_entity, + const std::string& scope, + const DeleteTokenCallback& callback) override; void AddInstanceIDData(const std::string& app_id, - const std::string& instance_id_data) override; + const std::string& instance_id, + const std::string& extra_data) override; void RemoveInstanceIDData(const std::string& app_id) override; void GetInstanceIDData( const std::string& app_id, - const gcm::InstanceIDStore::GetInstanceIDDataCallback& callback) override; + const GetInstanceIDDataCallback& callback) override; private: - std::map<std::string, std::string> instance_id_data_; + std::map<std::string, std::pair<std::string, std::string>> instance_id_data_; + std::map<std::string, std::string> tokens_; DISALLOW_COPY_AND_ASSIGN(FakeGCMDriverForInstanceID); }; diff --git a/components/gcm_driver/instance_id/instance_id.h b/components/gcm_driver/instance_id/instance_id.h index 8141a3a..343b9c5 100644 --- a/components/gcm_driver/instance_id/instance_id.h +++ b/components/gcm_driver/instance_id/instance_id.h @@ -30,6 +30,8 @@ class InstanceID { INVALID_PARAMETER, // Instance ID is disabled. DISABLED, + // Previous asynchronous operation is still pending to finish. + ASYNC_OPERATION_PENDING, // Network socket error. NETWORK_ERROR, // Problem at the server. diff --git a/components/gcm_driver/instance_id/instance_id_driver_unittest.cc b/components/gcm_driver/instance_id/instance_id_driver_unittest.cc index 41305b5..5e79331 100644 --- a/components/gcm_driver/instance_id/instance_id_driver_unittest.cc +++ b/components/gcm_driver/instance_id/instance_id_driver_unittest.cc @@ -19,6 +19,10 @@ namespace { const char kTestAppID1[] = "TestApp1"; const char kTestAppID2[] = "TestApp2"; +const char kAuthorizedEntity1[] = "Sender 1"; +const char kAuthorizedEntity2[] = "Sender 2"; +const char kScope1[] = "GCM1"; +const char kScope2[] = "FooBar"; bool VerifyInstanceID(const std::string& str) { // Checks the length. @@ -53,6 +57,15 @@ class InstanceIDDriverTest : public testing::Test { std::string GetID(InstanceID* instance_id); base::Time GetCreationTime(InstanceID* instance_id); InstanceID::Result DeleteID(InstanceID* instance_id); + std::string GetToken( + InstanceID* instance_id, + const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options); + InstanceID::Result DeleteToken( + InstanceID* instance_id, + const std::string& authorized_entity, + const std::string& scope); InstanceIDDriver* driver() const { return driver_.get(); } @@ -60,6 +73,8 @@ class InstanceIDDriverTest : public testing::Test { void GetIDCompleted(const std::string& id); void GetCreationTimeCompleted(const base::Time& creation_time); void DeleteIDCompleted(InstanceID::Result result); + void GetTokenCompleted(const std::string& token, InstanceID::Result result); + void DeleteTokenCompleted(InstanceID::Result result); base::MessageLoopForUI message_loop_; scoped_ptr<FakeGCMDriverForInstanceID> gcm_driver_; @@ -67,6 +82,7 @@ class InstanceIDDriverTest : public testing::Test { std::string id_; base::Time creation_time_; + std::string token_; InstanceID::Result result_; bool async_operation_completed_; @@ -129,7 +145,41 @@ InstanceID::Result InstanceIDDriverTest::DeleteID(InstanceID* instance_id) { return result_; } +std::string InstanceIDDriverTest::GetToken( + InstanceID* instance_id, + const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options) { + async_operation_completed_ = false; + token_.clear(); + result_ = InstanceID::UNKNOWN_ERROR;; + instance_id->GetToken( + authorized_entity, + scope, + options, + base::Bind(&InstanceIDDriverTest::GetTokenCompleted, + base::Unretained(this))); + WaitForAsyncOperation(); + return token_; +} + +InstanceID::Result InstanceIDDriverTest::DeleteToken( + InstanceID* instance_id, + const std::string& authorized_entity, + const std::string& scope) { + async_operation_completed_ = false; + result_ = InstanceID::UNKNOWN_ERROR;; + instance_id->DeleteToken( + authorized_entity, + scope, + base::Bind(&InstanceIDDriverTest::DeleteTokenCompleted, + base::Unretained(this))); + WaitForAsyncOperation(); + return result_; +} + void InstanceIDDriverTest::GetIDCompleted(const std::string& id) { + DCHECK(!async_operation_completed_); async_operation_completed_ = true; id_ = id; if (!async_operation_completed_callback_.is_null()) @@ -138,6 +188,7 @@ void InstanceIDDriverTest::GetIDCompleted(const std::string& id) { void InstanceIDDriverTest::GetCreationTimeCompleted( const base::Time& creation_time) { + DCHECK(!async_operation_completed_); async_operation_completed_ = true; creation_time_ = creation_time; if (!async_operation_completed_callback_.is_null()) @@ -145,6 +196,25 @@ void InstanceIDDriverTest::GetCreationTimeCompleted( } void InstanceIDDriverTest::DeleteIDCompleted(InstanceID::Result result) { + DCHECK(!async_operation_completed_); + async_operation_completed_ = true; + result_ = result; + if (!async_operation_completed_callback_.is_null()) + async_operation_completed_callback_.Run(); +} + +void InstanceIDDriverTest::GetTokenCompleted( + const std::string& token, InstanceID::Result result){ + DCHECK(!async_operation_completed_); + async_operation_completed_ = true; + token_ = token; + result_ = result; + if (!async_operation_completed_callback_.is_null()) + async_operation_completed_callback_.Run(); +} + +void InstanceIDDriverTest::DeleteTokenCompleted(InstanceID::Result result) { + DCHECK(!async_operation_completed_); async_operation_completed_ = true; result_ = result; if (!async_operation_completed_callback_.is_null()) @@ -220,4 +290,55 @@ TEST_F(InstanceIDDriverTest, DeleteID) { EXPECT_FALSE(GetCreationTime(instance_id).is_null()); } +TEST_F(InstanceIDDriverTest, GetToken) { + InstanceID* instance_id = driver()->GetInstanceID(kTestAppID1); + std::map<std::string, std::string> options; + std::string token1 = + GetToken(instance_id, kAuthorizedEntity1, kScope1, options); + EXPECT_FALSE(token1.empty()); + + // Same token is returned for same authorized entity and scope. + EXPECT_EQ(token1, + GetToken(instance_id, kAuthorizedEntity1, kScope1, options)); + + // Different token is returned for different authorized entity or scope. + std::string token2 = + GetToken(instance_id, kAuthorizedEntity1, kScope2, options); + EXPECT_FALSE(token2.empty()); + EXPECT_NE(token1, token2); + + std::string token3 = + GetToken(instance_id, kAuthorizedEntity2, kScope1, options); + EXPECT_FALSE(token3.empty()); + EXPECT_NE(token1, token3); + EXPECT_NE(token2, token3); +} + +TEST_F(InstanceIDDriverTest, DeleteToken) { + InstanceID* instance_id = driver()->GetInstanceID(kTestAppID1); + std::map<std::string, std::string> options; + + // Gets 2 tokens. + std::string token1 = + GetToken(instance_id, kAuthorizedEntity1, kScope1, options); + EXPECT_FALSE(token1.empty()); + std::string token2 = + GetToken(instance_id, kAuthorizedEntity2, kScope1, options); + EXPECT_FALSE(token1.empty()); + EXPECT_NE(token1, token2); + + // Different token is returned for same authorized entity and scope after + // deletion. + EXPECT_EQ(InstanceID::SUCCESS, + DeleteToken(instance_id, kAuthorizedEntity1, kScope1)); + std::string new_token1 = + GetToken(instance_id, kAuthorizedEntity1, kScope2, options); + EXPECT_FALSE(new_token1.empty()); + EXPECT_NE(token1, new_token1); + + // The other token is not affected by the deletion. + EXPECT_EQ(token2, + GetToken(instance_id, kAuthorizedEntity2, kScope1, options)); +} + } // instance_id diff --git a/components/gcm_driver/instance_id/instance_id_impl.cc b/components/gcm_driver/instance_id/instance_id_impl.cc index b77cf3f..e9c347e 100644 --- a/components/gcm_driver/instance_id/instance_id_impl.cc +++ b/components/gcm_driver/instance_id/instance_id_impl.cc @@ -15,6 +15,34 @@ namespace instance_id { +namespace { + +InstanceID::Result GCMClientResultToInstanceIDResult( + gcm::GCMClient::Result result) { + switch (result) { + case gcm::GCMClient::SUCCESS: + return InstanceID::SUCCESS; + case gcm::GCMClient::INVALID_PARAMETER: + return InstanceID::INVALID_PARAMETER; + case gcm::GCMClient::ASYNC_OPERATION_PENDING: + return InstanceID::ASYNC_OPERATION_PENDING; + case gcm::GCMClient::GCM_DISABLED: + return InstanceID::DISABLED; + case gcm::GCMClient::NETWORK_ERROR: + return InstanceID::NETWORK_ERROR; + case gcm::GCMClient::SERVER_ERROR: + return InstanceID::SERVER_ERROR; + case gcm::GCMClient::UNKNOWN_ERROR: + return InstanceID::UNKNOWN_ERROR; + default: + NOTREACHED() << "Unexpected value of result cannot be converted: " + << result; + } + return InstanceID::UNKNOWN_ERROR; +} + +} // namespace + // static InstanceID* InstanceID::Create(const std::string& app_id, gcm::GCMDriver* gcm_driver) { @@ -27,7 +55,7 @@ InstanceIDImpl::InstanceIDImpl(const std::string& app_id, gcm_driver_(gcm_driver), load_from_store_(false), weak_ptr_factory_(this) { - gcm_driver_->GetInstanceIDStore()->GetInstanceIDData( + GetInstanceIDHandler()->GetInstanceIDData( app_id, base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted, weak_ptr_factory_.GetWeakPtr())); @@ -75,32 +103,148 @@ void InstanceIDImpl::GetToken( const std::string& scope, const std::map<std::string, std::string>& options, const GetTokenCallback& callback) { - NOTIMPLEMENTED(); + if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { + delayed_task_controller_.AddTask( + base::Bind(&InstanceIDImpl::DoGetToken, + weak_ptr_factory_.GetWeakPtr(), + authorized_entity, + scope, + options, + callback)); + return; + } + + DoGetToken(authorized_entity, scope, options, callback); +} + +void InstanceIDImpl::DoGetToken( + const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options, + const GetTokenCallback& callback) { + EnsureIDGenerated(); + + GetInstanceIDHandler()->GetToken( + app_id(), + authorized_entity, + scope, + options, + base::Bind(&InstanceIDImpl::OnGetTokenCompleted, + weak_ptr_factory_.GetWeakPtr(), + callback)); } void InstanceIDImpl::DeleteToken(const std::string& authorized_entity, const std::string& scope, const DeleteTokenCallback& callback) { - NOTIMPLEMENTED(); + if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { + delayed_task_controller_.AddTask( + base::Bind(&InstanceIDImpl::DoDeleteToken, + weak_ptr_factory_.GetWeakPtr(), + authorized_entity, + scope, + callback)); + return; + } + + DoDeleteToken(authorized_entity, scope, callback); +} + +void InstanceIDImpl::DoDeleteToken( + const std::string& authorized_entity, + const std::string& scope, + const DeleteTokenCallback& callback) { + // Nothing to delete if the ID has not been generated. + if (id_.empty()) { + callback.Run(InstanceID::SUCCESS); + return; + } + + GetInstanceIDHandler()->DeleteToken( + app_id(), + authorized_entity, + scope, + base::Bind(&InstanceIDImpl::OnDeleteTokenCompleted, + weak_ptr_factory_.GetWeakPtr(), + callback)); } void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) { - gcm_driver_->GetInstanceIDStore()->RemoveInstanceIDData(app_id()); + if (!delayed_task_controller_.CanRunTaskWithoutDelay()) { + delayed_task_controller_.AddTask( + base::Bind(&InstanceIDImpl::DoDeleteID, + weak_ptr_factory_.GetWeakPtr(), + callback)); + return; + } + + DoDeleteID(callback); +} + +void InstanceIDImpl::DoDeleteID(const DeleteIDCallback& callback) { + // Nothing to do if ID has not been generated. + if (id_.empty()) { + callback.Run(InstanceID::SUCCESS); + return; + } + + GetInstanceIDHandler()->DeleteToken( + app_id(), + "*", + "*", + base::Bind(&InstanceIDImpl::OnDeleteIDCompleted, + weak_ptr_factory_.GetWeakPtr(), + callback)); + + GetInstanceIDHandler()->RemoveInstanceIDData(app_id()); id_.clear(); creation_time_ = base::Time(); +} + +void InstanceIDImpl::OnGetTokenCompleted(const GetTokenCallback& callback, + const std::string& token, + gcm::GCMClient::Result result) { + callback.Run(token, GCMClientResultToInstanceIDResult(result)); +} + +void InstanceIDImpl::OnDeleteTokenCompleted( + const DeleteTokenCallback& callback, + gcm::GCMClient::Result result) { + callback.Run(GCMClientResultToInstanceIDResult(result)); +} - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(callback, InstanceID::SUCCESS)); +void InstanceIDImpl::OnDeleteIDCompleted( + const DeleteIDCallback& callback, + gcm::GCMClient::Result result) { + callback.Run(GCMClientResultToInstanceIDResult(result)); } void InstanceIDImpl::GetInstanceIDDataCompleted( - const std::string& instance_id_data) { - Deserialize(instance_id_data); + const std::string& instance_id, + const std::string& extra_data) { + id_ = instance_id; + + if (extra_data.empty()) { + creation_time_ = base::Time(); + } else { + int64 time_internal = 0LL; + if (!base::StringToInt64(extra_data, &time_internal)) { + DVLOG(1) << "Failed to parse the time data: " + extra_data; + return; + } + creation_time_ = base::Time::FromInternalValue(time_internal); + } + delayed_task_controller_.SetReady(); } +gcm::InstanceIDHandler* InstanceIDImpl::GetInstanceIDHandler() const { + gcm::InstanceIDHandler* handler = gcm_driver_->GetInstanceIDHandler(); + DCHECK(handler); + return handler; +} + void InstanceIDImpl::EnsureIDGenerated() { if (!id_.empty()) return; @@ -131,35 +275,10 @@ void InstanceIDImpl::EnsureIDGenerated() { creation_time_ = base::Time::Now(); // Save to the persistent store. - gcm_driver_->GetInstanceIDStore()->AddInstanceIDData( - app_id(), SerializeAsString()); -} - -std::string InstanceIDImpl::SerializeAsString() const { - std::string serialized_data; - serialized_data += id_; - serialized_data += ","; - serialized_data += base::Int64ToString(creation_time_.ToInternalValue()); - return serialized_data; -} - -void InstanceIDImpl::Deserialize(const std::string& serialized_data) { - if (serialized_data.empty()) - return; - std::size_t pos = serialized_data.find(','); - if (pos == std::string::npos) { - DVLOG(1) << "Failed to deserialize the InstanceID data: " + serialized_data; - return; - } - - id_ = serialized_data.substr(0, pos); - - int64 time_internal = 0LL; - if (!base::StringToInt64(serialized_data.substr(pos + 1), &time_internal)) { - DVLOG(1) << "Failed to deserialize the InstanceID data: " + serialized_data; - return; - } - creation_time_ = base::Time::FromInternalValue(time_internal); + GetInstanceIDHandler()->AddInstanceIDData( + app_id(), + id_, + base::Int64ToString(creation_time_.ToInternalValue())); } } // namespace instance_id diff --git a/components/gcm_driver/instance_id/instance_id_impl.h b/components/gcm_driver/instance_id/instance_id_impl.h index a5124c1..8b0d942 100644 --- a/components/gcm_driver/instance_id/instance_id_impl.h +++ b/components/gcm_driver/instance_id/instance_id_impl.h @@ -13,11 +13,13 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" #include "base/time/time.h" +#include "components/gcm_driver/gcm_client.h" #include "components/gcm_driver/gcm_delayed_task_controller.h" #include "components/gcm_driver/instance_id/instance_id.h" namespace gcm { class GCMDriver; +class InstanceIDHandler; } // namespace gcm namespace instance_id { @@ -41,15 +43,31 @@ class InstanceIDImpl : public InstanceID { void DeleteID(const DeleteIDCallback& callback) override; private: + gcm::InstanceIDHandler* GetInstanceIDHandler() const; + void EnsureIDGenerated(); - void GetInstanceIDDataCompleted(const std::string& instance_id_data); + + void OnGetTokenCompleted(const GetTokenCallback& callback, + const std::string& token, + gcm::GCMClient::Result result); + void OnDeleteTokenCompleted(const DeleteTokenCallback& callback, + gcm::GCMClient::Result result); + void OnDeleteIDCompleted(const DeleteIDCallback& callback, + gcm::GCMClient::Result result); + void GetInstanceIDDataCompleted(const std::string& instance_id, + const std::string& extra_data); void DoGetID(const GetIDCallback& callback); void DoGetCreationTime(const GetCreationTimeCallback& callback); - - // Encodes/decodes the InstanceID data to work with the persistent store. - std::string SerializeAsString() const; - void Deserialize(const std::string& serialized_data); + void DoGetToken( + const std::string& authorized_entity, + const std::string& scope, + const std::map<std::string, std::string>& options, + const GetTokenCallback& callback); + void DoDeleteToken(const std::string& authorized_entity, + const std::string& scope, + const DeleteTokenCallback& callback); + void DoDeleteID(const DeleteIDCallback& callback); gcm::GCMDriver* gcm_driver_; // Not owned. |