diff options
author | gene@chromium.org <gene@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 19:59:41 +0000 |
---|---|---|
committer | gene@chromium.org <gene@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-10-26 19:59:41 +0000 |
commit | 05861d65af900b604d9e99e4eebb61deb45de1cd (patch) | |
tree | 172427792ac96feea1189b762287b0af74b7cea9 /chrome | |
parent | fc992beca7a034a8e6437faf73377d375ac2e44a (diff) | |
download | chromium_src-05861d65af900b604d9e99e4eebb61deb45de1cd.zip chromium_src-05861d65af900b604d9e99e4eebb61deb45de1cd.tar.gz chromium_src-05861d65af900b604d9e99e4eebb61deb45de1cd.tar.bz2 |
Adding XMPP ping functionality to CloudPrint. XMPP ping and timeout is controlled thorugh Service State file.
BUG=157735
Review URL: https://chromiumcodereview.appspot.com/11232048
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@164385 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/common/pref_names.cc | 4 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 2 | ||||
-rw-r--r-- | chrome/service/cloud_print/cloud_print_consts.h | 9 | ||||
-rw-r--r-- | chrome/service/cloud_print/cloud_print_proxy_backend.cc | 77 | ||||
-rw-r--r-- | chrome/service/cloud_print/connector_settings.cc | 21 | ||||
-rw-r--r-- | chrome/service/cloud_print/connector_settings.h | 20 | ||||
-rw-r--r-- | chrome/service/cloud_print/connector_settings_unittest.cc | 25 | ||||
-rw-r--r-- | chrome/service/service_process_prefs.cc | 15 | ||||
-rw-r--r-- | chrome/service/service_process_prefs.h | 6 |
9 files changed, 177 insertions, 2 deletions
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index eabe1ad..5cab24f 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1934,6 +1934,10 @@ const char kCloudPrintRobotRefreshToken[] = "cloud_print.robot_refresh_token"; const char kCloudPrintRobotEmail[] = "cloud_print.robot_email"; // A boolean indicating whether we should connect to cloud print new printers. const char kCloudPrintConnectNewPrinters[] = "cloud_print.connect_new_printers"; +// A boolean indicating whether we should ping XMPP connection. +const char kCloudPrintXmppPingEnabled[] = "cloud_print.xmpp_ping_enabled"; +// An int value indicating the average timeout between xmpp pings. +const char kCloudPrintXmppPingTimeout[] = "cloud_print.xmpp_ping_timeout_sec"; // List of printers which should not be connected. const char kCloudPrintPrinterBlacklist[] = "cloud_print.printer_blacklist"; // A boolean indicating whether submitting jobs to Google Cloud Print is diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 0b44d49..4813b30 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -640,6 +640,8 @@ extern const char kCloudPrintEnableJobPoll[]; extern const char kCloudPrintRobotRefreshToken[]; extern const char kCloudPrintRobotEmail[]; extern const char kCloudPrintConnectNewPrinters[]; +extern const char kCloudPrintXmppPingEnabled[]; +extern const char kCloudPrintXmppPingTimeout[]; extern const char kCloudPrintPrinterBlacklist[]; extern const char kCloudPrintSubmitEnabled[]; diff --git a/chrome/service/cloud_print/cloud_print_consts.h b/chrome/service/cloud_print/cloud_print_consts.h index 2d9254e..b5fb24c 100644 --- a/chrome/service/cloud_print/cloud_print_consts.h +++ b/chrome/service/cloud_print/cloud_print_consts.h @@ -64,6 +64,15 @@ const int kCloudPrintAuthMaxRetryCount = -1; const int kMinJobPollIntervalSecs = 5*60; // 5 minutes in seconds const int kMaxJobPollIntervalSecs = 8*60; // 8 minutes in seconds +// When we have XMPP notifications available, we ping server to keep connection +// alive or check connection status. +const int kDefaultXmppPingTimeoutSecs = 5*60; // 5 minutes in seconds +const int kMinimumXmppPingTimeoutSecs = 2*60; // 2 minutes in seconds +const int kXmppPingCheckIntervalSecs = 60; + +// Number of failed pings before we try to reinstablish XMPP connection. +const int kMaxFailedXmppPings = 2; + // The number of seconds before the OAuth2 access token is due to expire that // we try and refresh it. const int kTokenRefreshGracePeriodSecs = 5*60; // 5 minutes in seconds diff --git a/chrome/service/cloud_print/cloud_print_proxy_backend.cc b/chrome/service/cloud_print/cloud_print_proxy_backend.cc index 16d7211..44df7b6 100644 --- a/chrome/service/cloud_print/cloud_print_proxy_backend.cc +++ b/chrome/service/cloud_print/cloud_print_proxy_backend.cc @@ -8,10 +8,12 @@ #include <vector> #include "base/bind.h" +#include "base/command_line.h" #include "base/compiler_specific.h" #include "base/file_util.h" #include "base/rand_util.h" #include "base/values.h" +#include "chrome/common/chrome_switches.h" #include "chrome/service/cloud_print/cloud_print_auth.h" #include "chrome/service/cloud_print/cloud_print_connector.h" #include "chrome/service/cloud_print/cloud_print_consts.h" @@ -88,6 +90,7 @@ class CloudPrintProxyBackend::Core notifier::NotificationsDisabledReason reason) OVERRIDE; virtual void OnIncomingNotification( const notifier::Notification& notification) OVERRIDE; + virtual void OnPingResponse() OVERRIDE; private: friend class base::RefCountedThreadSafe<Core>; @@ -119,6 +122,10 @@ class CloudPrintProxyBackend::Core // Schedules a task to poll for jobs. Does nothing if a task is already // scheduled. void ScheduleJobPoll(); + void PingXmppServer(); + void ScheduleXmppPing(); + void CheckXmppPingStatus(); + CloudPrintTokenStore* GetTokenStore(); // Our parent CloudPrintProxyBackend @@ -143,8 +150,13 @@ class CloudPrintProxyBackend::Core bool job_poll_scheduled_; // Indicates whether we should poll for jobs when we lose XMPP connection. bool enable_job_poll_; + // Indicates whether a task to ping xmpp server has been scheduled. + bool xmpp_ping_scheduled_; + // Number of XMPP pings pending reply from the server. + int pending_xmpp_pings_; // Connector settings. ConnectorSettings settings_; + std::string robot_email_; scoped_ptr<CloudPrintTokenStore> token_store_; DISALLOW_COPY_AND_ASSIGN(Core); @@ -240,7 +252,9 @@ CloudPrintProxyBackend::Core::Core( oauth_client_info_(oauth_client_info), notifications_enabled_(false), job_poll_scheduled_(false), - enable_job_poll_(enable_job_poll) { + enable_job_poll_(enable_job_poll), + xmpp_ping_scheduled_(false), + pending_xmpp_pings_(0) { settings_.CopyFrom(settings); } @@ -305,6 +319,7 @@ void CloudPrintProxyBackend::Core::OnAuthenticationComplete( CloudPrintTokenStore* token_store = GetTokenStore(); bool first_time = token_store->token().empty(); token_store->SetToken(access_token); + robot_email_ = robot_email; // Let the frontend know that we have authenticated. backend_->frontend_loop_->PostTask( FROM_HERE, @@ -350,6 +365,7 @@ void CloudPrintProxyBackend::Core::InitNotifications( const std::string& access_token) { DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); + pending_xmpp_pings_ = 0; notifier::NotifierOptions notifier_options; notifier_options.request_context_getter = g_service_process->GetServiceURLRequestContextGetter(); @@ -430,6 +446,53 @@ void CloudPrintProxyBackend::Core::ScheduleJobPoll() { } } +void CloudPrintProxyBackend::Core::PingXmppServer() { + xmpp_ping_scheduled_ = false; + + if (!push_client_.get()) + return; + + push_client_->SendPing(); + + pending_xmpp_pings_++; + if (pending_xmpp_pings_ >= kMaxFailedXmppPings) { + // Check ping status when we close to the limit. + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&CloudPrintProxyBackend::Core::CheckXmppPingStatus, this), + base::TimeDelta::FromSeconds(kXmppPingCheckIntervalSecs)); + } + + // Schedule next ping if needed. + if (notifications_enabled_) + ScheduleXmppPing(); +} + +void CloudPrintProxyBackend::Core::ScheduleXmppPing() { + if (!settings_.xmpp_ping_enabled()) + return; + + if (!xmpp_ping_scheduled_) { + base::TimeDelta interval = base::TimeDelta::FromSeconds( + base::RandInt(settings_.xmpp_ping_timeout_sec() * 0.9, + settings_.xmpp_ping_timeout_sec() * 1.1)); + MessageLoop::current()->PostDelayedTask( + FROM_HERE, + base::Bind(&CloudPrintProxyBackend::Core::PingXmppServer, this), + interval); + xmpp_ping_scheduled_ = true; + } +} + +void CloudPrintProxyBackend::Core::CheckXmppPingStatus() { + if (pending_xmpp_pings_ >= kMaxFailedXmppPings) { + // Reconnect to XMPP. + pending_xmpp_pings_ = 0; + push_client_.reset(); + InitNotifications(robot_email_, GetTokenStore()->token()); + } +} + CloudPrintTokenStore* CloudPrintProxyBackend::Core::GetTokenStore() { DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); if (!token_store_.get()) @@ -476,6 +539,9 @@ void CloudPrintProxyBackend::Core::OnNotificationsEnabled() { // Note that ScheduleJobPoll will not schedule again if a job poll task is // already scheduled. ScheduleJobPoll(); + + // Schedule periodic ping for XMPP notification channel. + ScheduleXmppPing(); } void CloudPrintProxyBackend::Core::OnNotificationsDisabled( @@ -494,6 +560,10 @@ void CloudPrintProxyBackend::Core::OnNotificationsDisabled( void CloudPrintProxyBackend::Core::OnIncomingNotification( const notifier::Notification& notification) { + // Since we got some notification from the server, + // reset pending ping counter to 0. + pending_xmpp_pings_ = 0; + DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); VLOG(1) << "CP_CONNECTOR: Incoming notification."; if (0 == base::strcasecmp(kCloudPrintPushNotificationsSource, @@ -501,3 +571,8 @@ void CloudPrintProxyBackend::Core::OnIncomingNotification( HandlePrinterNotification(notification.data); } +void CloudPrintProxyBackend::Core::OnPingResponse() { + pending_xmpp_pings_ = 0; + VLOG(1) << "CP_CONNECTOR: Ping response received."; +} + diff --git a/chrome/service/cloud_print/connector_settings.cc b/chrome/service/cloud_print/connector_settings.cc index 0976c42..ccfc6e1 100644 --- a/chrome/service/cloud_print/connector_settings.cc +++ b/chrome/service/cloud_print/connector_settings.cc @@ -19,7 +19,9 @@ const char kDeleteOnEnumFail[] = "delete_on_enum_fail"; ConnectorSettings::ConnectorSettings() : delete_on_enum_fail_(false), - connect_new_printers_(true) { + connect_new_printers_(true), + xmpp_ping_enabled_(false), + xmpp_ping_timeout_sec_(kDefaultXmppPingTimeoutSecs) { } ConnectorSettings::~ConnectorSettings() { @@ -56,6 +58,13 @@ void ConnectorSettings::InitFrom(ServiceProcessPrefs* prefs) { connect_new_printers_ = prefs->GetBoolean( prefs::kCloudPrintConnectNewPrinters, true); + + xmpp_ping_enabled_ = prefs->GetBoolean( + prefs::kCloudPrintXmppPingEnabled, false); + int timeout = prefs->GetInt( + prefs::kCloudPrintXmppPingTimeout, kDefaultXmppPingTimeoutSecs); + SetXmppPingTimeoutSec(timeout); + const base::ListValue* printers = prefs->GetList( prefs::kCloudPrintPrinterBlacklist); if (printers) { @@ -76,8 +85,18 @@ void ConnectorSettings::CopyFrom(const ConnectorSettings& source) { proxy_id_ = source.proxy_id(); delete_on_enum_fail_ = source.delete_on_enum_fail(); connect_new_printers_ = source.connect_new_printers(); + xmpp_ping_enabled_ = source.xmpp_ping_enabled(); + xmpp_ping_timeout_sec_ = source.xmpp_ping_timeout_sec(); printer_blacklist_ = source.printer_blacklist_; if (source.print_system_settings()) print_system_settings_.reset(source.print_system_settings()->DeepCopy()); } +void ConnectorSettings::SetXmppPingTimeoutSec(int timeout) { + xmpp_ping_timeout_sec_ = timeout; + if (xmpp_ping_timeout_sec_ < kMinimumXmppPingTimeoutSecs) { + LOG(WARNING) << + "CP_CONNECTOR: XMPP ping timeout is less then minimal value"; + xmpp_ping_timeout_sec_ = kMinimumXmppPingTimeoutSecs; + } +} diff --git a/chrome/service/cloud_print/connector_settings.h b/chrome/service/cloud_print/connector_settings.h index 9750727..4c9b086 100644 --- a/chrome/service/cloud_print/connector_settings.h +++ b/chrome/service/cloud_print/connector_settings.h @@ -42,12 +42,26 @@ class ConnectorSettings { return connect_new_printers_; }; + bool xmpp_ping_enabled() const { + return xmpp_ping_enabled_; + } + + void set_xmpp_ping_enabled(bool enabled) { + xmpp_ping_enabled_ = enabled; + } + + int xmpp_ping_timeout_sec() const { + return xmpp_ping_timeout_sec_; + } + const base::DictionaryValue* print_system_settings() const { return print_system_settings_.get(); }; bool IsPrinterBlacklisted(const std::string& name) const; + void SetXmppPingTimeoutSec(int timeout); + private: // Cloud Print server url. GURL server_url_; @@ -63,6 +77,12 @@ class ConnectorSettings { // If true register all new printers in cloud print. bool connect_new_printers_; + // Indicate if XMPP pings are enabled. + bool xmpp_ping_enabled_; + + // Indicate timeout between XMPP pings. + int xmpp_ping_timeout_sec_; + // List of printers which should not be connected. std::set<std::string> printer_blacklist_; diff --git a/chrome/service/cloud_print/connector_settings_unittest.cc b/chrome/service/cloud_print/connector_settings_unittest.cc index 6aaa6c4..09ceeef 100644 --- a/chrome/service/cloud_print/connector_settings_unittest.cc +++ b/chrome/service/cloud_print/connector_settings_unittest.cc @@ -11,6 +11,7 @@ #include "base/message_loop_proxy.h" #include "base/scoped_temp_dir.h" #include "base/values.h" +#include "chrome/service/cloud_print/cloud_print_consts.h" #include "chrome/service/service_process_prefs.h" #include "testing/gmock/include/gmock/gmock.h" @@ -28,6 +29,8 @@ const char kServiceStateContent[] = " 'service_url': 'http://cp.google.com'," " 'xmpp_auth_token': 'xmp token'," " 'connect_new_printers': false," + " 'xmpp_ping_enabled': true," + " 'xmpp_ping_timeout_sec': 256," " 'printer_blacklist': [" " 'prn1'," " 'prn2'" @@ -83,6 +86,7 @@ TEST_F(ConnectorSettingsTest, InitFromEmpty) { EXPECT_FALSE(settings.delete_on_enum_fail()); EXPECT_EQ(NULL, settings.print_system_settings()); EXPECT_TRUE(settings.connect_new_printers()); + EXPECT_FALSE(settings.xmpp_ping_enabled()); EXPECT_FALSE(settings.IsPrinterBlacklisted("prn1")); } } @@ -97,6 +101,8 @@ TEST_F(ConnectorSettingsTest, InitFromFile) { EXPECT_TRUE(settings.delete_on_enum_fail()); EXPECT_TRUE(settings.print_system_settings()); EXPECT_FALSE(settings.connect_new_printers()); + EXPECT_TRUE(settings.xmpp_ping_enabled()); + EXPECT_EQ(settings.xmpp_ping_timeout_sec(), 256); EXPECT_FALSE(settings.IsPrinterBlacklisted("prn0")); EXPECT_TRUE(settings.IsPrinterBlacklisted("prn1")); } @@ -115,6 +121,25 @@ TEST_F(ConnectorSettingsTest, CopyFrom) { EXPECT_EQ(settings1.print_system_settings()->size(), settings2.print_system_settings()->size()); EXPECT_EQ(settings1.connect_new_printers(), settings2.connect_new_printers()); + EXPECT_EQ(settings1.xmpp_ping_enabled(), settings2.xmpp_ping_enabled()); + EXPECT_EQ(settings1.xmpp_ping_timeout_sec(), + settings2.xmpp_ping_timeout_sec()); EXPECT_TRUE(settings2.IsPrinterBlacklisted("prn1")); } +TEST_F(ConnectorSettingsTest, SettersTest) { + scoped_ptr<ServiceProcessPrefs> prefs(CreateTestFile("{}")); + ConnectorSettings settings; + settings.InitFrom(prefs.get()); + EXPECT_FALSE(settings.xmpp_ping_enabled()); + + // Set and check valid settings. + settings.set_xmpp_ping_enabled(true); + settings.SetXmppPingTimeoutSec(256); + EXPECT_TRUE(settings.xmpp_ping_enabled()); + EXPECT_EQ(settings.xmpp_ping_timeout_sec(), 256); + + // Set invalid settings, and check correct defaults. + settings.SetXmppPingTimeoutSec(1); + EXPECT_EQ(settings.xmpp_ping_timeout_sec(), kMinimumXmppPingTimeoutSecs); +} diff --git a/chrome/service/service_process_prefs.cc b/chrome/service/service_process_prefs.cc index 7de70a4..811647d 100644 --- a/chrome/service/service_process_prefs.cc +++ b/chrome/service/service_process_prefs.cc @@ -54,6 +54,21 @@ void ServiceProcessPrefs::SetBoolean(const std::string& key, bool value) { prefs_->SetValue(key, Value::CreateBooleanValue(value)); } +int ServiceProcessPrefs::GetInt(const std::string& key, + int default_value) const { + const Value* value; + int result = default_value; + if (prefs_->GetValue(key, &value) != PersistentPrefStore::READ_OK || + !value->GetAsInteger(&result)) { + return default_value; + } + return result; +} + +void ServiceProcessPrefs::SetInt(const std::string& key, int value) { + prefs_->SetValue(key, Value::CreateIntegerValue(value)); +} + const DictionaryValue* ServiceProcessPrefs::GetDictionary( const std::string& key) const { const Value* value; diff --git a/chrome/service/service_process_prefs.h b/chrome/service/service_process_prefs.h index 2bc3e5fe..018ce1d 100644 --- a/chrome/service/service_process_prefs.h +++ b/chrome/service/service_process_prefs.h @@ -43,6 +43,12 @@ class ServiceProcessPrefs { // Set a boolean |value| for |key|. void SetBoolean(const std::string& key, bool value); + // Returns an int preference for |key|. + int GetInt(const std::string& key, int default_value) const; + + // Set an int |value| for |key|. + void SetInt(const std::string& key, int value); + // Returns a dictionary preference for |key|. const base::DictionaryValue* GetDictionary(const std::string& key) const; |