| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/service/cloud_print/cloud_print_proxy_backend.h" | 5 #include "chrome/service/cloud_print/cloud_print_proxy_backend.h" |
| 6 | 6 |
| 7 #include <map> | 7 #include <map> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/md5.h" | 11 #include "base/md5.h" |
| 12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
| 13 #include "base/string_split.h" | 13 #include "base/string_split.h" |
| 14 #include "base/string_util.h" | 14 #include "base/string_util.h" |
| 15 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
| 16 #include "base/values.h" | 16 #include "base/values.h" |
| 17 #include "chrome/common/net/http_return.h" | 17 #include "chrome/common/net/url_fetcher_protect.h" |
| 18 #include "chrome/service/cloud_print/cloud_print_consts.h" | 18 #include "chrome/service/cloud_print/cloud_print_consts.h" |
| 19 #include "chrome/service/cloud_print/cloud_print_helpers.h" | 19 #include "chrome/service/cloud_print/cloud_print_helpers.h" |
| 20 #include "chrome/service/cloud_print/cloud_print_url_fetcher.h" |
| 20 #include "chrome/service/cloud_print/printer_job_handler.h" | 21 #include "chrome/service/cloud_print/printer_job_handler.h" |
| 21 #include "chrome/service/gaia/service_gaia_authenticator.h" | 22 #include "chrome/service/gaia/service_gaia_authenticator.h" |
| 22 #include "chrome/service/service_process.h" | 23 #include "chrome/service/service_process.h" |
| 23 #include "googleurl/src/gurl.h" | 24 #include "googleurl/src/gurl.h" |
| 24 #include "jingle/notifier/base/notifier_options.h" | 25 #include "jingle/notifier/base/notifier_options.h" |
| 25 #include "jingle/notifier/listener/push_notifications_thread.h" | 26 #include "jingle/notifier/listener/push_notifications_thread.h" |
| 26 #include "jingle/notifier/listener/talk_mediator_impl.h" | 27 #include "jingle/notifier/listener/talk_mediator_impl.h" |
| 27 #include "net/url_request/url_request_status.h" | 28 #include "net/url_request/url_request_status.h" |
| 28 | 29 |
| 29 // The real guts of CloudPrintProxyBackend, to keep the public client API clean. | 30 // The real guts of CloudPrintProxyBackend, to keep the public client API clean. |
| 30 class CloudPrintProxyBackend::Core | 31 class CloudPrintProxyBackend::Core |
| 31 : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>, | 32 : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>, |
| 32 public URLFetcherDelegate, | 33 public CloudPrintURLFetcherDelegate, |
| 33 public cloud_print::PrintServerWatcherDelegate, | 34 public cloud_print::PrintServerWatcherDelegate, |
| 34 public PrinterJobHandlerDelegate, | 35 public PrinterJobHandlerDelegate, |
| 35 public notifier::TalkMediator::Delegate { | 36 public notifier::TalkMediator::Delegate { |
| 36 public: | 37 public: |
| 37 // It is OK for print_server_url to be empty. In this case system should | 38 // It is OK for print_server_url to be empty. In this case system should |
| 38 // use system default (local) print server. | 39 // use system default (local) print server. |
| 39 explicit Core(CloudPrintProxyBackend* backend, | 40 explicit Core(CloudPrintProxyBackend* backend, |
| 40 const GURL& cloud_print_server_url, | 41 const GURL& cloud_print_server_url, |
| 41 const DictionaryValue* print_system_settings); | 42 const DictionaryValue* print_system_settings); |
| 42 | 43 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 55 const std::string cloud_print_xmpp_token, | 56 const std::string cloud_print_xmpp_token, |
| 56 const std::string email, | 57 const std::string email, |
| 57 const std::string& proxy_id); | 58 const std::string& proxy_id); |
| 58 | 59 |
| 59 // Called on the CloudPrintProxyBackend core_thread_ to perform | 60 // Called on the CloudPrintProxyBackend core_thread_ to perform |
| 60 // shutdown. | 61 // shutdown. |
| 61 void DoShutdown(); | 62 void DoShutdown(); |
| 62 void DoRegisterSelectedPrinters( | 63 void DoRegisterSelectedPrinters( |
| 63 const printing::PrinterList& printer_list); | 64 const printing::PrinterList& printer_list); |
| 64 | 65 |
| 65 // URLFetcher::Delegate implementation. | 66 // CloudPrintURLFetcher::Delegate implementation. |
| 66 virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url, | 67 virtual CloudPrintURLFetcher::ResponseAction HandleJSONData( |
| 67 const URLRequestStatus& status, | 68 const URLFetcher* source, |
| 68 int response_code, | 69 const GURL& url, |
| 69 const ResponseCookies& cookies, | 70 DictionaryValue* json_data, |
| 70 const std::string& data); | 71 bool succeeded); |
| 72 |
| 73 virtual void OnRequestAuthError(); |
| 74 |
| 71 // cloud_print::PrintServerWatcherDelegate implementation | 75 // cloud_print::PrintServerWatcherDelegate implementation |
| 72 virtual void OnPrinterAdded(); | 76 virtual void OnPrinterAdded(); |
| 73 // PrinterJobHandler::Delegate implementation | 77 // PrinterJobHandler::Delegate implementation |
| 74 virtual void OnPrinterJobHandlerShutdown(PrinterJobHandler* job_handler, | 78 virtual void OnPrinterJobHandlerShutdown(PrinterJobHandler* job_handler, |
| 75 const std::string& printer_id); | 79 const std::string& printer_id); |
| 76 virtual void OnAuthError(); | 80 virtual void OnAuthError(); |
| 77 | 81 |
| 78 // notifier::TalkMediator::Delegate implementation. | 82 // notifier::TalkMediator::Delegate implementation. |
| 79 virtual void OnNotificationStateChange( | 83 virtual void OnNotificationStateChange( |
| 80 bool notifications_enabled); | 84 bool notifications_enabled); |
| 81 virtual void OnIncomingNotification( | 85 virtual void OnIncomingNotification( |
| 82 const IncomingNotificationData& notification_data); | 86 const IncomingNotificationData& notification_data); |
| 83 virtual void OnOutgoingNotification(); | 87 virtual void OnOutgoingNotification(); |
| 84 | 88 |
| 85 protected: | 89 private: |
| 86 // Prototype for a response handler. | 90 // Prototype for a response handler. |
| 87 typedef void (CloudPrintProxyBackend::Core::*ResponseHandler)( | 91 typedef CloudPrintURLFetcher::ResponseAction |
| 88 const URLFetcher* source, const GURL& url, | 92 (CloudPrintProxyBackend::Core::*ResponseHandler)( |
| 89 const URLRequestStatus& status, int response_code, | 93 const URLFetcher* source, |
| 90 const ResponseCookies& cookies, const std::string& data); | 94 const GURL& url, |
| 95 DictionaryValue* json_data, |
| 96 bool succeeded); |
| 91 // Begin response handlers | 97 // Begin response handlers |
| 92 void HandlePrinterListResponse(const URLFetcher* source, const GURL& url, | 98 CloudPrintURLFetcher::ResponseAction HandlePrinterListResponse( |
| 93 const URLRequestStatus& status, | 99 const URLFetcher* source, |
| 94 int response_code, | 100 const GURL& url, |
| 95 const ResponseCookies& cookies, | 101 DictionaryValue* json_data, |
| 96 const std::string& data); | 102 bool succeeded); |
| 97 void HandleRegisterPrinterResponse(const URLFetcher* source, | 103 |
| 98 const GURL& url, | 104 CloudPrintURLFetcher::ResponseAction HandleRegisterPrinterResponse( |
| 99 const URLRequestStatus& status, | 105 const URLFetcher* source, |
| 100 int response_code, | 106 const GURL& url, |
| 101 const ResponseCookies& cookies, | 107 DictionaryValue* json_data, |
| 102 const std::string& data); | 108 bool succeeded); |
| 103 // End response handlers | 109 // End response handlers |
| 104 | 110 |
| 105 // NotifyXXX is how the Core communicates with the frontend across | 111 // NotifyXXX is how the Core communicates with the frontend across |
| 106 // threads. | 112 // threads. |
| 107 void NotifyPrinterListAvailable( | 113 void NotifyPrinterListAvailable( |
| 108 const printing::PrinterList& printer_list); | 114 const printing::PrinterList& printer_list); |
| 109 void NotifyAuthenticated( | 115 void NotifyAuthenticated( |
| 110 const std::string& cloud_print_token, | 116 const std::string& cloud_print_token, |
| 111 const std::string& cloud_print_xmpp_token, | 117 const std::string& cloud_print_xmpp_token, |
| 112 const std::string& email); | 118 const std::string& email); |
| 113 void NotifyAuthenticationFailed(); | 119 void NotifyAuthenticationFailed(); |
| 114 | 120 |
| 121 URLFetcherProtectEntry* CreateDefaultRetryPolicy(); |
| 122 |
| 115 // Starts a new printer registration process. | 123 // Starts a new printer registration process. |
| 116 void StartRegistration(); | 124 void StartRegistration(); |
| 117 // Ends the printer registration process. | 125 // Ends the printer registration process. |
| 118 void EndRegistration(); | 126 void EndRegistration(); |
| 119 // Registers printer capabilities and defaults for the next printer in the | 127 // Registers printer capabilities and defaults for the next printer in the |
| 120 // list with the cloud print server. | 128 // list with the cloud print server. |
| 121 void RegisterNextPrinter(); | 129 void RegisterNextPrinter(); |
| 122 // Retrieves the list of registered printers for this user/proxy combination | 130 // Retrieves the list of registered printers for this user/proxy combination |
| 123 // from the cloud print server. | 131 // from the cloud print server. |
| 124 void GetRegisteredPrinters(); | 132 void GetRegisteredPrinters(); |
| 125 void HandleServerError(Task* task_to_retry); | |
| 126 // Removes the given printer from the list. Returns false if the printer | 133 // Removes the given printer from the list. Returns false if the printer |
| 127 // did not exist in the list. | 134 // did not exist in the list. |
| 128 bool RemovePrinterFromList(const std::string& printer_name); | 135 bool RemovePrinterFromList(const std::string& printer_name); |
| 129 // Initializes a job handler object for the specified printer. The job | 136 // Initializes a job handler object for the specified printer. The job |
| 130 // handler is responsible for checking for pending print jobs for this | 137 // handler is responsible for checking for pending print jobs for this |
| 131 // printer and print them. | 138 // printer and print them. |
| 132 void InitJobHandlerForPrinter(DictionaryValue* printer_data); | 139 void InitJobHandlerForPrinter(DictionaryValue* printer_data); |
| 133 | 140 |
| 134 void HandlePrinterNotification(const std::string& printer_id); | 141 void HandlePrinterNotification(const std::string& printer_id); |
| 135 void PollForJobs(); | 142 void PollForJobs(); |
| 136 // Schedules a task to poll for jobs. Does nothing if a task is already | 143 // Schedules a task to poll for jobs. Does nothing if a task is already |
| 137 // scheduled. | 144 // scheduled. |
| 138 void ScheduleJobPoll(); | 145 void ScheduleJobPoll(); |
| 139 | 146 |
| 140 // Our parent CloudPrintProxyBackend | 147 // Our parent CloudPrintProxyBackend |
| 141 CloudPrintProxyBackend* backend_; | 148 CloudPrintProxyBackend* backend_; |
| 142 | 149 |
| 143 GURL cloud_print_server_url_; | 150 GURL cloud_print_server_url_; |
| 144 scoped_ptr<DictionaryValue> print_system_settings_; | 151 scoped_ptr<DictionaryValue> print_system_settings_; |
| 145 // Pointer to current print system. | 152 // Pointer to current print system. |
| 146 scoped_refptr<cloud_print::PrintSystem> print_system_; | 153 scoped_refptr<cloud_print::PrintSystem> print_system_; |
| 147 // The list of printers to be registered with the cloud print server. | 154 // The list of printers to be registered with the cloud print server. |
| 148 // To begin with,this list is initialized with the list of local and network | 155 // To begin with,this list is initialized with the list of local and network |
| 149 // printers available. Then we query the server for the list of printers | 156 // printers available. Then we query the server for the list of printers |
| 150 // already registered. We trim this list to remove the printers already | 157 // already registered. We trim this list to remove the printers already |
| 151 // registered. We then pass a copy of this list to the frontend to give the | 158 // registered. We then pass a copy of this list to the frontend to give the |
| 152 // user a chance to further trim the list. When the frontend gives us the | 159 // user a chance to further trim the list. When the frontend gives us the |
| 153 // final list we make a copy into this so that we can start registering. | 160 // final list we make a copy into this so that we can start registering. |
| 154 printing::PrinterList printer_list_; | 161 printing::PrinterList printer_list_; |
| 155 // The URLFetcher instance for the current request | 162 // The CloudPrintURLFetcher instance for the current request. |
| 156 scoped_ptr<URLFetcher> request_; | 163 scoped_refptr<CloudPrintURLFetcher> request_; |
| 157 // The index of the nex printer to be uploaded. | 164 // The index of the nex printer to be uploaded. |
| 158 size_t next_upload_index_; | 165 size_t next_upload_index_; |
| 159 // The unique id for this proxy | 166 // The unique id for this proxy |
| 160 std::string proxy_id_; | 167 std::string proxy_id_; |
| 161 // The GAIA auth token | 168 // The GAIA auth token |
| 162 std::string auth_token_; | 169 std::string auth_token_; |
| 163 // The number of consecutive times that connecting to the server failed. | |
| 164 int server_error_count_; | |
| 165 // Cached info about the last printer that we tried to upload. We cache this | 170 // Cached info about the last printer that we tried to upload. We cache this |
| 166 // so we won't have to requery the printer if the upload fails and we need | 171 // so we won't have to requery the printer if the upload fails and we need |
| 167 // to retry. | 172 // to retry. |
| 168 std::string last_uploaded_printer_name_; | 173 std::string last_uploaded_printer_name_; |
| 169 printing::PrinterCapsAndDefaults last_uploaded_printer_info_; | 174 printing::PrinterCapsAndDefaults last_uploaded_printer_info_; |
| 170 // A map of printer id to job handler. | 175 // A map of printer id to job handler. |
| 171 typedef std::map<std::string, scoped_refptr<PrinterJobHandler> > | 176 typedef std::map<std::string, scoped_refptr<PrinterJobHandler> > |
| 172 JobHandlerMap; | 177 JobHandlerMap; |
| 173 JobHandlerMap job_handler_map_; | 178 JobHandlerMap job_handler_map_; |
| 174 ResponseHandler next_response_handler_; | 179 ResponseHandler next_response_handler_; |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 core_thread_.message_loop()->PostTask(FROM_HERE, | 246 core_thread_.message_loop()->PostTask(FROM_HERE, |
| 242 NewRunnableMethod( | 247 NewRunnableMethod( |
| 243 core_.get(), | 248 core_.get(), |
| 244 &CloudPrintProxyBackend::Core::DoRegisterSelectedPrinters, | 249 &CloudPrintProxyBackend::Core::DoRegisterSelectedPrinters, |
| 245 printer_list)); | 250 printer_list)); |
| 246 } | 251 } |
| 247 | 252 |
| 248 CloudPrintProxyBackend::Core::Core(CloudPrintProxyBackend* backend, | 253 CloudPrintProxyBackend::Core::Core(CloudPrintProxyBackend* backend, |
| 249 const GURL& cloud_print_server_url, | 254 const GURL& cloud_print_server_url, |
| 250 const DictionaryValue* print_system_settings) | 255 const DictionaryValue* print_system_settings) |
| 251 : backend_(backend), cloud_print_server_url_(cloud_print_server_url), | 256 : backend_(backend), |
| 252 next_upload_index_(0), server_error_count_(0), | 257 cloud_print_server_url_(cloud_print_server_url), |
| 253 next_response_handler_(NULL), new_printers_available_(false), | 258 next_upload_index_(0), |
| 254 notifications_enabled_(false), job_poll_scheduled_(false) { | 259 next_response_handler_(NULL), |
| 260 new_printers_available_(false), |
| 261 notifications_enabled_(false), |
| 262 job_poll_scheduled_(false) { |
| 255 if (print_system_settings) { | 263 if (print_system_settings) { |
| 256 // It is possible to have no print settings specified. | 264 // It is possible to have no print settings specified. |
| 257 print_system_settings_.reset( | 265 print_system_settings_.reset( |
| 258 reinterpret_cast<DictionaryValue*>(print_system_settings->DeepCopy())); | 266 reinterpret_cast<DictionaryValue*>(print_system_settings->DeepCopy())); |
| 259 } | 267 } |
| 260 } | 268 } |
| 261 | 269 |
| 262 void CloudPrintProxyBackend::Core::DoInitializeWithLsid( | 270 void CloudPrintProxyBackend::Core::DoInitializeWithLsid( |
| 263 const std::string& lsid, const std::string& proxy_id) { | 271 const std::string& lsid, const std::string& proxy_id) { |
| 264 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 272 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 talk_mediator_->AddSubscribedServiceUrl(push_notifications_channel_); | 343 talk_mediator_->AddSubscribedServiceUrl(push_notifications_channel_); |
| 336 talk_mediator_->SetDelegate(this); | 344 talk_mediator_->SetDelegate(this); |
| 337 talk_mediator_->SetAuthToken(email, cloud_print_xmpp_token, | 345 talk_mediator_->SetAuthToken(email, cloud_print_xmpp_token, |
| 338 kSyncGaiaServiceId); | 346 kSyncGaiaServiceId); |
| 339 talk_mediator_->Login(); | 347 talk_mediator_->Login(); |
| 340 | 348 |
| 341 print_server_watcher_ = print_system_->CreatePrintServerWatcher(); | 349 print_server_watcher_ = print_system_->CreatePrintServerWatcher(); |
| 342 print_server_watcher_->StartWatching(this); | 350 print_server_watcher_->StartWatching(this); |
| 343 | 351 |
| 344 proxy_id_ = proxy_id; | 352 proxy_id_ = proxy_id; |
| 353 |
| 354 // Register the request retry policies for cloud print APIs and job data |
| 355 // requests. |
| 356 URLFetcherProtectManager::GetInstance()->Register( |
| 357 kCloudPrintAPIRetryPolicy, CreateDefaultRetryPolicy()); |
| 358 URLFetcherProtectManager::GetInstance()->Register( |
| 359 kJobDataRetryPolicy, CreateDefaultRetryPolicy())->SetMaxRetries( |
| 360 kJobDataMaxRetryCount); |
| 361 |
| 345 StartRegistration(); | 362 StartRegistration(); |
| 346 } | 363 } |
| 347 | 364 |
| 365 URLFetcherProtectEntry* |
| 366 CloudPrintProxyBackend::Core::CreateDefaultRetryPolicy() { |
| 367 // Times are in milliseconds. |
| 368 const int kSlidingWindowPeriod = 2000; |
| 369 const int kMaxSendThreshold = 20; |
| 370 const int kMaxRetries = -1; |
| 371 const int kInitialTimeout = 100; |
| 372 const double kMultiplier = 2.0; |
| 373 const int kConstantFactor = 100; |
| 374 const int kMaximumTimeout = 5*60*1000; |
| 375 return new URLFetcherProtectEntry(kSlidingWindowPeriod, |
| 376 kMaxSendThreshold, |
| 377 kMaxRetries, |
| 378 kInitialTimeout, |
| 379 kMultiplier, |
| 380 kConstantFactor, |
| 381 kMaximumTimeout); |
| 382 } |
| 383 |
| 348 void CloudPrintProxyBackend::Core::StartRegistration() { | 384 void CloudPrintProxyBackend::Core::StartRegistration() { |
| 349 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 385 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 350 printer_list_.clear(); | 386 printer_list_.clear(); |
| 351 print_system_->GetPrintBackend()->EnumeratePrinters(&printer_list_); | 387 print_system_->GetPrintBackend()->EnumeratePrinters(&printer_list_); |
| 352 server_error_count_ = 0; | |
| 353 // Now we need to ask the server about printers that were registered on the | 388 // Now we need to ask the server about printers that were registered on the |
| 354 // server so that we can trim this list. | 389 // server so that we can trim this list. |
| 355 GetRegisteredPrinters(); | 390 GetRegisteredPrinters(); |
| 356 } | 391 } |
| 357 | 392 |
| 358 void CloudPrintProxyBackend::Core::EndRegistration() { | 393 void CloudPrintProxyBackend::Core::EndRegistration() { |
| 359 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 394 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 360 request_.reset(); | 395 request_ = NULL; |
| 361 if (new_printers_available_) { | 396 if (new_printers_available_) { |
| 362 new_printers_available_ = false; | 397 new_printers_available_ = false; |
| 363 StartRegistration(); | 398 StartRegistration(); |
| 364 } | 399 } |
| 365 } | 400 } |
| 366 | 401 |
| 367 void CloudPrintProxyBackend::Core::DoShutdown() { | 402 void CloudPrintProxyBackend::Core::DoShutdown() { |
| 368 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 403 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 369 VLOG(1) << "CP_PROXY: Shutdown proxy, id: " << proxy_id_; | 404 VLOG(1) << "CP_PROXY: Shutdown proxy, id: " << proxy_id_; |
| 370 if (print_server_watcher_ != NULL) | 405 if (print_server_watcher_ != NULL) |
| 371 print_server_watcher_->StopWatching(); | 406 print_server_watcher_->StopWatching(); |
| 372 | 407 |
| 373 // Need to kill all running jobs. | 408 // Need to kill all running jobs. |
| 374 while (!job_handler_map_.empty()) { | 409 while (!job_handler_map_.empty()) { |
| 375 JobHandlerMap::iterator index = job_handler_map_.begin(); | 410 JobHandlerMap::iterator index = job_handler_map_.begin(); |
| 376 // Shutdown will call our OnPrinterJobHandlerShutdown method which will | 411 // Shutdown will call our OnPrinterJobHandlerShutdown method which will |
| 377 // remove this from the map. | 412 // remove this from the map. |
| 378 index->second->Shutdown(); | 413 index->second->Shutdown(); |
| 379 } | 414 } |
| 380 // Important to delete the TalkMediator on this thread. | 415 // Important to delete the TalkMediator on this thread. |
| 381 talk_mediator_.reset(); | 416 talk_mediator_.reset(); |
| 382 notifications_enabled_ = false; | 417 notifications_enabled_ = false; |
| 383 request_.reset(); | 418 request_ = NULL; |
| 384 MessageLoop::current()->QuitNow(); | 419 MessageLoop::current()->QuitNow(); |
| 385 } | 420 } |
| 386 | 421 |
| 387 void CloudPrintProxyBackend::Core::DoRegisterSelectedPrinters( | 422 void CloudPrintProxyBackend::Core::DoRegisterSelectedPrinters( |
| 388 const printing::PrinterList& printer_list) { | 423 const printing::PrinterList& printer_list) { |
| 389 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 424 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 390 if (!print_system_.get()) | 425 if (!print_system_.get()) |
| 391 return; // No print system available. | 426 return; // No print system available. |
| 392 server_error_count_ = 0; | |
| 393 printer_list_.assign(printer_list.begin(), printer_list.end()); | 427 printer_list_.assign(printer_list.begin(), printer_list.end()); |
| 394 next_upload_index_ = 0; | 428 next_upload_index_ = 0; |
| 395 RegisterNextPrinter(); | 429 RegisterNextPrinter(); |
| 396 } | 430 } |
| 397 | 431 |
| 398 void CloudPrintProxyBackend::Core::GetRegisteredPrinters() { | 432 void CloudPrintProxyBackend::Core::GetRegisteredPrinters() { |
| 399 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 433 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 400 request_.reset( | 434 GURL printer_list_url = |
| 401 new URLFetcher( | 435 CloudPrintHelpers::GetUrlForPrinterList(cloud_print_server_url_, |
| 402 CloudPrintHelpers::GetUrlForPrinterList(cloud_print_server_url_, | 436 proxy_id_); |
| 403 proxy_id_), | |
| 404 URLFetcher::GET, this)); | |
| 405 CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_); | |
| 406 next_response_handler_ = | 437 next_response_handler_ = |
| 407 &CloudPrintProxyBackend::Core::HandlePrinterListResponse; | 438 &CloudPrintProxyBackend::Core::HandlePrinterListResponse; |
| 408 request_->Start(); | 439 request_ = new CloudPrintURLFetcher; |
| 440 request_->StartGetRequest(printer_list_url, this, auth_token_, |
| 441 kCloudPrintAPIRetryPolicy); |
| 409 } | 442 } |
| 410 | 443 |
| 411 void CloudPrintProxyBackend::Core::RegisterNextPrinter() { | 444 void CloudPrintProxyBackend::Core::RegisterNextPrinter() { |
| 412 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 445 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 413 // For the next printer to be uploaded, create a multi-part post request to | 446 // For the next printer to be uploaded, create a multi-part post request to |
| 414 // upload the printer capabilities and the printer defaults. | 447 // upload the printer capabilities and the printer defaults. |
| 415 if (next_upload_index_ < printer_list_.size()) { | 448 if (next_upload_index_ < printer_list_.size()) { |
| 416 const printing::PrinterBasicInfo& info = | 449 const printing::PrinterBasicInfo& info = |
| 417 printer_list_.at(next_upload_index_); | 450 printer_list_.at(next_upload_index_); |
| 418 bool have_printer_info = true; | 451 bool have_printer_info = true; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 458 // Send a hash of the printer capabilities to the server. We will use this | 491 // Send a hash of the printer capabilities to the server. We will use this |
| 459 // later to check if the capabilities have changed | 492 // later to check if the capabilities have changed |
| 460 CloudPrintHelpers::AddMultipartValueForUpload( | 493 CloudPrintHelpers::AddMultipartValueForUpload( |
| 461 kPrinterCapsHashValue, | 494 kPrinterCapsHashValue, |
| 462 MD5String(last_uploaded_printer_info_.printer_capabilities), | 495 MD5String(last_uploaded_printer_info_.printer_capabilities), |
| 463 mime_boundary, std::string(), &post_data); | 496 mime_boundary, std::string(), &post_data); |
| 464 // Terminate the request body | 497 // Terminate the request body |
| 465 post_data.append("--" + mime_boundary + "--\r\n"); | 498 post_data.append("--" + mime_boundary + "--\r\n"); |
| 466 std::string mime_type("multipart/form-data; boundary="); | 499 std::string mime_type("multipart/form-data; boundary="); |
| 467 mime_type += mime_boundary; | 500 mime_type += mime_boundary; |
| 468 request_.reset( | 501 GURL register_url = CloudPrintHelpers::GetUrlForPrinterRegistration( |
| 469 new URLFetcher( | 502 cloud_print_server_url_); |
| 470 CloudPrintHelpers::GetUrlForPrinterRegistration( | 503 |
| 471 cloud_print_server_url_), | |
| 472 URLFetcher::POST, this)); | |
| 473 CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_); | |
| 474 request_->set_upload_data(mime_type, post_data); | |
| 475 next_response_handler_ = | 504 next_response_handler_ = |
| 476 &CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse; | 505 &CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse; |
| 477 request_->Start(); | 506 request_ = new CloudPrintURLFetcher; |
| 507 request_->StartPostRequest(register_url, this, auth_token_, |
| 508 kCloudPrintAPIRetryPolicy, mime_type, |
| 509 post_data); |
| 510 |
| 478 } else { | 511 } else { |
| 479 LOG(ERROR) << "CP_PROXY: Failed to get printer info for: " << | 512 LOG(ERROR) << "CP_PROXY: Failed to get printer info for: " << |
| 480 info.printer_name; | 513 info.printer_name; |
| 481 next_upload_index_++; | 514 next_upload_index_++; |
| 482 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this, | 515 MessageLoop::current()->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 483 &CloudPrintProxyBackend::Core::RegisterNextPrinter)); | 516 &CloudPrintProxyBackend::Core::RegisterNextPrinter)); |
| 484 } | 517 } |
| 485 } else { | 518 } else { |
| 486 EndRegistration(); | 519 EndRegistration(); |
| 487 } | 520 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 514 int interval_in_seconds = base::RandInt(kMinJobPollIntervalSecs, | 547 int interval_in_seconds = base::RandInt(kMinJobPollIntervalSecs, |
| 515 kMaxJobPollIntervalSecs); | 548 kMaxJobPollIntervalSecs); |
| 516 MessageLoop::current()->PostDelayedTask( | 549 MessageLoop::current()->PostDelayedTask( |
| 517 FROM_HERE, | 550 FROM_HERE, |
| 518 NewRunnableMethod(this, &CloudPrintProxyBackend::Core::PollForJobs), | 551 NewRunnableMethod(this, &CloudPrintProxyBackend::Core::PollForJobs), |
| 519 interval_in_seconds * 1000); | 552 interval_in_seconds * 1000); |
| 520 job_poll_scheduled_ = true; | 553 job_poll_scheduled_ = true; |
| 521 } | 554 } |
| 522 } | 555 } |
| 523 | 556 |
| 524 // URLFetcher::Delegate implementation. | 557 // CloudPrintURLFetcher::Delegate implementation. |
| 525 void CloudPrintProxyBackend::Core::OnURLFetchComplete( | 558 CloudPrintURLFetcher::ResponseAction |
| 526 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, | 559 CloudPrintProxyBackend::Core::HandleJSONData( |
| 527 int response_code, const ResponseCookies& cookies, | 560 const URLFetcher* source, |
| 528 const std::string& data) { | 561 const GURL& url, |
| 529 DCHECK(source == request_.get()); | 562 DictionaryValue* json_data, |
| 530 // If we get an auth error, we need to give up right away and notify the | 563 bool succeeded) { |
| 531 // frontend loop. | 564 DCHECK(next_response_handler_); |
| 532 if (RC_FORBIDDEN == response_code) { | 565 return (this->*next_response_handler_)(source, url, json_data, succeeded); |
| 533 backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 566 } |
| 534 &Core::NotifyAuthenticationFailed)); | 567 |
| 535 } else { | 568 void CloudPrintProxyBackend::Core::OnRequestAuthError() { |
| 536 // We need a next response handler | 569 OnAuthError(); |
| 537 DCHECK(next_response_handler_); | |
| 538 (this->*next_response_handler_)(source, url, status, response_code, | |
| 539 cookies, data); | |
| 540 } | |
| 541 } | 570 } |
| 542 | 571 |
| 543 void CloudPrintProxyBackend::Core::NotifyPrinterListAvailable( | 572 void CloudPrintProxyBackend::Core::NotifyPrinterListAvailable( |
| 544 const printing::PrinterList& printer_list) { | 573 const printing::PrinterList& printer_list) { |
| 545 DCHECK(MessageLoop::current() == backend_->frontend_loop_); | 574 DCHECK(MessageLoop::current() == backend_->frontend_loop_); |
| 546 backend_->frontend_->OnPrinterListAvailable(printer_list); | 575 backend_->frontend_->OnPrinterListAvailable(printer_list); |
| 547 } | 576 } |
| 548 | 577 |
| 549 void CloudPrintProxyBackend::Core::NotifyAuthenticated( | 578 void CloudPrintProxyBackend::Core::NotifyAuthenticated( |
| 550 const std::string& cloud_print_token, | 579 const std::string& cloud_print_token, |
| 551 const std::string& cloud_print_xmpp_token, | 580 const std::string& cloud_print_xmpp_token, |
| 552 const std::string& email) { | 581 const std::string& email) { |
| 553 DCHECK(MessageLoop::current() == backend_->frontend_loop_); | 582 DCHECK(MessageLoop::current() == backend_->frontend_loop_); |
| 554 backend_->frontend_->OnAuthenticated(cloud_print_token, | 583 backend_->frontend_->OnAuthenticated(cloud_print_token, |
| 555 cloud_print_xmpp_token, email); | 584 cloud_print_xmpp_token, email); |
| 556 } | 585 } |
| 557 | 586 |
| 558 void CloudPrintProxyBackend::Core::NotifyAuthenticationFailed() { | 587 void CloudPrintProxyBackend::Core::NotifyAuthenticationFailed() { |
| 559 DCHECK(MessageLoop::current() == backend_->frontend_loop_); | 588 DCHECK(MessageLoop::current() == backend_->frontend_loop_); |
| 560 backend_->frontend_->OnAuthenticationFailed(); | 589 backend_->frontend_->OnAuthenticationFailed(); |
| 561 } | 590 } |
| 562 | 591 |
| 563 void CloudPrintProxyBackend::Core::HandlePrinterListResponse( | 592 CloudPrintURLFetcher::ResponseAction |
| 564 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, | 593 CloudPrintProxyBackend::Core::HandlePrinterListResponse( |
| 565 int response_code, const ResponseCookies& cookies, | 594 const URLFetcher* source, |
| 566 const std::string& data) { | 595 const GURL& url, |
| 596 DictionaryValue* json_data, |
| 597 bool succeeded) { |
| 567 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 598 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 568 bool succeeded = false; | 599 if (!succeeded) { |
| 569 if (status.is_success() && response_code == 200) { | 600 NOTREACHED(); |
| 570 server_error_count_ = 0; | 601 return CloudPrintURLFetcher::RETRY_REQUEST; |
| 571 // Parse the response JSON for the list of printers already registered. | 602 } |
| 572 DictionaryValue* response_dict_temp = NULL; | 603 ListValue* printer_list = NULL; |
| 573 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, | 604 json_data->GetList(kPrinterListValue, &printer_list); |
| 574 &response_dict_temp); | 605 // There may be no "printers" value in the JSON |
| 575 scoped_ptr<DictionaryValue> response_dict; | 606 if (printer_list) { |
| 576 response_dict.reset(response_dict_temp); | 607 for (size_t index = 0; index < printer_list->GetSize(); index++) { |
| 577 if (succeeded) { | 608 DictionaryValue* printer_data = NULL; |
| 578 DCHECK(response_dict.get()); | 609 if (printer_list->GetDictionary(index, &printer_data)) { |
| 579 ListValue* printer_list = NULL; | 610 std::string printer_name; |
| 580 response_dict->GetList(kPrinterListValue, &printer_list); | 611 printer_data->GetString(kNameValue, &printer_name); |
| 581 // There may be no "printers" value in the JSON | 612 RemovePrinterFromList(printer_name); |
| 582 if (printer_list) { | 613 InitJobHandlerForPrinter(printer_data); |
| 583 for (size_t index = 0; index < printer_list->GetSize(); index++) { | |
| 584 DictionaryValue* printer_data = NULL; | |
| 585 if (printer_list->GetDictionary(index, &printer_data)) { | |
| 586 std::string printer_name; | |
| 587 printer_data->GetString(kNameValue, &printer_name); | |
| 588 RemovePrinterFromList(printer_name); | |
| 589 InitJobHandlerForPrinter(printer_data); | |
| 590 } else { | |
| 591 NOTREACHED(); | |
| 592 } | |
| 593 } | |
| 594 } | |
| 595 MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release()); | |
| 596 if (!printer_list_.empty()) { | |
| 597 // Let the frontend know that we have a list of printers available. | |
| 598 backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | |
| 599 &Core::NotifyPrinterListAvailable, printer_list_)); | |
| 600 } else { | 614 } else { |
| 601 // No more work to be done here. | 615 NOTREACHED(); |
| 602 MessageLoop::current()->PostTask( | |
| 603 FROM_HERE, NewRunnableMethod(this, &Core::EndRegistration)); | |
| 604 } | 616 } |
| 605 } | 617 } |
| 606 } | 618 } |
| 607 | 619 request_ = NULL; |
| 608 if (!succeeded) | 620 if (!printer_list_.empty()) { |
| 609 HandleServerError(NewRunnableMethod(this, &Core::GetRegisteredPrinters)); | 621 // Let the frontend know that we have a list of printers available. |
| 622 backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 623 &Core::NotifyPrinterListAvailable, printer_list_)); |
| 624 } else { |
| 625 // No more work to be done here. |
| 626 MessageLoop::current()->PostTask( |
| 627 FROM_HERE, NewRunnableMethod(this, &Core::EndRegistration)); |
| 628 } |
| 629 return CloudPrintURLFetcher::STOP_PROCESSING; |
| 610 } | 630 } |
| 611 | 631 |
| 612 void CloudPrintProxyBackend::Core::InitJobHandlerForPrinter( | 632 void CloudPrintProxyBackend::Core::InitJobHandlerForPrinter( |
| 613 DictionaryValue* printer_data) { | 633 DictionaryValue* printer_data) { |
| 614 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 634 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 615 DCHECK(printer_data); | 635 DCHECK(printer_data); |
| 616 PrinterJobHandler::PrinterInfoFromCloud printer_info_cloud; | 636 PrinterJobHandler::PrinterInfoFromCloud printer_info_cloud; |
| 617 printer_data->GetString(kIdValue, &printer_info_cloud.printer_id); | 637 printer_data->GetString(kIdValue, &printer_info_cloud.printer_id); |
| 618 DCHECK(!printer_info_cloud.printer_id.empty()); | 638 DCHECK(!printer_info_cloud.printer_id.empty()); |
| 619 VLOG(1) << "CP_PROXY: Init job handler for printer id: " | 639 VLOG(1) << "CP_PROXY: Init job handler for printer id: " |
| (...skipping 28 matching lines...) Expand all Loading... |
| 648 } | 668 } |
| 649 scoped_refptr<PrinterJobHandler> job_handler; | 669 scoped_refptr<PrinterJobHandler> job_handler; |
| 650 job_handler = new PrinterJobHandler(printer_info, printer_info_cloud, | 670 job_handler = new PrinterJobHandler(printer_info, printer_info_cloud, |
| 651 auth_token_, cloud_print_server_url_, | 671 auth_token_, cloud_print_server_url_, |
| 652 print_system_.get(), this); | 672 print_system_.get(), this); |
| 653 job_handler_map_[printer_info_cloud.printer_id] = job_handler; | 673 job_handler_map_[printer_info_cloud.printer_id] = job_handler; |
| 654 job_handler->Initialize(); | 674 job_handler->Initialize(); |
| 655 } | 675 } |
| 656 } | 676 } |
| 657 | 677 |
| 658 void CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse( | 678 CloudPrintURLFetcher::ResponseAction |
| 659 const URLFetcher* source, const GURL& url, const URLRequestStatus& status, | 679 CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse( |
| 660 int response_code, const ResponseCookies& cookies, | 680 const URLFetcher* source, |
| 661 const std::string& data) { | 681 const GURL& url, |
| 682 DictionaryValue* json_data, |
| 683 bool succeeded) { |
| 662 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 684 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 663 VLOG(1) << "CP_PROXY: Handle register printer response, code: " | 685 if (succeeded) { |
| 664 << response_code; | 686 ListValue* printer_list = NULL; |
| 665 Task* next_task = | 687 json_data->GetList(kPrinterListValue, &printer_list); |
| 688 // There should be a "printers" value in the JSON |
| 689 DCHECK(printer_list); |
| 690 if (printer_list) { |
| 691 DictionaryValue* printer_data = NULL; |
| 692 if (printer_list->GetDictionary(0, &printer_data)) |
| 693 InitJobHandlerForPrinter(printer_data); |
| 694 } |
| 695 } |
| 696 next_upload_index_++; |
| 697 MessageLoop::current()->PostTask( |
| 698 FROM_HERE, |
| 666 NewRunnableMethod(this, | 699 NewRunnableMethod(this, |
| 667 &CloudPrintProxyBackend::Core::RegisterNextPrinter); | 700 &CloudPrintProxyBackend::Core::RegisterNextPrinter)); |
| 668 if (status.is_success() && (response_code == 200)) { | 701 return CloudPrintURLFetcher::STOP_PROCESSING; |
| 669 bool succeeded = false; | |
| 670 DictionaryValue* response_dict = NULL; | |
| 671 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict); | |
| 672 if (succeeded) { | |
| 673 DCHECK(response_dict); | |
| 674 ListValue* printer_list = NULL; | |
| 675 response_dict->GetList(kPrinterListValue, &printer_list); | |
| 676 // There should be a "printers" value in the JSON | |
| 677 DCHECK(printer_list); | |
| 678 if (printer_list) { | |
| 679 DictionaryValue* printer_data = NULL; | |
| 680 if (printer_list->GetDictionary(0, &printer_data)) | |
| 681 InitJobHandlerForPrinter(printer_data); | |
| 682 } | |
| 683 } | |
| 684 server_error_count_ = 0; | |
| 685 next_upload_index_++; | |
| 686 MessageLoop::current()->PostTask(FROM_HERE, next_task); | |
| 687 } else { | |
| 688 HandleServerError(next_task); | |
| 689 } | |
| 690 } | |
| 691 | |
| 692 void CloudPrintProxyBackend::Core::HandleServerError(Task* task_to_retry) { | |
| 693 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | |
| 694 VLOG(1) << "CP_PROXY: Server error."; | |
| 695 CloudPrintHelpers::HandleServerError( | |
| 696 &server_error_count_, -1, kMaxRetryInterval, kBaseRetryInterval, | |
| 697 task_to_retry, NULL); | |
| 698 } | 702 } |
| 699 | 703 |
| 700 bool CloudPrintProxyBackend::Core::RemovePrinterFromList( | 704 bool CloudPrintProxyBackend::Core::RemovePrinterFromList( |
| 701 const std::string& printer_name) { | 705 const std::string& printer_name) { |
| 702 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 706 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 703 for (printing::PrinterList::iterator index = printer_list_.begin(); | 707 for (printing::PrinterList::iterator index = printer_list_.begin(); |
| 704 index != printer_list_.end(); index++) { | 708 index != printer_list_.end(); index++) { |
| 705 if (0 == base::strcasecmp(index->printer_name.c_str(), | 709 if (0 == base::strcasecmp(index->printer_name.c_str(), |
| 706 printer_name.c_str())) { | 710 printer_name.c_str())) { |
| 707 index = printer_list_.erase(index); | 711 index = printer_list_.erase(index); |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 756 VLOG(1) << "CP_PROXY: Printer job handle shutdown, id " << printer_id; | 760 VLOG(1) << "CP_PROXY: Printer job handle shutdown, id " << printer_id; |
| 757 job_handler_map_.erase(printer_id); | 761 job_handler_map_.erase(printer_id); |
| 758 } | 762 } |
| 759 | 763 |
| 760 void CloudPrintProxyBackend::Core::OnAuthError() { | 764 void CloudPrintProxyBackend::Core::OnAuthError() { |
| 761 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); | 765 DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop()); |
| 762 VLOG(1) << "CP_PROXY: Auth Error"; | 766 VLOG(1) << "CP_PROXY: Auth Error"; |
| 763 backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, | 767 backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this, |
| 764 &Core::NotifyAuthenticationFailed)); | 768 &Core::NotifyAuthenticationFailed)); |
| 765 } | 769 } |
| OLD | NEW |