summaryrefslogtreecommitdiffstats
path: root/components/gcm_driver
diff options
context:
space:
mode:
authorjianli <jianli@chromium.org>2015-05-11 14:14:13 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-11 21:14:58 +0000
commit10018b2d2d5954cb697ccad19eef63919aef0786 (patch)
tree7f5f4fa86eacf75884463c87438ddfe84b1fd4f1 /components/gcm_driver
parente8624082aaf1743e46f2868f807ac164c587d77b (diff)
downloadchromium_src-10018b2d2d5954cb697ccad19eef63919aef0786.zip
chromium_src-10018b2d2d5954cb697ccad19eef63919aef0786.tar.gz
chromium_src-10018b2d2d5954cb697ccad19eef63919aef0786.tar.bz2
Persist Instance ID data to GCM store.
BUG=477084 TEST=new tests TBR=asvitkine@chromium.org Review URL: https://codereview.chromium.org/1126233004 Cr-Commit-Position: refs/heads/master@{#329233}
Diffstat (limited to 'components/gcm_driver')
-rw-r--r--components/gcm_driver/fake_gcm_client.cc11
-rw-r--r--components/gcm_driver/fake_gcm_client.h4
-rw-r--r--components/gcm_driver/fake_gcm_driver.cc4
-rw-r--r--components/gcm_driver/fake_gcm_driver.h1
-rw-r--r--components/gcm_driver/gcm_client.h11
-rw-r--r--components/gcm_driver/gcm_client_impl.cc26
-rw-r--r--components/gcm_driver/gcm_client_impl.h7
-rw-r--r--components/gcm_driver/gcm_driver.cc6
-rw-r--r--components/gcm_driver/gcm_driver.h23
-rw-r--r--components/gcm_driver/gcm_driver_android.cc5
-rw-r--r--components/gcm_driver/gcm_driver_android.h1
-rw-r--r--components/gcm_driver/gcm_driver_desktop.cc82
-rw-r--r--components/gcm_driver/gcm_driver_desktop.h17
-rw-r--r--components/gcm_driver/instance_id/BUILD.gn5
-rw-r--r--components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.cc45
-rw-r--r--components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h42
-rw-r--r--components/gcm_driver/instance_id/fake_instance_id_driver.cc16
-rw-r--r--components/gcm_driver/instance_id/fake_instance_id_driver.h27
-rw-r--r--components/gcm_driver/instance_id/instance_id.h7
-rw-r--r--components/gcm_driver/instance_id/instance_id_android.cc7
-rw-r--r--components/gcm_driver/instance_id/instance_id_android.h6
-rw-r--r--components/gcm_driver/instance_id/instance_id_driver_unittest.cc143
-rw-r--r--components/gcm_driver/instance_id/instance_id_impl.cc82
-rw-r--r--components/gcm_driver/instance_id/instance_id_impl.h23
24 files changed, 510 insertions, 91 deletions
diff --git a/components/gcm_driver/fake_gcm_client.cc b/components/gcm_driver/fake_gcm_client.cc
index 1795288..ffa77d1 100644
--- a/components/gcm_driver/fake_gcm_client.cc
+++ b/components/gcm_driver/fake_gcm_client.cc
@@ -137,6 +137,17 @@ void FakeGCMClient::SetLastTokenFetchTime(const base::Time& time) {
void FakeGCMClient::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) {
}
+void FakeGCMClient::AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) {
+}
+
+void FakeGCMClient::RemoveInstanceIDData(const std::string& app_id) {
+}
+
+std::string FakeGCMClient::GetInstanceIDData(const std::string& app_id) {
+ return std::string();
+}
+
void FakeGCMClient::PerformDelayedStart() {
DCHECK(ui_thread_->RunsTasksOnCurrentThread());
diff --git a/components/gcm_driver/fake_gcm_client.h b/components/gcm_driver/fake_gcm_client.h
index 21d696d..c0b03da 100644
--- a/components/gcm_driver/fake_gcm_client.h
+++ b/components/gcm_driver/fake_gcm_client.h
@@ -56,6 +56,10 @@ class FakeGCMClient : public GCMClient {
void RemoveAccountMapping(const std::string& account_id) override;
void SetLastTokenFetchTime(const base::Time& time) override;
void UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) override;
+ void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) override;
+ void RemoveInstanceIDData(const std::string& app_id) override;
+ std::string GetInstanceIDData(const std::string& app_id) override;
// Initiate the start that has been delayed.
// Called on UI thread.
diff --git a/components/gcm_driver/fake_gcm_driver.cc b/components/gcm_driver/fake_gcm_driver.cc
index 45791f6..c6f7d9e 100644
--- a/components/gcm_driver/fake_gcm_driver.cc
+++ b/components/gcm_driver/fake_gcm_driver.cc
@@ -98,4 +98,8 @@ void FakeGCMDriver::SetLastTokenFetchTime(const base::Time& time) {
void FakeGCMDriver::WakeFromSuspendForHeartbeat(bool wake) {
}
+InstanceIDStore* FakeGCMDriver::GetInstanceIDStore() {
+ return NULL;
+}
+
} // namespace gcm
diff --git a/components/gcm_driver/fake_gcm_driver.h b/components/gcm_driver/fake_gcm_driver.h
index 9b57af2e..5e334c6 100644
--- a/components/gcm_driver/fake_gcm_driver.h
+++ b/components/gcm_driver/fake_gcm_driver.h
@@ -41,6 +41,7 @@ class FakeGCMDriver : public GCMDriver {
base::Time GetLastTokenFetchTime() override;
void SetLastTokenFetchTime(const base::Time& time) override;
void WakeFromSuspendForHeartbeat(bool wake) override;
+ InstanceIDStore* GetInstanceIDStore() override;
protected:
// GCMDriver implementation:
diff --git a/components/gcm_driver/gcm_client.h b/components/gcm_driver/gcm_client.h
index 2aa224a..cd804b2 100644
--- a/components/gcm_driver/gcm_client.h
+++ b/components/gcm_driver/gcm_client.h
@@ -309,6 +309,17 @@ class GCMClient {
// Updates the timer used by the HeartbeatManager for sending heartbeats.
virtual void UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) = 0;
+
+ // Adds the Instance ID data for a specific app to the persistent store.
+ virtual void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) = 0;
+
+ // Removes the Instance ID data for a specific app from the persistent store.
+ virtual void RemoveInstanceIDData(const std::string& app_id) = 0;
+
+ // Retrieves the Instance ID data for a specific app from the persistent
+ // store.
+ virtual std::string GetInstanceIDData(const std::string& app_id) = 0;
};
} // namespace gcm
diff --git a/components/gcm_driver/gcm_client_impl.cc b/components/gcm_driver/gcm_client_impl.cc
index 1c9f64f..8fb162d 100644
--- a/components/gcm_driver/gcm_client_impl.cc
+++ b/components/gcm_driver/gcm_client_impl.cc
@@ -348,6 +348,7 @@ void GCMClientImpl::OnLoadCompleted(scoped_ptr<GCMStore::LoadResult> result) {
device_checkin_info_.accounts_set = true;
last_checkin_time_ = result->last_checkin_time;
gservices_settings_.UpdateFromLoadResult(*result);
+ instance_id_data_ = result->instance_id_data;
load_result_ = result.Pass();
state_ = LOADED;
@@ -530,6 +531,31 @@ void GCMClientImpl::UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) {
mcs_client_->UpdateHeartbeatTimer(timer.Pass());
}
+void GCMClientImpl::AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) {
+ instance_id_data_[app_id] = instance_id_data;
+ gcm_store_->AddInstanceIDData(
+ app_id,
+ instance_id_data,
+ base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void GCMClientImpl::RemoveInstanceIDData(const std::string& app_id) {
+ instance_id_data_.erase(app_id);
+ gcm_store_->RemoveInstanceIDData(
+ app_id,
+ base::Bind(&GCMClientImpl::IgnoreWriteResultCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+std::string GCMClientImpl::GetInstanceIDData(const std::string& app_id) {
+ auto iter = instance_id_data_.find(app_id);
+ if (iter == instance_id_data_.end())
+ return std::string();
+ return iter->second;
+}
+
void GCMClientImpl::StartCheckin() {
// Make sure no checkin is in progress.
if (checkin_request_.get())
diff --git a/components/gcm_driver/gcm_client_impl.h b/components/gcm_driver/gcm_client_impl.h
index 65b04a6..2db1805 100644
--- a/components/gcm_driver/gcm_client_impl.h
+++ b/components/gcm_driver/gcm_client_impl.h
@@ -126,6 +126,10 @@ class GCMClientImpl
void RemoveAccountMapping(const std::string& account_id) override;
void SetLastTokenFetchTime(const base::Time& time) override;
void UpdateHeartbeatTimer(scoped_ptr<base::Timer> timer) override;
+ void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) override;
+ void RemoveInstanceIDData(const std::string& app_id) override;
+ std::string GetInstanceIDData(const std::string& app_id) override;
// GCMStatsRecorder::Delegate implemenation.
void OnActivityRecorded() override;
@@ -341,6 +345,9 @@ class GCMClientImpl
// Time of the last successful checkin.
base::Time last_checkin_time_;
+ // Cached instance ID data, key is app id.
+ std::map<std::string, std::string> instance_id_data_;
+
// Factory for creating references when scheduling periodic checkin.
base::WeakPtrFactory<GCMClientImpl> periodic_checkin_ptr_factory_;
diff --git a/components/gcm_driver/gcm_driver.cc b/components/gcm_driver/gcm_driver.cc
index 080ba52..1b115c0 100644
--- a/components/gcm_driver/gcm_driver.cc
+++ b/components/gcm_driver/gcm_driver.cc
@@ -12,6 +12,12 @@
namespace gcm {
+InstanceIDStore::InstanceIDStore() {
+}
+
+InstanceIDStore::~InstanceIDStore() {
+}
+
GCMDriver::GCMDriver() : weak_ptr_factory_(this) {
}
diff --git a/components/gcm_driver/gcm_driver.h b/components/gcm_driver/gcm_driver.h
index fb20f3a..aac0975 100644
--- a/components/gcm_driver/gcm_driver.h
+++ b/components/gcm_driver/gcm_driver.h
@@ -22,6 +22,26 @@ class GCMAppHandler;
class GCMConnectionObserver;
struct AccountMapping;
+// Provides the capability to set/get InstanceID data in the GCM store.
+class InstanceIDStore {
+ public:
+ typedef base::Callback<void(const std::string& instance_id_data)>
+ GetInstanceIDDataCallback;
+
+ InstanceIDStore();
+ virtual ~InstanceIDStore();
+
+ virtual void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) = 0;
+ virtual void RemoveInstanceIDData(const std::string& app_id) = 0;
+ virtual void GetInstanceIDData(
+ const std::string& app_id,
+ const GetInstanceIDDataCallback& callback) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InstanceIDStore);
+};
+
// Bridge between GCM users in Chrome and the platform-specific implementation.
class GCMDriver {
public:
@@ -146,6 +166,9 @@ class GCMDriver {
// to send a heartbeat message.
virtual void WakeFromSuspendForHeartbeat(bool wake) = 0;
+ // Supports saving the Instance ID data in the GCM store.
+ virtual InstanceIDStore* GetInstanceIDStore() = 0;
+
protected:
// Ensures that the GCM service starts (if necessary conditions are met).
virtual GCMClient::Result EnsureStarted(GCMClient::StartMode start_mode) = 0;
diff --git a/components/gcm_driver/gcm_driver_android.cc b/components/gcm_driver/gcm_driver_android.cc
index 2f82fbe..ec69952 100644
--- a/components/gcm_driver/gcm_driver_android.cc
+++ b/components/gcm_driver/gcm_driver_android.cc
@@ -162,6 +162,11 @@ void GCMDriverAndroid::SetLastTokenFetchTime(const base::Time& time) {
void GCMDriverAndroid::WakeFromSuspendForHeartbeat(bool wake) {
}
+InstanceIDStore* GCMDriverAndroid::GetInstanceIDStore() {
+ // Not supported for Android.
+ return NULL;
+}
+
GCMClient::Result GCMDriverAndroid::EnsureStarted(
GCMClient::StartMode start_mode) {
// TODO(johnme): Maybe we should check if GMS is available?
diff --git a/components/gcm_driver/gcm_driver_android.h b/components/gcm_driver/gcm_driver_android.h
index 41c47b5..3c5d357 100644
--- a/components/gcm_driver/gcm_driver_android.h
+++ b/components/gcm_driver/gcm_driver_android.h
@@ -64,6 +64,7 @@ class GCMDriverAndroid : public GCMDriver {
base::Time GetLastTokenFetchTime() override;
void SetLastTokenFetchTime(const base::Time& time) override;
void WakeFromSuspendForHeartbeat(bool wake) override;
+ InstanceIDStore* GetInstanceIDStore() override;
protected:
// GCMDriver implementation:
diff --git a/components/gcm_driver/gcm_driver_desktop.cc b/components/gcm_driver/gcm_driver_desktop.cc
index 7db396d..a711999 100644
--- a/components/gcm_driver/gcm_driver_desktop.cc
+++ b/components/gcm_driver/gcm_driver_desktop.cc
@@ -87,6 +87,10 @@ class GCMDriverDesktop::IOWorker : public GCMClient::Delegate {
void RemoveAccountMapping(const std::string& account_id);
void SetLastTokenFetchTime(const base::Time& time);
void WakeFromSuspendForHeartbeat(bool wake);
+ void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data);
+ void RemoveInstanceIDData(const std::string& app_id);
+ void GetInstanceIDData(const std::string& app_id);
// For testing purpose. Can be called from UI thread. Use with care.
GCMClient* gcm_client_for_testing() const { return gcm_client_.get(); }
@@ -343,6 +347,37 @@ void GCMDriverDesktop::IOWorker::SetLastTokenFetchTime(const base::Time& time) {
gcm_client_->SetLastTokenFetchTime(time);
}
+void GCMDriverDesktop::IOWorker::AddInstanceIDData(
+ const std::string& app_id,
+ const std::string& instance_id_data) {
+ DCHECK(io_thread_->RunsTasksOnCurrentThread());
+
+ if (gcm_client_.get())
+ gcm_client_->AddInstanceIDData(app_id, instance_id_data);
+}
+
+void GCMDriverDesktop::IOWorker::RemoveInstanceIDData(
+ const std::string& app_id) {
+ DCHECK(io_thread_->RunsTasksOnCurrentThread());
+
+ if (gcm_client_.get())
+ gcm_client_->RemoveInstanceIDData(app_id);
+}
+
+void GCMDriverDesktop::IOWorker::GetInstanceIDData(
+ const std::string& app_id) {
+ DCHECK(io_thread_->RunsTasksOnCurrentThread());
+
+ std::string instance_id_data;
+ if (gcm_client_.get())
+ instance_id_data = gcm_client_->GetInstanceIDData(app_id);
+
+ ui_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&GCMDriverDesktop::GetInstanceIDDataFinished,
+ service_, app_id, instance_id_data));
+}
+
void GCMDriverDesktop::IOWorker::WakeFromSuspendForHeartbeat(bool wake) {
#if defined(OS_CHROMEOS)
DCHECK(io_thread_->RunsTasksOnCurrentThread());
@@ -659,6 +694,53 @@ void GCMDriverDesktop::SetLastTokenFetchTime(const base::Time& time) {
time));
}
+InstanceIDStore* GCMDriverDesktop::GetInstanceIDStore() {
+ return this;
+}
+
+void GCMDriverDesktop::AddInstanceIDData(
+ const std::string& app_id,
+ const std::string& instance_id_data) {
+ DCHECK(ui_thread_->RunsTasksOnCurrentThread());
+
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&GCMDriverDesktop::IOWorker::AddInstanceIDData,
+ base::Unretained(io_worker_.get()),
+ app_id,
+ instance_id_data));
+}
+
+void GCMDriverDesktop::RemoveInstanceIDData(const std::string& app_id) {
+ DCHECK(ui_thread_->RunsTasksOnCurrentThread());
+
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&GCMDriverDesktop::IOWorker::RemoveInstanceIDData,
+ base::Unretained(io_worker_.get()),
+ app_id));
+}
+
+void GCMDriverDesktop::GetInstanceIDData(
+ const std::string& app_id,
+ const GetInstanceIDDataCallback& callback) {
+ DCHECK(!get_instance_id_data_callbacks_.count(app_id));
+ get_instance_id_data_callbacks_[app_id] = callback;
+ io_thread_->PostTask(
+ FROM_HERE,
+ base::Bind(&GCMDriverDesktop::IOWorker::GetInstanceIDData,
+ base::Unretained(io_worker_.get()),
+ app_id));
+}
+
+void GCMDriverDesktop::GetInstanceIDDataFinished(
+ const std::string& app_id,
+ const std::string& instance_id_data) {
+ DCHECK(get_instance_id_data_callbacks_.count(app_id));
+ get_instance_id_data_callbacks_[app_id].Run(instance_id_data);
+ get_instance_id_data_callbacks_.erase(app_id);
+}
+
void GCMDriverDesktop::WakeFromSuspendForHeartbeat(bool wake) {
DCHECK(ui_thread_->RunsTasksOnCurrentThread());
diff --git a/components/gcm_driver/gcm_driver_desktop.h b/components/gcm_driver/gcm_driver_desktop.h
index 422f0f5..f52dd6bb 100644
--- a/components/gcm_driver/gcm_driver_desktop.h
+++ b/components/gcm_driver/gcm_driver_desktop.h
@@ -43,7 +43,8 @@ class GCMClientFactory;
class GCMDelayedTaskController;
// GCMDriver implementation for desktop and Chrome OS, using GCMClient.
-class GCMDriverDesktop : public GCMDriver {
+class GCMDriverDesktop : public GCMDriver,
+ public InstanceIDStore {
public:
GCMDriverDesktop(
scoped_ptr<GCMClientFactory> gcm_client_factory,
@@ -83,6 +84,14 @@ class GCMDriverDesktop : public GCMDriver {
base::Time GetLastTokenFetchTime() override;
void SetLastTokenFetchTime(const base::Time& time) override;
void WakeFromSuspendForHeartbeat(bool wake) override;
+ InstanceIDStore* GetInstanceIDStore() override;
+
+ // InstanceIDStore overrides:
+ void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) override;
+ void RemoveInstanceIDData(const std::string& app_id) override;
+ void GetInstanceIDData(const std::string& app_id,
+ const GetInstanceIDDataCallback& callback) override;
// Exposed for testing purpose.
bool gcm_enabled() const { return gcm_enabled_; }
@@ -130,6 +139,8 @@ class GCMDriverDesktop : public GCMDriver {
void OnDisconnected();
void GetGCMStatisticsFinished(const GCMClient::GCMStatistics& stats);
+ void GetInstanceIDDataFinished(const std::string& app_id,
+ const std::string& instance_id_data);
scoped_ptr<GCMChannelStatusSyncer> gcm_channel_status_syncer_;
@@ -172,6 +183,10 @@ class GCMDriverDesktop : public GCMDriver {
// Callback for GetGCMStatistics.
GetGCMStatisticsCallback request_gcm_statistics_callback_;
+ // Callbacks for GetInstanceIDData.
+ std::map<std::string, GetInstanceIDDataCallback>
+ get_instance_id_data_callbacks_;
+
// Used to pass a weak pointer to the IO worker.
base::WeakPtrFactory<GCMDriverDesktop> weak_ptr_factory_;
diff --git a/components/gcm_driver/instance_id/BUILD.gn b/components/gcm_driver/instance_id/BUILD.gn
index 430de17..179828f 100644
--- a/components/gcm_driver/instance_id/BUILD.gn
+++ b/components/gcm_driver/instance_id/BUILD.gn
@@ -34,12 +34,13 @@ source_set("instance_id") {
source_set("test_support") {
testonly = true
sources = [
- "fake_instance_id_driver.cc",
- "fake_instance_id_driver.h",
+ "fake_gcm_driver_for_instance_id.cc",
+ "fake_gcm_driver_for_instance_id.h",
]
deps = [
":instance_id",
+ "//components/gcm_driver:test_support",
"//testing/gtest",
]
}
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
new file mode 100644
index 0000000..2a50a03
--- /dev/null
+++ b/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.cc
@@ -0,0 +1,45 @@
+// Copyright 2015 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 "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+
+namespace instance_id {
+
+FakeGCMDriverForInstanceID::FakeGCMDriverForInstanceID() {
+}
+
+FakeGCMDriverForInstanceID::~FakeGCMDriverForInstanceID() {
+}
+
+gcm::InstanceIDStore* FakeGCMDriverForInstanceID::GetInstanceIDStore() {
+ return this;
+}
+
+void FakeGCMDriverForInstanceID::AddInstanceIDData(
+ const std::string& app_id,
+ const std::string& instance_id_data) {
+ instance_id_data_[app_id] = instance_id_data;
+}
+
+void FakeGCMDriverForInstanceID::RemoveInstanceIDData(
+ const std::string& app_id) {
+ instance_id_data_.erase(app_id);
+}
+
+void FakeGCMDriverForInstanceID::GetInstanceIDData(
+ const std::string& app_id,
+ const gcm::InstanceIDStore::GetInstanceIDDataCallback& callback) {
+ std::string data;
+ auto iter = instance_id_data_.find(app_id);
+ if (iter != instance_id_data_.end())
+ data = iter->second;
+ base::MessageLoop::current()->PostTask(
+ FROM_HERE,
+ base::Bind(callback, data));
+}
+
+} // 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
new file mode 100644
index 0000000..d5f9dd1
--- /dev/null
+++ b/components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h
@@ -0,0 +1,42 @@
+// Copyright 2015 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 COMPONENTS_GCM_DRIVER_INSTANCE_ID_FAKE_GCM_DRIVER__FOR_INSTANCE_ID_H_
+#define COMPONENTS_GCM_DRIVER_INSTANCE_ID_FAKE_GCM_DRIVER__FOR_INSTANCE_ID_H_
+
+#include <map>
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "components/gcm_driver/fake_gcm_driver.h"
+
+namespace instance_id {
+
+class FakeGCMDriverForInstanceID : public gcm::FakeGCMDriver,
+ public gcm::InstanceIDStore {
+ public:
+ FakeGCMDriverForInstanceID();
+ ~FakeGCMDriverForInstanceID() override;
+
+ // FakeGCMDriver overrides:
+ gcm::InstanceIDStore* GetInstanceIDStore() override;
+
+ // InstanceIDStore overrides:
+ void AddInstanceIDData(const std::string& app_id,
+ const std::string& instance_id_data) override;
+ void RemoveInstanceIDData(const std::string& app_id) override;
+ void GetInstanceIDData(
+ const std::string& app_id,
+ const gcm::InstanceIDStore::GetInstanceIDDataCallback& callback) override;
+
+ private:
+ std::map<std::string, std::string> instance_id_data_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeGCMDriverForInstanceID);
+};
+
+} // namespace instance_id
+
+#endif // COMPONENTS_GCM_DRIVER_INSTANCE_ID_FAKE_GCM_DRIVER__FOR_INSTANCE_ID_H_
diff --git a/components/gcm_driver/instance_id/fake_instance_id_driver.cc b/components/gcm_driver/instance_id/fake_instance_id_driver.cc
deleted file mode 100644
index 6b88f22..0000000
--- a/components/gcm_driver/instance_id/fake_instance_id_driver.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2015 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 "components/gcm_driver/instance_id/fake_instance_id_driver.h"
-
-namespace instance_id {
-
-FakeInstanceIDDriver::FakeInstanceIDDriver()
- : InstanceIDDriver(NULL) {
-}
-
-FakeInstanceIDDriver::~FakeInstanceIDDriver() {
-}
-
-} // namespace instance_id
diff --git a/components/gcm_driver/instance_id/fake_instance_id_driver.h b/components/gcm_driver/instance_id/fake_instance_id_driver.h
deleted file mode 100644
index 60fc0b2..0000000
--- a/components/gcm_driver/instance_id/fake_instance_id_driver.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2015 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 COMPONENTS_GCM_DRIVER_INSTANCE_ID_FAKE_INSTANCE_ID_DRIVER_H_
-#define COMPONENTS_GCM_DRIVER_INSTANCE_ID_FAKE_INSTANCE_ID_DRIVER_H_
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "components/gcm_driver/instance_id/instance_id_driver.h"
-
-namespace instance_id {
-
-class InstanceID;
-
-class FakeInstanceIDDriver : public InstanceIDDriver {
- public:
- FakeInstanceIDDriver();
- ~FakeInstanceIDDriver() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FakeInstanceIDDriver);
-};
-
-} // namespace instance_id
-
-#endif // COMPONENTS_GCM_DRIVER_INSTANCE_ID_FAKE_INSTANCE_ID_DRIVER_H_
diff --git a/components/gcm_driver/instance_id/instance_id.h b/components/gcm_driver/instance_id/instance_id.h
index 731d274..8141a3a 100644
--- a/components/gcm_driver/instance_id/instance_id.h
+++ b/components/gcm_driver/instance_id/instance_id.h
@@ -41,6 +41,9 @@ class InstanceID {
// Asynchronous callbacks.
typedef base::Callback<void(const std::string& app_id,
bool update_id)> TokenRefreshCallback;
+ typedef base::Callback<void(const std::string& id)> GetIDCallback;
+ typedef base::Callback<void(const base::Time& creation_time)>
+ GetCreationTimeCallback;
typedef base::Callback<void(const std::string& token,
Result result)> GetTokenCallback;
typedef base::Callback<void(Result result)> DeleteTokenCallback;
@@ -62,10 +65,10 @@ class InstanceID {
void SetTokenRefreshCallback(const TokenRefreshCallback& callback);
// Returns the Instance ID.
- virtual std::string GetID() = 0;
+ virtual void GetID(const GetIDCallback& callback) = 0;
// Returns the time when the InstanceID has been generated.
- virtual base::Time GetCreationTime() = 0;
+ virtual void GetCreationTime(const GetCreationTimeCallback& callback) = 0;
// Retrieves a token that allows the authorized entity to access the service
// defined as "scope".
diff --git a/components/gcm_driver/instance_id/instance_id_android.cc b/components/gcm_driver/instance_id/instance_id_android.cc
index 2057a814..9e7a164 100644
--- a/components/gcm_driver/instance_id/instance_id_android.cc
+++ b/components/gcm_driver/instance_id/instance_id_android.cc
@@ -21,14 +21,13 @@ InstanceIDAndroid::InstanceIDAndroid(const std::string& app_id)
InstanceIDAndroid::~InstanceIDAndroid() {
}
-std::string InstanceIDAndroid::GetID() {
+void InstanceIDAndroid::GetID(const GetIDCallback& callback) {
NOTIMPLEMENTED();
- return std::string();
}
-base::Time InstanceIDAndroid::GetCreationTime() {
+void InstanceIDAndroid::GetCreationTime(
+ const GetCreationTimeCallback& callback) {
NOTIMPLEMENTED();
- return base::Time();
}
void InstanceIDAndroid::GetToken(
diff --git a/components/gcm_driver/instance_id/instance_id_android.h b/components/gcm_driver/instance_id/instance_id_android.h
index b09901a..7a6babf 100644
--- a/components/gcm_driver/instance_id/instance_id_android.h
+++ b/components/gcm_driver/instance_id/instance_id_android.h
@@ -19,12 +19,12 @@ namespace instance_id {
// InstanceID implementation for Android.
class InstanceIDAndroid : public InstanceID {
public:
- explicit InstanceIDAndroid(const std::string& app_id);
+ InstanceIDAndroid(const std::string& app_id);
~InstanceIDAndroid() override;
// InstanceID:
- std::string GetID() override;
- base::Time GetCreationTime() override;
+ void GetID(const GetIDCallback& callback) override;
+ void GetCreationTime(const GetCreationTimeCallback& callback) override;
void GetToken(const std::string& audience,
const std::string& scope,
const std::map<std::string, std::string>& options,
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 37a1040..41305b5 100644
--- a/components/gcm_driver/instance_id/instance_id_driver_unittest.cc
+++ b/components/gcm_driver/instance_id/instance_id_driver_unittest.cc
@@ -9,7 +9,7 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
-#include "components/gcm_driver/fake_gcm_driver.h"
+#include "components/gcm_driver/instance_id/fake_gcm_driver_for_instance_id.h"
#include "components/gcm_driver/instance_id/instance_id.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -46,41 +46,107 @@ class InstanceIDDriverTest : public testing::Test {
void WaitForAsyncOperation();
- void DeleteIDCompleted(InstanceID::Result result);
+ // Recreates InstanceIDDriver to simulate restart.
+ void RecreateInstanceIDDriver();
+
+ // Sync wrappers for async version.
+ std::string GetID(InstanceID* instance_id);
+ base::Time GetCreationTime(InstanceID* instance_id);
+ InstanceID::Result DeleteID(InstanceID* instance_id);
InstanceIDDriver* driver() const { return driver_.get(); }
- InstanceID::Result delete_id_result() const { return delete_id_result_; }
private:
+ void GetIDCompleted(const std::string& id);
+ void GetCreationTimeCompleted(const base::Time& creation_time);
+ void DeleteIDCompleted(InstanceID::Result result);
+
base::MessageLoopForUI message_loop_;
- scoped_ptr<gcm::FakeGCMDriver> gcm_driver_;
+ scoped_ptr<FakeGCMDriverForInstanceID> gcm_driver_;
scoped_ptr<InstanceIDDriver> driver_;
- InstanceID::Result delete_id_result_;
+
+ std::string id_;
+ base::Time creation_time_;
+ InstanceID::Result result_;
+
+ bool async_operation_completed_;
base::Closure async_operation_completed_callback_;
DISALLOW_COPY_AND_ASSIGN(InstanceIDDriverTest);
};
InstanceIDDriverTest::InstanceIDDriverTest()
- : delete_id_result_(InstanceID::UNKNOWN_ERROR) {
+ : result_(InstanceID::UNKNOWN_ERROR),
+ async_operation_completed_(false) {
}
InstanceIDDriverTest::~InstanceIDDriverTest() {
}
void InstanceIDDriverTest::SetUp() {
- gcm_driver_.reset(new gcm::FakeGCMDriver);
+ gcm_driver_.reset(new FakeGCMDriverForInstanceID);
+ RecreateInstanceIDDriver();
+}
+
+void InstanceIDDriverTest::RecreateInstanceIDDriver() {
driver_.reset(new InstanceIDDriver(gcm_driver_.get()));
}
void InstanceIDDriverTest::WaitForAsyncOperation() {
+ // No need to wait if async operation is not needed.
+ if (async_operation_completed_)
+ return;
base::RunLoop run_loop;
async_operation_completed_callback_ = run_loop.QuitClosure();
run_loop.Run();
}
+std::string InstanceIDDriverTest::GetID(InstanceID* instance_id) {
+ async_operation_completed_ = false;
+ id_.clear();
+ instance_id->GetID(base::Bind(&InstanceIDDriverTest::GetIDCompleted,
+ base::Unretained(this)));
+ WaitForAsyncOperation();
+ return id_;
+}
+
+base::Time InstanceIDDriverTest::GetCreationTime(InstanceID* instance_id) {
+ async_operation_completed_ = false;
+ creation_time_ = base::Time();
+ instance_id->GetCreationTime(
+ base::Bind(&InstanceIDDriverTest::GetCreationTimeCompleted,
+ base::Unretained(this)));
+ WaitForAsyncOperation();
+ return creation_time_;
+}
+
+InstanceID::Result InstanceIDDriverTest::DeleteID(InstanceID* instance_id) {
+ async_operation_completed_ = false;
+ result_ = InstanceID::UNKNOWN_ERROR;;
+ instance_id->DeleteID(base::Bind(&InstanceIDDriverTest::DeleteIDCompleted,
+ base::Unretained(this)));
+ WaitForAsyncOperation();
+ return result_;
+}
+
+void InstanceIDDriverTest::GetIDCompleted(const std::string& id) {
+ async_operation_completed_ = true;
+ id_ = id;
+ if (!async_operation_completed_callback_.is_null())
+ async_operation_completed_callback_.Run();
+}
+
+void InstanceIDDriverTest::GetCreationTimeCompleted(
+ const base::Time& creation_time) {
+ async_operation_completed_ = true;
+ creation_time_ = creation_time;
+ if (!async_operation_completed_callback_.is_null())
+ async_operation_completed_callback_.Run();
+}
+
void InstanceIDDriverTest::DeleteIDCompleted(InstanceID::Result result) {
- delete_id_result_ = result;
+ async_operation_completed_ = true;
+ result_ = result;
if (!async_operation_completed_callback_.is_null())
async_operation_completed_callback_.Run();
}
@@ -88,45 +154,70 @@ void InstanceIDDriverTest::DeleteIDCompleted(InstanceID::Result result) {
TEST_F(InstanceIDDriverTest, NewID) {
// Creation time should not be set when the ID is not created.
InstanceID* instance_id1 = driver()->GetInstanceID(kTestAppID1);
- EXPECT_TRUE(instance_id1->GetCreationTime().is_null());
+ EXPECT_TRUE(GetCreationTime(instance_id1).is_null());
// New ID is generated for the first time.
- std::string id1 = instance_id1->GetID();
- EXPECT_FALSE(id1.empty());
+ std::string id1 = GetID(instance_id1);
EXPECT_TRUE(VerifyInstanceID(id1));
- base::Time creation_time = instance_id1->GetCreationTime();
+ base::Time creation_time = GetCreationTime(instance_id1);
EXPECT_FALSE(creation_time.is_null());
// Same ID is returned for the same app.
- EXPECT_EQ(id1, instance_id1->GetID());
- EXPECT_EQ(creation_time, instance_id1->GetCreationTime());
+ EXPECT_EQ(id1, GetID(instance_id1));
+ EXPECT_EQ(creation_time, GetCreationTime(instance_id1));
// New ID is generated for another app.
InstanceID* instance_id2 = driver()->GetInstanceID(kTestAppID2);
- std::string id2 = instance_id2->GetID();
- EXPECT_FALSE(id2.empty());
+ std::string id2 = GetID(instance_id2);
EXPECT_TRUE(VerifyInstanceID(id2));
EXPECT_NE(id1, id2);
- EXPECT_FALSE(instance_id2->GetCreationTime().is_null());
+ EXPECT_FALSE(GetCreationTime(instance_id2).is_null());
+}
+
+TEST_F(InstanceIDDriverTest, PersistID) {
+ InstanceID* instance_id = driver()->GetInstanceID(kTestAppID1);
+
+ // Create the ID for the first time. The ID and creation time should be saved
+ // to the store.
+ std::string id = GetID(instance_id);
+ EXPECT_FALSE(id.empty());
+ base::Time creation_time = GetCreationTime(instance_id);
+ EXPECT_FALSE(creation_time.is_null());
+
+ // Simulate restart by recreating InstanceIDDriver. Same ID and creation time
+ // should be expected.
+ RecreateInstanceIDDriver();
+ instance_id = driver()->GetInstanceID(kTestAppID1);
+ EXPECT_EQ(creation_time, GetCreationTime(instance_id));
+ EXPECT_EQ(id, GetID(instance_id));
+
+ // Delete the ID. The ID and creation time should be removed from the store.
+ EXPECT_EQ(InstanceID::SUCCESS, DeleteID(instance_id));
+ EXPECT_TRUE(GetCreationTime(instance_id).is_null());
+
+ // Simulate restart by recreating InstanceIDDriver. Different ID should be
+ // expected.
+ // Note that we do not check for different creation time since the test might
+ // be run at a very fast server.
+ RecreateInstanceIDDriver();
+ instance_id = driver()->GetInstanceID(kTestAppID1);
+ EXPECT_NE(id, GetID(instance_id));
}
TEST_F(InstanceIDDriverTest, DeleteID) {
InstanceID* instance_id = driver()->GetInstanceID(kTestAppID1);
- std::string id1 = instance_id->GetID();
+ std::string id1 = GetID(instance_id);
EXPECT_FALSE(id1.empty());
- EXPECT_FALSE(instance_id->GetCreationTime().is_null());
+ EXPECT_FALSE(GetCreationTime(instance_id).is_null());
// New ID will be generated from GetID after calling DeleteID.
- instance_id->DeleteID(base::Bind(&InstanceIDDriverTest::DeleteIDCompleted,
- base::Unretained(this)));
- WaitForAsyncOperation();
- EXPECT_EQ(InstanceID::SUCCESS, delete_id_result());
- EXPECT_TRUE(instance_id->GetCreationTime().is_null());
+ EXPECT_EQ(InstanceID::SUCCESS, DeleteID(instance_id));
+ EXPECT_TRUE(GetCreationTime(instance_id).is_null());
- std::string id2 = instance_id->GetID();
+ std::string id2 = GetID(instance_id);
EXPECT_FALSE(id2.empty());
EXPECT_NE(id1, id2);
- EXPECT_FALSE(instance_id->GetCreationTime().is_null());
+ EXPECT_FALSE(GetCreationTime(instance_id).is_null());
}
} // 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 0ebcdf8..b77cf3f 100644
--- a/components/gcm_driver/instance_id/instance_id_impl.cc
+++ b/components/gcm_driver/instance_id/instance_id_impl.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/message_loop/message_loop.h"
+#include "base/strings/string_number_conversions.h"
#include "components/gcm_driver/gcm_driver_desktop.h"
#include "crypto/random.h"
@@ -23,19 +24,50 @@ InstanceID* InstanceID::Create(const std::string& app_id,
InstanceIDImpl::InstanceIDImpl(const std::string& app_id,
gcm::GCMDriver* gcm_driver)
: InstanceID(app_id),
- gcm_driver_(gcm_driver) {
+ gcm_driver_(gcm_driver),
+ load_from_store_(false),
+ weak_ptr_factory_(this) {
+ gcm_driver_->GetInstanceIDStore()->GetInstanceIDData(
+ app_id,
+ base::Bind(&InstanceIDImpl::GetInstanceIDDataCompleted,
+ weak_ptr_factory_.GetWeakPtr()));
}
InstanceIDImpl::~InstanceIDImpl() {
}
-std::string InstanceIDImpl::GetID() {
+void InstanceIDImpl::GetID(const GetIDCallback& callback) {
+ if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
+ delayed_task_controller_.AddTask(
+ base::Bind(&InstanceIDImpl::DoGetID,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
+ return;
+ }
+
+ DoGetID(callback);
+}
+
+void InstanceIDImpl::DoGetID(const GetIDCallback& callback) {
EnsureIDGenerated();
- return id_;
+ callback.Run(id_);
+}
+
+void InstanceIDImpl::GetCreationTime(const GetCreationTimeCallback& callback) {
+ if (!delayed_task_controller_.CanRunTaskWithoutDelay()) {
+ delayed_task_controller_.AddTask(
+ base::Bind(&InstanceIDImpl::DoGetCreationTime,
+ weak_ptr_factory_.GetWeakPtr(),
+ callback));
+ return;
+ }
+
+ DoGetCreationTime(callback);
}
-base::Time InstanceIDImpl::GetCreationTime() {
- return creation_time_;
+void InstanceIDImpl::DoGetCreationTime(
+ const GetCreationTimeCallback& callback) {
+ callback.Run(creation_time_);
}
void InstanceIDImpl::GetToken(
@@ -53,7 +85,8 @@ void InstanceIDImpl::DeleteToken(const std::string& authorized_entity,
}
void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) {
- // TODO(jianli): Delete the ID from the store.
+ gcm_driver_->GetInstanceIDStore()->RemoveInstanceIDData(app_id());
+
id_.clear();
creation_time_ = base::Time();
@@ -62,6 +95,12 @@ void InstanceIDImpl::DeleteID(const DeleteIDCallback& callback) {
base::Bind(callback, InstanceID::SUCCESS));
}
+void InstanceIDImpl::GetInstanceIDDataCompleted(
+ const std::string& instance_id_data) {
+ Deserialize(instance_id_data);
+ delayed_task_controller_.SetReady();
+}
+
void InstanceIDImpl::EnsureIDGenerated() {
if (!id_.empty())
return;
@@ -91,7 +130,36 @@ void InstanceIDImpl::EnsureIDGenerated() {
creation_time_ = base::Time::Now();
- // TODO(jianli): Save the ID to the store.
+ // 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);
}
} // 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 dd7b775..a5124c1 100644
--- a/components/gcm_driver/instance_id/instance_id_impl.h
+++ b/components/gcm_driver/instance_id/instance_id_impl.h
@@ -11,7 +11,9 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
+#include "components/gcm_driver/gcm_delayed_task_controller.h"
#include "components/gcm_driver/instance_id/instance_id.h"
namespace gcm {
@@ -27,8 +29,8 @@ class InstanceIDImpl : public InstanceID {
~InstanceIDImpl() override;
// InstanceID:
- std::string GetID() override;
- base::Time GetCreationTime() override;
+ void GetID(const GetIDCallback& callback) override;
+ void GetCreationTime(const GetCreationTimeCallback& callback) override;
void GetToken(const std::string& authorized_entity,
const std::string& scope,
const std::map<std::string, std::string>& options,
@@ -39,9 +41,22 @@ class InstanceIDImpl : public InstanceID {
void DeleteID(const DeleteIDCallback& callback) override;
private:
+ void EnsureIDGenerated();
+ void GetInstanceIDDataCompleted(const std::string& instance_id_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);
+
gcm::GCMDriver* gcm_driver_; // Not owned.
- void EnsureIDGenerated();
+ gcm::GCMDelayedTaskController delayed_task_controller_;
+
+ // Flag to indicate that we have tries to load the data from the store.
+ bool load_from_store_;
// The generated Instance ID.
std::string id_;
@@ -49,6 +64,8 @@ class InstanceIDImpl : public InstanceID {
// The time when the Instance ID has been generated.
base::Time creation_time_;
+ base::WeakPtrFactory<InstanceIDImpl> weak_ptr_factory_;
+
DISALLOW_COPY_AND_ASSIGN(InstanceIDImpl);
};