cloud_print_proxy_backend.cc revision f2477e01787aa58f445919b809d89e252beef54f
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" 130f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "base/metrics/histogram.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/common/cloud_print/cloud_print_constants.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_auth.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_connector.h" 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_service_helpers.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/cloud_print_token_store.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/cloud_print/connector_settings.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 "grit/generated_resources.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/base/notifier_options.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/listener/push_client.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "jingle/notifier/listener/push_client_observer.h" 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.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) void DoInitializeWithToken(const std::string& cloud_print_token); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoInitializeWithRobotToken(const std::string& robot_oauth_refresh_token, 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoInitializeWithRobotAuthCode(const std::string& robot_oauth_auth_code, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the CloudPrintProxyBackend core_thread_ to perform 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown. 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoShutdown(); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoRegisterSelectedPrinters( 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const printing::PrinterList& printer_list); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoUnregisterPrinters(); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CloudPrintAuth::Client implementation. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAuthenticationComplete( 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email) OVERRIDE; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnInvalidCredentials() OVERRIDE; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CloudPrintConnector::Client implementation. 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAuthFailed() OVERRIDE; 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) virtual void OnXmppPingUpdated(int ping_timeout) OVERRIDE; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifier::PushClientObserver implementation. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnNotificationsEnabled() OVERRIDE; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnNotificationsDisabled( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::NotificationsDisabledReason reason) OVERRIDE; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnIncomingNotification( 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const notifier::Notification& notification) OVERRIDE; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnPingResponse() OVERRIDE; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<Core>; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Core() {} 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateAuthAndConnector(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DestroyAuthAndConnector(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NotifyXXX is how the Core communicates with the frontend across 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads. 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyPrinterListAvailable( 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const printing::PrinterList& printer_list); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyAuthenticated( 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyAuthenticationFailed(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyPrintSystemUnavailable(); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyUnregisterPrinters(const std::string& auth_token, 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::list<std::string>& printer_ids); 10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void NotifyXmppPingUpdated(int ping_timeout); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Init XMPP channel 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void InitNotifications(const std::string& robot_email, 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void HandlePrinterNotification(const std::string& notification); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PollForJobs(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedules a task to poll for jobs. Does nothing if a task is already 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheduled. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleJobPoll(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PingXmppServer(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleXmppPing(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckXmppPingStatus(); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintTokenStore* GetTokenStore(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our parent CloudPrintProxyBackend 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintProxyBackend* backend_; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cloud Print authenticator. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CloudPrintAuth> auth_; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cloud Print connector. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CloudPrintConnector> connector_; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OAuth client info. 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gaia::OAuthClientInfo oauth_client_info_; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notification (xmpp) handler. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<notifier::PushClient> push_client_; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether XMPP notifications are currently enabled. 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool notifications_enabled_; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The time when notifications were enabled. Valid only when 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifications_enabled_ is true. 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks notifications_enabled_since_; 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether a task to poll for jobs has been scheduled. 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool job_poll_scheduled_; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether we should poll for jobs when we lose XMPP connection. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll_; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether a task to ping xmpp server has been scheduled. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool xmpp_ping_scheduled_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of XMPP pings pending reply from the server. 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pending_xmpp_pings_; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connector settings. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConnectorSettings settings_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string robot_email_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CloudPrintTokenStore> token_store_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Core); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintProxyBackend::CloudPrintProxyBackend( 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintProxyFrontend* frontend, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ConnectorSettings& settings, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gaia::OAuthClientInfo& oauth_client_info, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll) 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) : core_thread_("Chrome_CloudPrintProxyCoreThread"), 165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) frontend_loop_(base::MessageLoop::current()), 166a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) frontend_(frontend) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(frontend_); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_ = new Core(this, settings, oauth_client_info, enable_job_poll); 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CloudPrintProxyBackend::~CloudPrintProxyBackend() { DCHECK(!core_.get()); } 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithToken( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& cloud_print_token) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_thread_.Start()) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithToken, 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get(), cloud_print_token)); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithRobotToken( 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_thread_.Start()) 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotToken, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get(), robot_oauth_refresh_token, robot_email)); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithRobotAuthCode( 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_auth_code, 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_thread_.Start()) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get(), robot_oauth_auth_code, robot_email)); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Shutdown() { 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoShutdown, core_.get())); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.Stop(); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_ = NULL; // Releases reference to core_. 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::UnregisterPrinters() { 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoUnregisterPrinters, 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get())); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintProxyBackend::Core::Core( 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintProxyBackend* backend, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ConnectorSettings& settings, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gaia::OAuthClientInfo& oauth_client_info, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : backend_(backend), 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_client_info_(oauth_client_info), 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_(false), 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_poll_scheduled_(false), 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_job_poll_(enable_job_poll), 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmpp_ping_scheduled_(false), 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_(0) { 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_.CopyFrom(settings); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::CreateAuthAndConnector() { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!auth_.get()) { 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_ = new CloudPrintAuth(this, settings_.server_url(), oauth_client_info_, 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_.proxy_id()); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connector_.get()) { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_ = new CloudPrintConnector(this, settings_); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DestroyAuthAndConnector() { 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_ = NULL; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_ = NULL; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithToken( 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& cloud_print_token) { 256a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAuthAndConnector(); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AuthenticateWithToken(cloud_print_token); 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithRobotToken( 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 264a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAuthAndConnector(); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AuthenticateWithRobotToken(robot_oauth_refresh_token, robot_email); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode( 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_auth_code, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 272a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAuthAndConnector(); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AuthenticateWithRobotAuthCode(robot_oauth_auth_code, robot_email); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnAuthenticationComplete( 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email) { 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintTokenStore* token_store = GetTokenStore(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool first_time = token_store->token().empty(); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_store->SetToken(access_token); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) robot_email_ = robot_email; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let the frontend know that we have authenticated. 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Core::NotifyAuthenticated, this, robot_oauth_refresh_token, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) robot_email, user_email)); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first_time) { 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitNotifications(robot_email, access_token); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are refreshing a token, update the XMPP token too. 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(push_client_.get()); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->UpdateCredentials(robot_email, access_token); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start cloud print connector if needed. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connector_->IsRunning()) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connector_->Start()) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let the frontend know that we do not have a print system. 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&Core::NotifyPrintSystemUnavailable, this)); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnInvalidCredentials() { 309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Auth Error"; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&Core::NotifyAuthenticationFailed, this)); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnAuthFailed() { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Authentication failed in connector."; 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let's stop connecter and refresh token. We'll restart connecter once 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new token available. 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connector_->IsRunning()) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->Stop(); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Refresh Auth token. 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->RefreshAccessToken(); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnXmppPingUpdated(int ping_timeout) { 32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) settings_.SetXmppPingTimeoutSec(ping_timeout); 32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) backend_->frontend_loop_->PostTask( 32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&Core::NotifyXmppPingUpdated, this, ping_timeout)); 33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 33268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::InitNotifications( 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token) { 336a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::NotifierOptions notifier_options; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier_options.request_context_getter = 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_service_process->GetServiceURLRequestContextGetter(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier_options.auth_mechanism = "X-OAUTH2"; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier_options.try_ssltcp_first = true; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_ = notifier::PushClient::CreateDefault(notifier_options); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->AddObserver(this); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::Subscription subscription; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subscription.channel = kCloudPrintPushNotificationsSource; 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subscription.from = kCloudPrintPushNotificationsSource; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->UpdateSubscriptions( 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::SubscriptionList(1, subscription)); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->UpdateCredentials(robot_email, access_token); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoShutdown() { 355a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Shutdown connector, id: " << settings_.proxy_id(); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connector_->IsRunning()) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->Stop(); 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Important to delete the PushClient on this thread. 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (push_client_.get()) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->RemoveObserver(this); 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_.reset(); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_ = false; 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_since_ = base::TimeTicks(); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_store_.reset(); 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DestroyAuthAndConnector(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoUnregisterPrinters() { 374a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string access_token = GetTokenStore()->token(); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::list<std::string> printer_ids; 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->GetPrinterIds(&printer_ids); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Core::NotifyUnregisterPrinters, 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, access_token, printer_ids)); 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::HandlePrinterNotification( 38868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& notification) { 389a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 39168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t pos = notification.rfind(kNotificationUpdateSettings); 39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (pos == std::string::npos) { 39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Handle printer notification, id: " 39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) << notification; 39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) connector_->CheckForJobs(kJobFetchReasonNotified, notification); 39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(pos == notification.length() - strlen(kNotificationUpdateSettings)); 39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string printer_id = notification.substr(0, pos); 39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Update printer settings, id: " << printer_id; 40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) connector_->UpdatePrinterSettings(printer_id); 40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::PollForJobs() { 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Polling for jobs."; 406a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check all printers for jobs. 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->CheckForJobs(kJobFetchReasonPoll, std::string()); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_poll_scheduled_ = false; 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have notifications and job polling is enabled, poll again 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after a while. 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!notifications_enabled_ && enable_job_poll_) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleJobPoll(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::ScheduleJobPoll() { 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!job_poll_scheduled_) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta interval = base::TimeDelta::FromSeconds( 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RandInt(kMinJobPollIntervalSecs, kMaxJobPollIntervalSecs)); 421a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::PollForJobs, this), 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interval); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_poll_scheduled_ = true; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::PingXmppServer() { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmpp_ping_scheduled_ = false; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!push_client_.get()) 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->SendPing(); 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_++; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_xmpp_pings_ >= kMaxFailedXmppPings) { 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check ping status when we close to the limit. 440a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::CheckXmppPingStatus, this), 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kXmppPingCheckIntervalSecs)); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule next ping if needed. 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (notifications_enabled_) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleXmppPing(); 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::ScheduleXmppPing() { 45268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // settings_.xmpp_ping_enabled() is obsolete, we are now control 45368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // XMPP pings from Cloud Print server. 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!xmpp_ping_scheduled_) { 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta interval = base::TimeDelta::FromSeconds( 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RandInt(settings_.xmpp_ping_timeout_sec() * 0.9, 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_.xmpp_ping_timeout_sec() * 1.1)); 458a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::PingXmppServer, this), 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interval); 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmpp_ping_scheduled_ = true; 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::CheckXmppPingStatus() { 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_xmpp_pings_ >= kMaxFailedXmppPings) { 4680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("CloudPrint.XmppPingTry", 99); // Max on fail. 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reconnect to XMPP. 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_.reset(); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitNotifications(robot_email_, GetTokenStore()->token()); 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintTokenStore* CloudPrintProxyBackend::Core::GetTokenStore() { 477a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!token_store_.get()) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_store_.reset(new CloudPrintTokenStore); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return token_store_.get(); 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyAuthenticated( 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email) { 487a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 488a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) backend_->frontend_ 489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ->OnAuthenticated(robot_oauth_refresh_token, robot_email, user_email); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyAuthenticationFailed() { 493a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_->OnAuthenticationFailed(); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyPrintSystemUnavailable() { 498a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_->OnPrintSystemUnavailable(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyUnregisterPrinters( 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token, 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::list<std::string>& printer_ids) { 505a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_->OnUnregisterPrinters(auth_token, printer_ids); 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyXmppPingUpdated(int ping_timeout) { 51068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) backend_->frontend_->OnXmppPingUpdated(ping_timeout); 51268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnNotificationsEnabled() { 515a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_ = true; 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_since_ = base::TimeTicks::Now(); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Notifications for connector " << settings_.proxy_id() 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " were enabled at " 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << notifications_enabled_since_.ToInternalValue(); 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notifications just got re-enabled. In this case we want to schedule 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a poll once for jobs we might have missed when we were dark. 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that ScheduleJobPoll will not schedule again if a job poll task is 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already scheduled. 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleJobPoll(); 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule periodic ping for XMPP notification channel. 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleXmppPing(); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnNotificationsDisabled( 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::NotificationsDisabledReason reason) { 533a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_ = false; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Notifications for connector " << settings_.proxy_id() 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " disabled."; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_since_ = base::TimeTicks(); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We just lost notifications. This this case we want to schedule a 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // job poll if enable_job_poll_ is true. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enable_job_poll_) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleJobPoll(); 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnIncomingNotification( 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const notifier::Notification& notification) { 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we got some notification from the server, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset pending ping counter to 0. 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 551a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Incoming notification."; 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == base::strcasecmp(kCloudPrintPushNotificationsSource, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notification.channel.c_str())) 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePrinterNotification(notification.data); 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnPingResponse() { 5590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("CloudPrint.XmppPingTry", pending_xmpp_pings_); 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Ping response received."; 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cloud_print 565