Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(232)

Side by Side Diff: chrome/service/cloud_print/cloud_print_proxy_backend.cc

Issue 4165013: Re-landing issue 4202006 (http://codereview.chromium.org/4202006/show) which ... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 10 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « chrome/service/cloud_print/cloud_print_proxy_backend.h ('k') | chrome/service/cloud_print/cloud_print_url_fetcher.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698