cloud_print_proxy_backend.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_proxy_backend.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_constants.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_auth.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_connector.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_helpers.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_token_store.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/connector_settings.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/gaia/service_gaia_authenticator.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/net/service_url_request_context.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/service_process.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "googleurl/src/gurl.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/base/notifier_options.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/listener/push_client.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/listener/push_client_observer.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cloud_print {
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The real guts of CloudPrintProxyBackend, to keep the public client API clean.
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CloudPrintProxyBackend::Core
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public CloudPrintAuth::Client,
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public CloudPrintConnector::Client,
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      public notifier::PushClientObserver {
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It is OK for print_server_url to be empty. In this case system should
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // use system default (local) print server.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Core(CloudPrintProxyBackend* backend,
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const ConnectorSettings& settings,
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       const gaia::OAuthClientInfo& oauth_client_info,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       bool enable_job_poll);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note:
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The Do* methods are the various entry points from CloudPrintProxyBackend
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It calls us on a dedicated thread to actually perform synchronous
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (and potentially blocking) operations.
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the CloudPrintProxyBackend core_thread_ to perform
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initialization. When we are passed in an LSID we authenticate using that
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and retrieve new auth tokens.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoInitializeWithLsid(const std::string& lsid,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& last_robot_refresh_token,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& last_robot_email,
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const std::string& last_user_email);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoInitializeWithToken(const std::string& cloud_print_token);
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoInitializeWithRobotToken(const std::string& robot_oauth_refresh_token,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& robot_email);
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoInitializeWithRobotAuthCode(const std::string& robot_oauth_auth_code,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     const std::string& robot_email);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Called on the CloudPrintProxyBackend core_thread_ to perform
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // shutdown.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoShutdown();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoRegisterSelectedPrinters(
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const printing::PrinterList& printer_list);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DoUnregisterPrinters();
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CloudPrintAuth::Client implementation.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAuthenticationComplete(
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& access_token,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& robot_oauth_refresh_token,
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& robot_email,
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string& user_email) OVERRIDE;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnInvalidCredentials() OVERRIDE;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // CloudPrintConnector::Client implementation.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnAuthFailed() OVERRIDE;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifier::PushClientObserver implementation.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnNotificationsEnabled() OVERRIDE;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnNotificationsDisabled(
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notifier::NotificationsDisabledReason reason) OVERRIDE;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnIncomingNotification(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const notifier::Notification& notification) OVERRIDE;
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnPingResponse() OVERRIDE;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  friend class base::RefCountedThreadSafe<Core>;
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~Core() {}
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CreateAuthAndConnector();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void DestroyAuthAndConnector();
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NotifyXXX is how the Core communicates with the frontend across
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // threads.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyPrinterListAvailable(
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const printing::PrinterList& printer_list);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyAuthenticated(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_refresh_token,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email,
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_email);
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyAuthenticationFailed();
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyPrintSystemUnavailable();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void NotifyUnregisterPrinters(const std::string& auth_token,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                const std::list<std::string>& printer_ids);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Init XMPP channel
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void InitNotifications(const std::string& robot_email,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         const std::string& access_token);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandlePrinterNotification(const std::string& printer_id);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PollForJobs();
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedules a task to poll for jobs. Does nothing if a task is already
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // scheduled.
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScheduleJobPoll();
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PingXmppServer();
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void ScheduleXmppPing();
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void CheckXmppPingStatus();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintTokenStore* GetTokenStore();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Our parent CloudPrintProxyBackend
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintProxyBackend* backend_;
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cloud Print authenticator.
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<CloudPrintAuth> auth_;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Cloud Print connector.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<CloudPrintConnector> connector_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // OAuth client info.
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gaia::OAuthClientInfo oauth_client_info_;
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notification (xmpp) handler.
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<notifier::PushClient> push_client_;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates whether XMPP notifications are currently enabled.
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool notifications_enabled_;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The time when notifications were enabled. Valid only when
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // notifications_enabled_ is true.
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::TimeTicks notifications_enabled_since_;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates whether a task to poll for jobs has been scheduled.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool job_poll_scheduled_;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates whether we should poll for jobs when we lose XMPP connection.
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enable_job_poll_;
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Indicates whether a task to ping xmpp server has been scheduled.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool xmpp_ping_scheduled_;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Number of XMPP pings pending reply from the server.
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int pending_xmpp_pings_;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Connector settings.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConnectorSettings settings_;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string robot_email_;
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<CloudPrintTokenStore> token_store_;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(Core);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintProxyBackend::CloudPrintProxyBackend(
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloudPrintProxyFrontend* frontend,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ConnectorSettings& settings,
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gaia::OAuthClientInfo& oauth_client_info,
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool enable_job_poll)
171a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    : core_thread_("Chrome_CloudPrintProxyCoreThread"),
172a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      frontend_loop_(base::MessageLoop::current()),
173a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      frontend_(frontend) {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(frontend_);
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_ = new Core(this, settings, oauth_client_info, enable_job_poll);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CloudPrintProxyBackend::~CloudPrintProxyBackend() { DCHECK(!core_.get()); }
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithLsid(
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& lsid,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& last_robot_refresh_token,
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& last_robot_email,
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& last_user_email) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_thread_.Start())
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.message_loop()->PostTask(
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithLsid,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 core_.get(), lsid, last_robot_refresh_token, last_robot_email,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 last_user_email));
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithToken(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& cloud_print_token) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_thread_.Start())
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.message_loop()->PostTask(
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithToken,
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 core_.get(), cloud_print_token));
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithRobotToken(
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_refresh_token,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_thread_.Start())
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.message_loop()->PostTask(
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotToken,
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 core_.get(), robot_oauth_refresh_token, robot_email));
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithRobotAuthCode(
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_auth_code,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email) {
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!core_thread_.Start())
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.message_loop()->PostTask(
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode,
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 core_.get(), robot_oauth_auth_code, robot_email));
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Shutdown() {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.message_loop()->PostTask(
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintProxyBackend::Core::DoShutdown, core_.get()));
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.Stop();
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_ = NULL;  // Releases reference to core_.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::UnregisterPrinters() {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  core_thread_.message_loop()->PostTask(
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&CloudPrintProxyBackend::Core::DoUnregisterPrinters,
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 core_.get()));
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintProxyBackend::Core::Core(
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CloudPrintProxyBackend* backend,
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ConnectorSettings& settings,
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const gaia::OAuthClientInfo& oauth_client_info,
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool enable_job_poll)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : backend_(backend),
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        oauth_client_info_(oauth_client_info),
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        notifications_enabled_(false),
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        job_poll_scheduled_(false),
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        enable_job_poll_(enable_job_poll),
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xmpp_ping_scheduled_(false),
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pending_xmpp_pings_(0) {
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  settings_.CopyFrom(settings);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::CreateAuthAndConnector() {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!auth_.get()) {
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    auth_ = new CloudPrintAuth(this, settings_.server_url(), oauth_client_info_,
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               settings_.proxy_id());
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!connector_.get()) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connector_ = new CloudPrintConnector(this, settings_);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DestroyAuthAndConnector() {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_ = NULL;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connector_ = NULL;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithLsid(
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& lsid,
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& last_robot_refresh_token,
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& last_robot_email,
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& last_user_email) {
281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAuthAndConnector();
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note: The GAIA login is synchronous but that should be OK because we are in
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the CloudPrintProxyCoreThread and we cannot really do anything else until
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the GAIA signin is successful.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_->AuthenticateWithLsid(lsid, last_robot_refresh_token,
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              last_robot_email, last_user_email);
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithToken(
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& cloud_print_token) {
292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAuthAndConnector();
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_->AuthenticateWithToken(cloud_print_token);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithRobotToken(
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_refresh_token,
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email) {
300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAuthAndConnector();
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_->AuthenticateWithRobotToken(robot_oauth_refresh_token, robot_email);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode(
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_auth_code,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email) {
308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CreateAuthAndConnector();
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_->AuthenticateWithRobotAuthCode(robot_oauth_auth_code, robot_email);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnAuthenticationComplete(
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& access_token,
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_refresh_token,
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email,
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_email) {
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CloudPrintTokenStore* token_store  = GetTokenStore();
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool first_time = token_store->token().empty();
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  token_store->SetToken(access_token);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  robot_email_ = robot_email;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let the frontend know that we have authenticated.
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->frontend_loop_->PostTask(
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::NotifyAuthenticated, this, robot_oauth_refresh_token,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 robot_email, user_email));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (first_time) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitNotifications(robot_email, access_token);
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we are refreshing a token, update the XMPP token too.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(push_client_.get());
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    push_client_->UpdateCredentials(robot_email, access_token);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Start cloud print connector if needed.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!connector_->IsRunning()) {
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!connector_->Start()) {
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Let the frontend know that we do not have a print system.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      backend_->frontend_loop_->PostTask(
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE, base::Bind(&Core::NotifyPrintSystemUnavailable, this));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnInvalidCredentials() {
345a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Auth Error";
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->frontend_loop_->PostTask(
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE, base::Bind(&Core::NotifyAuthenticationFailed, this));
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnAuthFailed() {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Authentication failed in connector.";
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Let's stop connecter and refresh token. We'll restart connecter once
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // new token available.
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connector_->IsRunning())
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connector_->Stop();
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Refresh Auth token.
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  auth_->RefreshAccessToken();
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::InitNotifications(
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email,
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& access_token) {
365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_xmpp_pings_ = 0;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier::NotifierOptions notifier_options;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier_options.request_context_getter =
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_service_process->GetServiceURLRequestContextGetter();
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier_options.auth_mechanism = "X-OAUTH2";
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier_options.try_ssltcp_first = true;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_ = notifier::PushClient::CreateDefault(notifier_options);
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->AddObserver(this);
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifier::Subscription subscription;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subscription.channel = kCloudPrintPushNotificationsSource;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  subscription.from = kCloudPrintPushNotificationsSource;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->UpdateSubscriptions(
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      notifier::SubscriptionList(1, subscription));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->UpdateCredentials(robot_email, access_token);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoShutdown() {
384a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Shutdown connector, id: " << settings_.proxy_id();
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (connector_->IsRunning())
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    connector_->Stop();
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Important to delete the PushClient on this thread.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (push_client_.get()) {
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    push_client_->RemoveObserver(this);
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_.reset();
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_enabled_ = false;
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_enabled_since_ = base::TimeTicks();
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  token_store_.reset();
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DestroyAuthAndConnector();
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoUnregisterPrinters() {
403a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string access_token = GetTokenStore()->token();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<std::string> printer_ids;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connector_->GetPrinterIds(&printer_ids);
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->frontend_loop_->PostTask(
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&Core::NotifyUnregisterPrinters,
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 this, access_token, printer_ids));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::HandlePrinterNotification(
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& printer_id) {
418a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Handle printer notification, id: " << printer_id;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connector_->CheckForJobs(kJobFetchReasonNotified, printer_id);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::PollForJobs() {
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Polling for jobs.";
425a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check all printers for jobs.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  connector_->CheckForJobs(kJobFetchReasonPoll, std::string());
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  job_poll_scheduled_ = false;
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we don't have notifications and job polling is enabled, poll again
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // after a while.
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!notifications_enabled_ && enable_job_poll_)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleJobPoll();
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::ScheduleJobPoll() {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!job_poll_scheduled_) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta interval = base::TimeDelta::FromSeconds(
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::RandInt(kMinJobPollIntervalSecs, kMaxJobPollIntervalSecs));
440a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CloudPrintProxyBackend::Core::PollForJobs, this),
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        interval);
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    job_poll_scheduled_ = true;
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::PingXmppServer() {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  xmpp_ping_scheduled_ = false;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!push_client_.get())
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  push_client_->SendPing();
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_xmpp_pings_++;
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_xmpp_pings_ >= kMaxFailedXmppPings) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check ping status when we close to the limit.
459a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CloudPrintProxyBackend::Core::CheckXmppPingStatus, this),
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::TimeDelta::FromSeconds(kXmppPingCheckIntervalSecs));
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule next ping if needed.
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (notifications_enabled_)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleXmppPing();
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::ScheduleXmppPing() {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!settings_.xmpp_ping_enabled())
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!xmpp_ping_scheduled_) {
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::TimeDelta interval = base::TimeDelta::FromSeconds(
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::RandInt(settings_.xmpp_ping_timeout_sec() * 0.9,
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    settings_.xmpp_ping_timeout_sec() * 1.1));
478a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    base::MessageLoop::current()->PostDelayedTask(
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&CloudPrintProxyBackend::Core::PingXmppServer, this),
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        interval);
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    xmpp_ping_scheduled_ = true;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::CheckXmppPingStatus() {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_xmpp_pings_ >= kMaxFailedXmppPings) {
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reconnect to XMPP.
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_xmpp_pings_ = 0;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    push_client_.reset();
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    InitNotifications(robot_email_, GetTokenStore()->token());
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintTokenStore* CloudPrintProxyBackend::Core::GetTokenStore() {
496a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!token_store_.get())
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    token_store_.reset(new CloudPrintTokenStore);
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return token_store_.get();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyAuthenticated(
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_oauth_refresh_token,
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& robot_email,
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& user_email) {
506a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->frontend_loop_);
507a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  backend_->frontend_
508a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      ->OnAuthenticated(robot_oauth_refresh_token, robot_email, user_email);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyAuthenticationFailed() {
512a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->frontend_loop_);
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->frontend_->OnAuthenticationFailed();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyPrintSystemUnavailable() {
517a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->frontend_loop_);
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->frontend_->OnPrintSystemUnavailable();
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyUnregisterPrinters(
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& auth_token,
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::list<std::string>& printer_ids) {
524a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->frontend_loop_);
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  backend_->frontend_->OnUnregisterPrinters(auth_token, printer_ids);
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnNotificationsEnabled() {
529a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_enabled_ = true;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_enabled_since_ = base::TimeTicks::Now();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "Notifications for connector " << settings_.proxy_id()
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " were enabled at "
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << notifications_enabled_since_.ToInternalValue();
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Notifications just got re-enabled. In this case we want to schedule
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a poll once for jobs we might have missed when we were dark.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that ScheduleJobPoll will not schedule again if a job poll task is
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // already scheduled.
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleJobPoll();
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Schedule periodic ping for XMPP notification channel.
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ScheduleXmppPing();
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnNotificationsDisabled(
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notifier::NotificationsDisabledReason reason) {
547a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_enabled_ = false;
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG(ERROR) << "Notifications for connector " << settings_.proxy_id()
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << " disabled.";
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notifications_enabled_since_ = base::TimeTicks();
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We just lost notifications. This this case we want to schedule a
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // job poll if enable_job_poll_ is true.
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (enable_job_poll_)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ScheduleJobPoll();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnIncomingNotification(
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const notifier::Notification& notification) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Since we got some notification from the server,
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reset pending ping counter to 0.
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_xmpp_pings_ = 0;
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop());
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Incoming notification.";
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (0 == base::strcasecmp(kCloudPrintPushNotificationsSource,
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            notification.channel.c_str()))
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HandlePrinterNotification(notification.data);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnPingResponse() {
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_xmpp_pings_ = 0;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CP_CONNECTOR: Ping response received.";
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace cloud_print
578