summaryrefslogtreecommitdiffstats
path: root/google_apis
diff options
context:
space:
mode:
authorfgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-17 04:52:12 +0000
committerfgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-17 04:52:12 +0000
commit7f154a57cb75adefa6741f1b157967b5eb127d7c (patch)
tree5d70a9132364974465fbf5c35bca7436f72ece2a /google_apis
parent68f404105a46cf9f09b6b5cd30170e883e71be91 (diff)
downloadchromium_src-7f154a57cb75adefa6741f1b157967b5eb127d7c.zip
chromium_src-7f154a57cb75adefa6741f1b157967b5eb127d7c.tar.gz
chromium_src-7f154a57cb75adefa6741f1b157967b5eb127d7c.tar.bz2
Adding GServicesSettings class and tests
BUG=359254 Review URL: https://codereview.chromium.org/226923002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@264419 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'google_apis')
-rw-r--r--google_apis/gcm/engine/gservices_settings.cc150
-rw-r--r--google_apis/gcm/engine/gservices_settings.h89
-rw-r--r--google_apis/gcm/engine/gservices_settings_unittest.cc234
-rw-r--r--google_apis/gcm/gcm.gyp3
4 files changed, 476 insertions, 0 deletions
diff --git a/google_apis/gcm/engine/gservices_settings.cc b/google_apis/gcm/engine/gservices_settings.cc
new file mode 100644
index 0000000..fc38e9d
--- /dev/null
+++ b/google_apis/gcm/engine/gservices_settings.cc
@@ -0,0 +1,150 @@
+// 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/gservices_settings.h"
+
+#include "base/bind.h"
+#include "base/strings/string_number_conversions.h"
+
+namespace {
+// The expected time in seconds between periodic checkins.
+const char kCheckinIntervalKey[] = "checkin_interval";
+// The override URL to the checkin server.
+const char kCheckinURLKey[] = "checkin_url";
+// The MCS machine name to connect to.
+const char kMCSHostnameKey[] = "gcm_hostname";
+// The MCS port to connect to.
+const char kMCSSecurePortKey[] = "gcm_secure_port";
+// The URL to get MCS registration IDs.
+const char kRegistrationURLKey[] = "gcm_registration_url";
+
+const int64 kDefaultCheckinInterval = 2 * 24 * 60 * 60; // seconds = 2 days.
+const char kDefaultCheckinURL[] = "https://android.clients.google.com/checkin";
+const char kDefaultMCSHostname[] = "https://mtalk.google.com";
+const int kDefaultMCSSecurePort = 5228;
+const char kDefaultRegistrationURL[] =
+ "https://android.clients.google.com/c2dm/register3";
+
+} // namespace
+
+namespace gcm {
+
+GServicesSettings::GServicesSettings(GCMStore* gcm_store)
+ : gcm_store_(gcm_store),
+ checkin_interval_(kDefaultCheckinInterval),
+ checkin_url_(kDefaultCheckinURL),
+ mcs_hostname_(kDefaultMCSHostname),
+ mcs_secure_port_(kDefaultMCSSecurePort),
+ registration_url_(kDefaultRegistrationURL),
+ weak_ptr_factory_(this) {
+}
+
+GServicesSettings::~GServicesSettings() {}
+
+void GServicesSettings::UpdateFromCheckinResponse(
+ const checkin_proto::AndroidCheckinResponse& checkin_response) {
+ if (!checkin_response.has_digest() ||
+ checkin_response.digest() == digest_) {
+ // There are no changes as digest is the same or no settings provided.
+ return;
+ }
+
+ std::map<std::string, std::string> settings;
+ for (int i = 0; i < checkin_response.setting_size(); ++i) {
+ std::string name = checkin_response.setting(i).name();
+ std::string value = checkin_response.setting(i).value();
+ settings[name] = value;
+ }
+
+ // Only update the settings in store and digest, if the settings actually
+ // passed the verificaiton in update settings.
+ if (UpdateSettings(settings)) {
+ digest_ = checkin_response.digest();
+ gcm_store_->SetGServicesSettings(
+ settings,
+ digest_,
+ base::Bind(&GServicesSettings::SetGServicesSettingsCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+}
+
+void GServicesSettings::UpdateFromLoadResult(
+ const GCMStore::LoadResult& load_result) {
+ if (UpdateSettings(load_result.gservices_settings))
+ digest_ = load_result.gservices_digest;
+}
+
+bool GServicesSettings::UpdateSettings(
+ const std::map<std::string, std::string>& settings) {
+ int64 new_checkin_interval = 0LL;
+ std::map<std::string, std::string>::const_iterator iter =
+ settings.find(kCheckinIntervalKey);
+ if (iter != settings.end()) {
+ if (!base::StringToInt64(iter->second, &new_checkin_interval)) {
+ LOG(ERROR) << "Failed to parse checkin interval: " << iter->second;
+ return false;
+ }
+ if (new_checkin_interval <= 0LL) {
+ LOG(ERROR) << "Checkin interval not positive: " << new_checkin_interval;
+ return false;
+ }
+ }
+
+ std::string new_mcs_hostname;
+ int new_mcs_secure_port = -1;
+ iter = settings.find(kMCSHostnameKey);
+ if (iter != settings.end()) {
+ new_mcs_hostname = iter->second;
+ if (new_mcs_hostname.empty()) {
+ LOG(ERROR) << "Empty MCS hostname provided.";
+ return false;
+ }
+
+ iter = settings.find(kMCSSecurePortKey);
+ if (iter != settings.end()) {
+ if (!base::StringToInt(iter->second, &new_mcs_secure_port)) {
+ LOG(ERROR) << "Failed to parse MCS secure port: " << iter->second;
+ return false;
+ }
+ if (new_mcs_secure_port < 0 || 65535 < new_mcs_secure_port) {
+ LOG(ERROR) << "Incorrect port value: " << new_mcs_secure_port;
+ return false;
+ }
+ }
+ }
+
+ std::string new_checkin_url;
+ iter = settings.find(kCheckinURLKey);
+ if (iter != settings.end()) {
+ new_checkin_url = iter->second;
+ if (new_checkin_url.empty()) {
+ LOG(ERROR) << "Empty checkin URL provided.";
+ return false;
+ }
+ }
+
+ std::string new_registration_url;
+ iter = settings.find(kRegistrationURLKey);
+ if (iter != settings.end()) {
+ new_registration_url = iter->second;
+ if (new_registration_url.empty()) {
+ LOG(ERROR) << "Empty registration URL provided.";
+ return false;
+ }
+ }
+
+ // We only update the settings once all of them are correct.
+ checkin_interval_ = new_checkin_interval;
+ mcs_hostname_ = new_mcs_hostname;
+ mcs_secure_port_ = new_mcs_secure_port;
+ checkin_url_ = new_checkin_url;
+ registration_url_ = new_registration_url;
+ return true;
+}
+
+void GServicesSettings::SetGServicesSettingsCallback(bool success) {
+ DCHECK(success);
+}
+
+} // namespace gcm
diff --git a/google_apis/gcm/engine/gservices_settings.h b/google_apis/gcm/engine/gservices_settings.h
new file mode 100644
index 0000000..db3c6b0
--- /dev/null
+++ b/google_apis/gcm/engine/gservices_settings.h
@@ -0,0 +1,89 @@
+// 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_GSERVICES_SETTINGS_H_
+#define GOOGLE_APIS_GCM_ENGINE_GSERVICES_SETTINGS_H_
+
+#include <map>
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "google_apis/gcm/base/gcm_export.h"
+#include "google_apis/gcm/engine/gcm_store.h"
+#include "google_apis/gcm/protocol/checkin.pb.h"
+
+namespace gcm {
+
+// Class responsible for handling G-services settings. It takes care of
+// extracting them from checkin response and storing in GCMStore.
+class GCM_EXPORT GServicesSettings {
+ public:
+ // Create an instance of GServicesSettings class. |gcm_store| is used to store
+ // the settings after they are extracted from checkin response.
+ explicit GServicesSettings(GCMStore* gcm_store);
+ ~GServicesSettings();
+
+ // Udpates the settings based on |checkin_response|.
+ void UpdateFromCheckinResponse(
+ const checkin_proto::AndroidCheckinResponse& checkin_response);
+
+ // Updates the settings based on |load_result|.
+ void UpdateFromLoadResult(const GCMStore::LoadResult& load_result);
+
+ const std::string& digest() const { return digest_; }
+
+ // TODO(fgorski): Consider returning TimeDelta.
+ int64 checkin_interval() const { return checkin_interval_; }
+
+ // TODO(fgorski): Consider returning GURL and use it for validation.
+ const std::string& checkin_url() const { return checkin_url_; }
+
+ // TODO(fgorski): Consider returning GURL and use it for validation.
+ const std::string& mcs_hostname() const { return mcs_hostname_; }
+
+ int mcs_secure_port() const { return mcs_secure_port_; }
+
+ // TODO(fgorski): Consider returning GURL and use it for validation.
+ const std::string& registration_url() const { return registration_url_; }
+
+ private:
+ // Parses the |settings| to fill in specific fields.
+ // TODO(fgorski): Change to a status variable that can be logged to UMA.
+ bool UpdateSettings(const std::map<std::string, std::string>& settings);
+
+ // Callback passed to GCMStore::SetGServicesSettings.
+ void SetGServicesSettingsCallback(bool success);
+
+ // GCM store to persist the settings. Not owned.
+ GCMStore* gcm_store_;
+
+ // Digest (hash) of the settings, used to check whether settings need update.
+ // It is meant to be sent with checkin request, instead of sending the whole
+ // settings table.
+ std::string digest_;
+
+ // Time in seconds between periodic checkins.
+ int64 checkin_interval_;
+
+ // URL that should be used for checkins.
+ std::string checkin_url_;
+
+ // Hostname of the MCS server.
+ std::string mcs_hostname_;
+
+ // Secure port to connect to on MCS sever.
+ int mcs_secure_port_;
+
+ // URL that should be used for regisrations and unregistrations.
+ std::string registration_url_;
+
+ // Factory for creating references in callbacks.
+ base::WeakPtrFactory<GServicesSettings> weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(GServicesSettings);
+};
+
+} // namespace gcm
+
+#endif // GOOGLE_APIS_GCM_ENGINE_GSERVICES_SETTINGS_H_
diff --git a/google_apis/gcm/engine/gservices_settings_unittest.cc b/google_apis/gcm/engine/gservices_settings_unittest.cc
new file mode 100644
index 0000000..ada4194
--- /dev/null
+++ b/google_apis/gcm/engine/gservices_settings_unittest.cc
@@ -0,0 +1,234 @@
+// 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 "base/strings/string_number_conversions.h"
+#include "google_apis/gcm/engine/gservices_settings.h"
+#include "google_apis/gcm/engine/registration_info.h"
+#include "google_apis/gcm/gcm_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace gcm {
+
+namespace {
+
+const int64 kAlternativeCheckinInterval = 2000LL;
+const char kAlternativeCheckinURL[] = "http://alternative.url/checkin";
+const char kAlternativeMCSHostname[] = "http://alternative.gcm.host";
+const int kAlternativeMCSSecurePort = 443;
+const char kAlternativeRegistrationURL[] =
+ "http://alternative.url/registration";
+
+const int64 kDefaultCheckinInterval = 2 * 24 * 60 * 60; // seconds = 2 days.
+const char kDefaultCheckinURL[] = "https://android.clients.google.com/checkin";
+const char kDefaultMCSHostname[] = "https://mtalk.google.com";
+const int kDefaultMCSSecurePort = 5228;
+const char kDefaultRegistrationURL[] =
+ "https://android.clients.google.com/c2dm/register3";
+
+class FakeGCMStore : public GCMStore {
+ public:
+ FakeGCMStore();
+ virtual ~FakeGCMStore();
+
+ virtual void Load(const gcm::GCMStore::LoadCallback& callback) OVERRIDE {}
+ virtual void Close() OVERRIDE {}
+ virtual void Destroy(const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {
+ }
+ virtual void SetDeviceCredentials(
+ uint64 device_android_id,
+ uint64 device_security_token,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void AddRegistration(
+ const std::string& app_id,
+ const linked_ptr<gcm::RegistrationInfo>& registration,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void RemoveRegistration(
+ const std::string& app_id,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void AddIncomingMessage(
+ const std::string& persistent_id,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void RemoveIncomingMessage(
+ const std::string& persistent_id,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void RemoveIncomingMessages(
+ const PersistentIdList& persistent_ids,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual bool AddOutgoingMessage(
+ const std::string& persistent_id,
+ const gcm::MCSMessage& message,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {
+ return true;
+ }
+ virtual void OverwriteOutgoingMessage(
+ const std::string& persistent_id,
+ const gcm::MCSMessage& message,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void RemoveOutgoingMessage(
+ const std::string& persistent_id,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void RemoveOutgoingMessages(
+ const PersistentIdList& persistent_ids,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+ virtual void SetLastCheckinTime(
+ const base::Time& last_checkin_time,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {}
+
+ // G-service settings handling.
+ virtual void SetGServicesSettings(
+ const std::map<std::string, std::string>& settings,
+ const std::string& settings_digest,
+ const gcm::GCMStore::UpdateCallback& callback) OVERRIDE {
+ settings_saved_ = true;
+ }
+
+ void Reset() {
+ settings_saved_ = false;
+ }
+
+ bool settings_saved() const { return settings_saved_; }
+
+ private:
+ bool settings_saved_;
+};
+
+FakeGCMStore::FakeGCMStore() : settings_saved_(false) {}
+
+FakeGCMStore::~FakeGCMStore() {}
+
+} // namespace
+
+class GServicesSettingsTest : public testing::Test {
+ public:
+ GServicesSettingsTest();
+ virtual ~GServicesSettingsTest();
+
+ virtual void SetUp() OVERRIDE;
+
+ void CheckAllSetToDefault();
+ void CheckAllSetToAlternative();
+ void SetWithAlternativeSettings(
+ checkin_proto::AndroidCheckinResponse& checkin_response);
+
+ GServicesSettings& settings() {
+ return gserivces_settings_;
+ }
+
+ const std::map<std::string, std::string>& alternative_settings() {
+ return alternative_settings_;
+ }
+
+ FakeGCMStore& gcm_store() { return gcm_store_; }
+
+ private:
+ FakeGCMStore gcm_store_;
+ GServicesSettings gserivces_settings_;
+ std::map<std::string, std::string> alternative_settings_;
+};
+
+GServicesSettingsTest::GServicesSettingsTest()
+ : gserivces_settings_(&gcm_store_) {
+}
+
+GServicesSettingsTest::~GServicesSettingsTest() {}
+
+void GServicesSettingsTest::SetUp() {
+ alternative_settings_["checkin_interval"] =
+ base::Int64ToString(kAlternativeCheckinInterval);
+ alternative_settings_["checkin_url"] = kAlternativeCheckinURL;
+ alternative_settings_["gcm_hostname"] = kAlternativeMCSHostname;
+ alternative_settings_["gcm_secure_port"] =
+ base::IntToString(kAlternativeMCSSecurePort);
+ alternative_settings_["gcm_registration_url"] = kAlternativeRegistrationURL;
+}
+
+void GServicesSettingsTest::CheckAllSetToDefault() {
+ EXPECT_EQ(kDefaultCheckinInterval, settings().checkin_interval());
+ EXPECT_EQ(kDefaultCheckinURL, settings().checkin_url());
+ EXPECT_EQ(kDefaultMCSHostname, settings().mcs_hostname());
+ EXPECT_EQ(kDefaultMCSSecurePort, settings().mcs_secure_port());
+ EXPECT_EQ(kDefaultRegistrationURL, settings().registration_url());
+}
+
+void GServicesSettingsTest::CheckAllSetToAlternative() {
+ EXPECT_EQ(kAlternativeCheckinInterval, settings().checkin_interval());
+ EXPECT_EQ(kAlternativeCheckinURL, settings().checkin_url());
+ EXPECT_EQ(kAlternativeMCSHostname, settings().mcs_hostname());
+ EXPECT_EQ(kAlternativeMCSSecurePort, settings().mcs_secure_port());
+ EXPECT_EQ(kAlternativeRegistrationURL, settings().registration_url());
+}
+
+void GServicesSettingsTest::SetWithAlternativeSettings(
+ checkin_proto::AndroidCheckinResponse& checkin_response) {
+ for (std::map<std::string, std::string>::const_iterator iter =
+ alternative_settings_.begin();
+ iter != alternative_settings_.end(); ++iter) {
+ checkin_proto::GservicesSetting* setting = checkin_response.add_setting();
+ setting->set_name(iter->first);
+ setting->set_value(iter->second);
+ }
+}
+
+// Verifies default values of the G-services settings and settings digest.
+TEST_F(GServicesSettingsTest, DefaultSettingsAndDigest) {
+ CheckAllSetToDefault();
+ EXPECT_EQ(std::string(), settings().digest());
+}
+
+// Verifies that the settings are set correctly based on the load result.
+TEST_F(GServicesSettingsTest, UpdateFromLoadResult) {
+ GCMStore::LoadResult result;
+ result.gservices_settings = alternative_settings();
+ result.gservices_digest = "digest_value";
+ settings().UpdateFromLoadResult(result);
+
+ CheckAllSetToAlternative();
+ EXPECT_EQ("digest_value", settings().digest());
+}
+
+// Verifies that the settings are set correctly after parsing a checkin
+// response.
+TEST_F(GServicesSettingsTest, UpdateFromCheckinResponse) {
+ checkin_proto::AndroidCheckinResponse checkin_response;
+
+ checkin_response.set_digest("digest_value");
+ SetWithAlternativeSettings(checkin_response);
+
+ settings().UpdateFromCheckinResponse(checkin_response);
+ EXPECT_TRUE(gcm_store().settings_saved());
+
+ CheckAllSetToAlternative();
+ EXPECT_EQ("digest_value", settings().digest());
+}
+
+// Verifies that no update is done, when a checkin response misses digest.
+TEST_F(GServicesSettingsTest, UpdateFromCheckinResponseNoDigest) {
+ checkin_proto::AndroidCheckinResponse checkin_response;
+
+ SetWithAlternativeSettings(checkin_response);
+ settings().UpdateFromCheckinResponse(checkin_response);
+ EXPECT_FALSE(gcm_store().settings_saved());
+
+ CheckAllSetToDefault();
+ EXPECT_EQ(std::string(), settings().digest());
+}
+
+// Verifies that no update is done, when a checkin response digest is the same.
+TEST_F(GServicesSettingsTest, UpdateFromCheckinResponseSameDigest) {
+ GCMStore::LoadResult load_result;
+ load_result.gservices_digest = "old_digest";
+ load_result.gservices_settings = alternative_settings();
+ settings().UpdateFromLoadResult(load_result);
+
+ checkin_proto::AndroidCheckinResponse checkin_response;
+ checkin_response.set_digest("old_digest");
+ SetWithAlternativeSettings(checkin_response);
+ settings().UpdateFromCheckinResponse(checkin_response);
+ EXPECT_FALSE(gcm_store().settings_saved());
+
+ CheckAllSetToAlternative();
+ EXPECT_EQ("old_digest", settings().digest());
+}
+
+} // namespace gcm
diff --git a/google_apis/gcm/gcm.gyp b/google_apis/gcm/gcm.gyp
index 9843776..c065818 100644
--- a/google_apis/gcm/gcm.gyp
+++ b/google_apis/gcm/gcm.gyp
@@ -58,6 +58,8 @@
'engine/gcm_store.h',
'engine/gcm_store_impl.cc',
'engine/gcm_store_impl.h',
+ 'engine/gservices_settings.cc',
+ 'engine/gservices_settings.h',
'engine/heartbeat_manager.cc',
'engine/heartbeat_manager.h',
'engine/mcs_client.cc',
@@ -134,6 +136,7 @@
'engine/fake_connection_handler.cc',
'engine/fake_connection_handler.h',
'engine/gcm_store_impl_unittest.cc',
+ 'engine/gservices_settings_unittest.cc',
'engine/heartbeat_manager_unittest.cc',
'engine/mcs_client_unittest.cc',
'engine/registration_request_unittest.cc',