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" 156e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "base/strings/string_util.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.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" 23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "chrome/service/net/service_url_request_context_getter.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/service/service_process.h" 250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/cloud_devices/common/cloud_devices_switches.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_oauth_client.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/gaia_urls.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" 317dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cloud_print { 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The real guts of CloudPrintProxyBackend, to keep the public client API clean. 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CloudPrintProxyBackend::Core 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>, 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public CloudPrintAuth::Client, 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public CloudPrintConnector::Client, 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public notifier::PushClientObserver { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It is OK for print_server_url to be empty. In this case system should 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use system default (local) print server. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Core(CloudPrintProxyBackend* backend, 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ConnectorSettings& settings, 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gaia::OAuthClientInfo& oauth_client_info, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The Do* methods are the various entry points from CloudPrintProxyBackend 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // It calls us on a dedicated thread to actually perform synchronous 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (and potentially blocking) operations. 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoInitializeWithToken(const std::string& cloud_print_token); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoInitializeWithRobotToken(const std::string& robot_oauth_refresh_token, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoInitializeWithRobotAuthCode(const std::string& robot_oauth_auth_code, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called on the CloudPrintProxyBackend core_thread_ to perform 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shutdown. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoShutdown(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoRegisterSelectedPrinters( 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const printing::PrinterList& printer_list); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DoUnregisterPrinters(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CloudPrintAuth::Client implementation. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAuthenticationComplete( 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token, 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email) OVERRIDE; 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnInvalidCredentials() OVERRIDE; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CloudPrintConnector::Client implementation. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnAuthFailed() OVERRIDE; 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) virtual void OnXmppPingUpdated(int ping_timeout) OVERRIDE; 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifier::PushClientObserver implementation. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnNotificationsEnabled() OVERRIDE; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnNotificationsDisabled( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::NotificationsDisabledReason reason) OVERRIDE; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnIncomingNotification( 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const notifier::Notification& notification) OVERRIDE; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnPingResponse() OVERRIDE; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class base::RefCountedThreadSafe<Core>; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Core() {} 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CreateAuthAndConnector(); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DestroyAuthAndConnector(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NotifyXXX is how the Core communicates with the frontend across 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // threads. 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyPrinterListAvailable( 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const printing::PrinterList& printer_list); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyAuthenticated( 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyAuthenticationFailed(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyPrintSystemUnavailable(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void NotifyUnregisterPrinters(const std::string& auth_token, 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::list<std::string>& printer_ids); 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void NotifyXmppPingUpdated(int ping_timeout); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Init XMPP channel 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void InitNotifications(const std::string& robot_email, 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) void HandlePrinterNotification(const std::string& notification); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PollForJobs(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedules a task to poll for jobs. Does nothing if a task is already 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // scheduled. 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleJobPoll(); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void PingXmppServer(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void ScheduleXmppPing(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckXmppPingStatus(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintTokenStore* GetTokenStore(); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our parent CloudPrintProxyBackend 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintProxyBackend* backend_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cloud Print authenticator. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CloudPrintAuth> auth_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cloud Print connector. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_refptr<CloudPrintConnector> connector_; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OAuth client info. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gaia::OAuthClientInfo oauth_client_info_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notification (xmpp) handler. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<notifier::PushClient> push_client_; 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether XMPP notifications are currently enabled. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool notifications_enabled_; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The time when notifications were enabled. Valid only when 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // notifications_enabled_ is true. 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeTicks notifications_enabled_since_; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether a task to poll for jobs has been scheduled. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool job_poll_scheduled_; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether we should poll for jobs when we lose XMPP connection. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll_; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Indicates whether a task to ping xmpp server has been scheduled. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool xmpp_ping_scheduled_; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Number of XMPP pings pending reply from the server. 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int pending_xmpp_pings_; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Connector settings. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConnectorSettings settings_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string robot_email_; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<CloudPrintTokenStore> token_store_; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(Core); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintProxyBackend::CloudPrintProxyBackend( 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintProxyFrontend* frontend, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ConnectorSettings& settings, 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gaia::OAuthClientInfo& oauth_client_info, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll) 163a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) : core_thread_("Chrome_CloudPrintProxyCoreThread"), 164a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) frontend_loop_(base::MessageLoop::current()), 165a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) frontend_(frontend) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(frontend_); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_ = new Core(this, settings, oauth_client_info, enable_job_poll); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)CloudPrintProxyBackend::~CloudPrintProxyBackend() { DCHECK(!core_.get()); } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithToken( 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& cloud_print_token) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_thread_.Start()) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithToken, 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get(), cloud_print_token)); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithRobotToken( 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_thread_.Start()) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotToken, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get(), robot_oauth_refresh_token, robot_email)); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CloudPrintProxyBackend::InitializeWithRobotAuthCode( 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_auth_code, 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!core_thread_.Start()) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode, 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get(), robot_oauth_auth_code, robot_email)); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Shutdown() { 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoShutdown, core_.get())); 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.Stop(); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_ = NULL; // Releases reference to core_. 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::UnregisterPrinters() { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_thread_.message_loop()->PostTask( 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::DoUnregisterPrinters, 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) core_.get())); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintProxyBackend::Core::Core( 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintProxyBackend* backend, 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ConnectorSettings& settings, 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gaia::OAuthClientInfo& oauth_client_info, 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool enable_job_poll) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : backend_(backend), 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) oauth_client_info_(oauth_client_info), 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_(false), 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_poll_scheduled_(false), 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enable_job_poll_(enable_job_poll), 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmpp_ping_scheduled_(false), 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_(0) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_.CopyFrom(settings); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::CreateAuthAndConnector() { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!auth_.get()) { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_ = new CloudPrintAuth(this, settings_.server_url(), oauth_client_info_, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_.proxy_id()); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connector_.get()) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_ = new CloudPrintConnector(this, settings_); 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DestroyAuthAndConnector() { 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_ = NULL; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_ = NULL; 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithToken( 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& cloud_print_token) { 255a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAuthAndConnector(); 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AuthenticateWithToken(cloud_print_token); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithRobotToken( 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 263a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAuthAndConnector(); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AuthenticateWithRobotToken(robot_oauth_refresh_token, robot_email); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoInitializeWithRobotAuthCode( 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_auth_code, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email) { 271a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateAuthAndConnector(); 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->AuthenticateWithRobotAuthCode(robot_oauth_auth_code, robot_email); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnAuthenticationComplete( 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token, 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloudPrintTokenStore* token_store = GetTokenStore(); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool first_time = token_store->token().empty(); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_store->SetToken(access_token); 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) robot_email_ = robot_email; 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let the frontend know that we have authenticated. 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Core::NotifyAuthenticated, this, robot_oauth_refresh_token, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) robot_email, user_email)); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (first_time) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitNotifications(robot_email, access_token); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are refreshing a token, update the XMPP token too. 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(push_client_.get()); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->UpdateCredentials(robot_email, access_token); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start cloud print connector if needed. 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connector_->IsRunning()) { 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!connector_->Start()) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let the frontend know that we do not have a print system. 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&Core::NotifyPrintSystemUnavailable, this)); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnInvalidCredentials() { 308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Auth Error"; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, base::Bind(&Core::NotifyAuthenticationFailed, this)); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnAuthFailed() { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Authentication failed in connector."; 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let's stop connecter and refresh token. We'll restart connecter once 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new token available. 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connector_->IsRunning()) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->Stop(); 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Refresh Auth token. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) auth_->RefreshAccessToken(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 32568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnXmppPingUpdated(int ping_timeout) { 32668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) settings_.SetXmppPingTimeoutSec(ping_timeout); 32768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) backend_->frontend_loop_->PostTask( 32868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) FROM_HERE, 32968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) base::Bind(&Core::NotifyXmppPingUpdated, this, ping_timeout)); 33068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 33168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::InitNotifications( 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& access_token) { 335a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::NotifierOptions notifier_options; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier_options.request_context_getter = 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_service_process->GetServiceURLRequestContextGetter(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier_options.auth_mechanism = "X-OAUTH2"; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier_options.try_ssltcp_first = true; 3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch notifier_options.xmpp_host_port = net::HostPortPair::FromString( 3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch switches::kCloudPrintXmppEndpoint)); 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_ = notifier::PushClient::CreateDefault(notifier_options); 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->AddObserver(this); 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::Subscription subscription; 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subscription.channel = kCloudPrintPushNotificationsSource; 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subscription.from = kCloudPrintPushNotificationsSource; 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->UpdateSubscriptions( 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::SubscriptionList(1, subscription)); 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->UpdateCredentials(robot_email, access_token); 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoShutdown() { 357a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Shutdown connector, id: " << settings_.proxy_id(); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (connector_->IsRunning()) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->Stop(); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Important to delete the PushClient on this thread. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (push_client_.get()) { 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->RemoveObserver(this); 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_.reset(); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_ = false; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_since_ = base::TimeTicks(); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_store_.reset(); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DestroyAuthAndConnector(); 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::DoUnregisterPrinters() { 376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string access_token = GetTokenStore()->token(); 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::list<std::string> printer_ids; 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->GetPrinterIds(&printer_ids); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_loop_->PostTask( 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&Core::NotifyUnregisterPrinters, 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, access_token, printer_ids)); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::HandlePrinterNotification( 39068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const std::string& notification) { 391a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 39268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 39368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t pos = notification.rfind(kNotificationUpdateSettings); 39468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) if (pos == std::string::npos) { 39568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Handle printer notification, id: " 39668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) << notification; 39768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) connector_->CheckForJobs(kJobFetchReasonNotified, notification); 39868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } else { 39968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(pos == notification.length() - strlen(kNotificationUpdateSettings)); 40068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) std::string printer_id = notification.substr(0, pos); 40168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Update printer settings, id: " << printer_id; 40268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) connector_->UpdatePrinterSettings(printer_id); 40368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::PollForJobs() { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Polling for jobs."; 408a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check all printers for jobs. 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) connector_->CheckForJobs(kJobFetchReasonPoll, std::string()); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_poll_scheduled_ = false; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we don't have notifications and job polling is enabled, poll again 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // after a while. 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!notifications_enabled_ && enable_job_poll_) 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleJobPoll(); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::ScheduleJobPoll() { 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!job_poll_scheduled_) { 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta interval = base::TimeDelta::FromSeconds( 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RandInt(kMinJobPollIntervalSecs, kMaxJobPollIntervalSecs)); 423a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::PollForJobs, this), 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interval); 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) job_poll_scheduled_ = true; 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::PingXmppServer() { 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmpp_ping_scheduled_ = false; 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!push_client_.get()) 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_->SendPing(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_++; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_xmpp_pings_ >= kMaxFailedXmppPings) { 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check ping status when we close to the limit. 442a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::CheckXmppPingStatus, this), 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromSeconds(kXmppPingCheckIntervalSecs)); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule next ping if needed. 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (notifications_enabled_) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleXmppPing(); 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::ScheduleXmppPing() { 45468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // settings_.xmpp_ping_enabled() is obsolete, we are now control 45568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // XMPP pings from Cloud Print server. 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!xmpp_ping_scheduled_) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta interval = base::TimeDelta::FromSeconds( 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::RandInt(settings_.xmpp_ping_timeout_sec() * 0.9, 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) settings_.xmpp_ping_timeout_sec() * 1.1)); 460a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&CloudPrintProxyBackend::Core::PingXmppServer, this), 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interval); 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) xmpp_ping_scheduled_ = true; 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::CheckXmppPingStatus() { 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pending_xmpp_pings_ >= kMaxFailedXmppPings) { 4700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("CloudPrint.XmppPingTry", 99); // Max on fail. 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Reconnect to XMPP. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) push_client_.reset(); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InitNotifications(robot_email_, GetTokenStore()->token()); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CloudPrintTokenStore* CloudPrintProxyBackend::Core::GetTokenStore() { 479a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!token_store_.get()) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) token_store_.reset(new CloudPrintTokenStore); 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return token_store_.get(); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyAuthenticated( 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_oauth_refresh_token, 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& robot_email, 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& user_email) { 489a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 490a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) backend_->frontend_ 491a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) ->OnAuthenticated(robot_oauth_refresh_token, robot_email, user_email); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyAuthenticationFailed() { 495a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_->OnAuthenticationFailed(); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyPrintSystemUnavailable() { 500a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_->OnPrintSystemUnavailable(); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyUnregisterPrinters( 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& auth_token, 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::list<std::string>& printer_ids) { 507a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) backend_->frontend_->OnUnregisterPrinters(auth_token, printer_ids); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 51168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CloudPrintProxyBackend::Core::NotifyXmppPingUpdated(int ping_timeout) { 51268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->frontend_loop_); 51368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) backend_->frontend_->OnXmppPingUpdated(ping_timeout); 51468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)} 51568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnNotificationsEnabled() { 517a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_ = true; 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_since_ = base::TimeTicks::Now(); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "Notifications for connector " << settings_.proxy_id() 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " were enabled at " 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << notifications_enabled_since_.ToInternalValue(); 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Notifications just got re-enabled. In this case we want to schedule 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a poll once for jobs we might have missed when we were dark. 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note that ScheduleJobPoll will not schedule again if a job poll task is 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already scheduled. 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleJobPoll(); 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schedule periodic ping for XMPP notification channel. 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleXmppPing(); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnNotificationsDisabled( 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifier::NotificationsDisabledReason reason) { 535a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_ = false; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Notifications for connector " << settings_.proxy_id() 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " disabled."; 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notifications_enabled_since_ = base::TimeTicks(); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We just lost notifications. This this case we want to schedule a 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // job poll if enable_job_poll_ is true. 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (enable_job_poll_) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScheduleJobPoll(); 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnIncomingNotification( 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const notifier::Notification& notification) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Since we got some notification from the server, 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reset pending ping counter to 0. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 553a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) DCHECK(base::MessageLoop::current() == backend_->core_thread_.message_loop()); 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Incoming notification."; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (0 == base::strcasecmp(kCloudPrintPushNotificationsSource, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) notification.channel.c_str())) 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HandlePrinterNotification(notification.data); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CloudPrintProxyBackend::Core::OnPingResponse() { 5610f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) UMA_HISTOGRAM_COUNTS_100("CloudPrint.XmppPingTry", pending_xmpp_pings_); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pending_xmpp_pings_ = 0; 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VLOG(1) << "CP_CONNECTOR: Ping response received."; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cloud_print 567