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 |