summaryrefslogtreecommitdiffstats
path: root/cloud_print/gcp20
diff options
context:
space:
mode:
authormaksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-07 06:01:27 +0000
committermaksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-08-07 06:01:27 +0000
commit98fae91a816298249923d30172e55f434687e1f9 (patch)
treea898ac7360d0f90fc938ad88b4ed388044724bc9 /cloud_print/gcp20
parent06fb2c0371b9cfb5980351d45665d41fdcfae3b5 (diff)
downloadchromium_src-98fae91a816298249923d30172e55f434687e1f9.zip
chromium_src-98fae91a816298249923d30172e55f434687e1f9.tar.gz
chromium_src-98fae91a816298249923d30172e55f434687e1f9.tar.bz2
GCP2.0 Device: XMPP pings.
BUG= Review URL: https://chromiumcodereview.appspot.com/21916003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@216107 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print/gcp20')
-rw-r--r--cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc90
-rw-r--r--cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h42
-rw-r--r--cloud_print/gcp20/prototype/printer.cc7
3 files changed, 125 insertions, 14 deletions
diff --git a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc
index bcf7dcc..6ad90230 100644
--- a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc
+++ b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.cc
@@ -4,7 +4,10 @@
#include "cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h"
+#include "base/bind.h"
#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "cloud_print/gcp20/prototype/cloud_print_url_request_context_getter.h"
#include "jingle/notifier/base/notifier_options.h"
@@ -12,6 +15,10 @@
namespace {
+const int kUrgentPingInterval = 60; // in seconds
+const int kPingTimeout = 30; // in seconds
+const double kRandomDelayPercentage = 0.2;
+
const char kCloudPrintPushNotificationsSource[] = "cloudprint.google.com";
// Splits message into two parts (e.g. '<device_id>/delete' will be splitted
@@ -32,21 +39,29 @@ void TokenizeXmppMessage(const std::string& message, std::string* device_id,
CloudPrintXmppListener::CloudPrintXmppListener(
const std::string& robot_email,
+ int standard_ping_interval,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
Delegate* delegate)
: robot_email_(robot_email),
+ standard_ping_interval_(standard_ping_interval),
+ ping_timeouts_posted_(0),
+ ping_responses_pending_(0),
+ ping_scheduled_(false),
context_getter_(new CloudPrintURLRequestContextGetter(task_runner)),
delegate_(delegate) {
}
CloudPrintXmppListener::~CloudPrintXmppListener() {
- push_client_->RemoveObserver(this);
- push_client_.reset();
+ if (push_client_) {
+ push_client_->RemoveObserver(this);
+ push_client_.reset();
+ }
}
void CloudPrintXmppListener::Connect(const std::string& access_token) {
- push_client_.reset();
access_token_ = access_token;
+ ping_responses_pending_ = 0;
+ ping_scheduled_ = 0;
notifier::NotifierOptions options;
options.request_context_getter = context_getter_;
@@ -66,8 +81,13 @@ void CloudPrintXmppListener::Connect(const std::string& access_token) {
push_client_->UpdateCredentials(robot_email_, access_token_);
}
+void CloudPrintXmppListener::set_standard_ping_interval(int interval) {
+ standard_ping_interval_ = interval;
+}
+
void CloudPrintXmppListener::OnNotificationsEnabled() {
delegate_->OnXmppConnected();
+ SchedulePing();
}
void CloudPrintXmppListener::OnNotificationsDisabled(
@@ -77,7 +97,7 @@ void CloudPrintXmppListener::OnNotificationsDisabled(
delegate_->OnXmppAuthError();
break;
case notifier::TRANSIENT_NOTIFICATION_ERROR:
- delegate_->OnXmppNetworkError();
+ Disconnect();
break;
default:
NOTREACHED() << "XMPP failed with unexpected reason code: " << reason;
@@ -102,7 +122,65 @@ void CloudPrintXmppListener::OnIncomingNotification(
}
void CloudPrintXmppListener::OnPingResponse() {
- // TODO(maksymb): Implement pings
- NOTIMPLEMENTED();
+ ping_responses_pending_ = 0;
+ SchedulePing();
+}
+
+void CloudPrintXmppListener::Disconnect() {
+ push_client_.reset();
+ delegate_->OnXmppNetworkError();
+}
+
+void CloudPrintXmppListener::SchedulePing() {
+ if (ping_scheduled_)
+ return;
+
+ DCHECK_LE(kPingTimeout, kUrgentPingInterval);
+ int delay = (ping_responses_pending_ > 0)
+ ? kUrgentPingInterval - kPingTimeout
+ : standard_ping_interval_;
+
+ delay += base::RandInt(0, delay*kRandomDelayPercentage);
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CloudPrintXmppListener::SendPing, AsWeakPtr()),
+ base::TimeDelta::FromSeconds(delay));
+
+ ping_scheduled_ = true;
+}
+
+void CloudPrintXmppListener::SendPing() {
+ ping_scheduled_ = false;
+
+ DCHECK(push_client_);
+ push_client_->SendPing();
+ ++ping_responses_pending_;
+
+ base::MessageLoop::current()->PostDelayedTask(
+ FROM_HERE,
+ base::Bind(&CloudPrintXmppListener::OnPingTimeoutReached, AsWeakPtr()),
+ base::TimeDelta::FromSeconds(kPingTimeout));
+ ++ping_timeouts_posted_;
+}
+
+void CloudPrintXmppListener::OnPingTimeoutReached() {
+ DCHECK_GT(ping_timeouts_posted_, 0);
+ --ping_timeouts_posted_;
+ if (ping_timeouts_posted_ > 0)
+ return; // Fake (old) timeout.
+
+ switch (ping_responses_pending_) {
+ case 0:
+ break;
+ case 1:
+ SchedulePing();
+ break;
+ case 2:
+ Disconnect();
+ break;
+ default:
+ NOTREACHED();
+ }
}
diff --git a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h
index 843ba89..7c612fe 100644
--- a/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h
+++ b/cloud_print/gcp20/prototype/cloud_print_xmpp_listener.h
@@ -11,6 +11,7 @@
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/weak_ptr.h"
#include "jingle/notifier/listener/push_client_observer.h"
namespace base {
@@ -31,7 +32,9 @@ class PushClient;
} // namespace notifier
-class CloudPrintXmppListener: public notifier::PushClientObserver {
+class CloudPrintXmppListener
+ : public base::SupportsWeakPtr<CloudPrintXmppListener>,
+ public notifier::PushClientObserver {
public:
class Delegate {
public:
@@ -52,12 +55,13 @@ class CloudPrintXmppListener: public notifier::PushClientObserver {
// Invoked when local settings was updated.
virtual void OnXmppNewLocalSettings(const std::string& device_id) = 0;
- // Invoked when printer was deleted from server.
+ // Invoked when printer was deleted from the server.
virtual void OnXmppDeleteNotification(const std::string& device_id) = 0;
};
CloudPrintXmppListener(
const std::string& robot_email,
+ int standard_ping_interval,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
Delegate* delegate);
@@ -66,6 +70,9 @@ class CloudPrintXmppListener: public notifier::PushClientObserver {
// Connects to the server.
void Connect(const std::string& access_token);
+ // Update ping interval when new local_settings was received.
+ void set_standard_ping_interval(int interval);
+
private:
// notifier::PushClientObserver methods:
virtual void OnNotificationsEnabled() OVERRIDE;
@@ -75,18 +82,41 @@ class CloudPrintXmppListener: public notifier::PushClientObserver {
const notifier::Notification& notification) OVERRIDE;
virtual void OnPingResponse() OVERRIDE;
- // Is used for reconnection when number of retries is now exhausted.
- void ReconnectInternal();
+ // Stops listening and sending pings.
+ void Disconnect();
+
+ // Schedules ping (unless it was already scheduled).
+ void SchedulePing();
+
+ // Sends ping.
+ void SendPing();
+
+ // Checks if ping was received.
+ void OnPingTimeoutReached();
// Credentials:
std::string robot_email_;
std::string access_token_;
- scoped_refptr<net::URLRequestContextGetter> context_getter_;
-
// Internal listener.
scoped_ptr<notifier::PushClient> push_client_;
+ // Interval between pings in regular workflow.
+ int standard_ping_interval_;
+
+ // Number of timeouts posted to MessageLoop. Is used for controlling "fake"
+ // timeout calls.
+ int ping_timeouts_posted_;
+
+ // Number of responses awaiting from XMPP server. Is used for controlling
+ // number of failed pings.
+ int ping_responses_pending_;
+
+ // Is used for preventing multiple pings at the moment.
+ bool ping_scheduled_;
+
+ scoped_refptr<net::URLRequestContextGetter> context_getter_;
+
Delegate* delegate_;
DISALLOW_COPY_AND_ASSIGN(CloudPrintXmppListener);
diff --git a/cloud_print/gcp20/prototype/printer.cc b/cloud_print/gcp20/prototype/printer.cc
index a161edd..4583aa7 100644
--- a/cloud_print/gcp20/prototype/printer.cc
+++ b/cloud_print/gcp20/prototype/printer.cc
@@ -27,7 +27,8 @@ const char kPrinterStatePathDefault[] = "printer_state.json";
namespace {
const uint16 kHttpPortDefault = 10101;
-const uint32 kTtlDefault = 60*60;
+const uint32 kTtlDefault = 60*60; // in seconds
+const int kXmppPingIntervalDefault = 5*60; // in seconds
const char kServiceType[] = "_privet._tcp.local";
const char kServiceNamePrefixDefault[] = "first_gcp20_device";
@@ -182,6 +183,7 @@ void Printer::Stop() {
}
void Printer::OnAuthError() {
+ LOG(ERROR) << "Auth error occurred";
access_token_update_ = base::Time::Now();
ChangeState(OFFLINE);
// TODO(maksymb): Implement *instant* updating of access_token.
@@ -476,7 +478,8 @@ void Printer::TryConnect() {
void Printer::ConnectXmpp() {
xmpp_listener_.reset(
- new CloudPrintXmppListener(reg_info_.xmpp_jid, GetTaskRunner(), this));
+ new CloudPrintXmppListener(reg_info_.xmpp_jid, kXmppPingIntervalDefault,
+ GetTaskRunner(), this));
xmpp_listener_->Connect(access_token_);
}