| Index: chrome/service/cloud_print/cloud_print_proxy_backend.cc
|
| ===================================================================
|
| --- chrome/service/cloud_print/cloud_print_proxy_backend.cc (revision 64444)
|
| +++ chrome/service/cloud_print/cloud_print_proxy_backend.cc (working copy)
|
| @@ -14,9 +14,10 @@
|
| #include "base/string_util.h"
|
| #include "base/utf_string_conversions.h"
|
| #include "base/values.h"
|
| -#include "chrome/common/net/http_return.h"
|
| +#include "chrome/common/net/url_fetcher_protect.h"
|
| #include "chrome/service/cloud_print/cloud_print_consts.h"
|
| #include "chrome/service/cloud_print/cloud_print_helpers.h"
|
| +#include "chrome/service/cloud_print/cloud_print_url_fetcher.h"
|
| #include "chrome/service/cloud_print/printer_job_handler.h"
|
| #include "chrome/service/gaia/service_gaia_authenticator.h"
|
| #include "chrome/service/service_process.h"
|
| @@ -29,7 +30,7 @@
|
| // The real guts of CloudPrintProxyBackend, to keep the public client API clean.
|
| class CloudPrintProxyBackend::Core
|
| : public base::RefCountedThreadSafe<CloudPrintProxyBackend::Core>,
|
| - public URLFetcherDelegate,
|
| + public CloudPrintURLFetcherDelegate,
|
| public cloud_print::PrintServerWatcherDelegate,
|
| public PrinterJobHandlerDelegate,
|
| public notifier::TalkMediator::Delegate {
|
| @@ -62,12 +63,15 @@
|
| void DoRegisterSelectedPrinters(
|
| const printing::PrinterList& printer_list);
|
|
|
| - // URLFetcher::Delegate implementation.
|
| - virtual void OnURLFetchComplete(const URLFetcher* source, const GURL& url,
|
| - const URLRequestStatus& status,
|
| - int response_code,
|
| - const ResponseCookies& cookies,
|
| - const std::string& data);
|
| + // CloudPrintURLFetcher::Delegate implementation.
|
| + virtual CloudPrintURLFetcher::ResponseAction HandleJSONData(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded);
|
| +
|
| + virtual void OnRequestAuthError();
|
| +
|
| // cloud_print::PrintServerWatcherDelegate implementation
|
| virtual void OnPrinterAdded();
|
| // PrinterJobHandler::Delegate implementation
|
| @@ -82,24 +86,26 @@
|
| const IncomingNotificationData& notification_data);
|
| virtual void OnOutgoingNotification();
|
|
|
| - protected:
|
| + private:
|
| // Prototype for a response handler.
|
| - typedef void (CloudPrintProxyBackend::Core::*ResponseHandler)(
|
| - const URLFetcher* source, const GURL& url,
|
| - const URLRequestStatus& status, int response_code,
|
| - const ResponseCookies& cookies, const std::string& data);
|
| + typedef CloudPrintURLFetcher::ResponseAction
|
| + (CloudPrintProxyBackend::Core::*ResponseHandler)(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded);
|
| // Begin response handlers
|
| - void HandlePrinterListResponse(const URLFetcher* source, const GURL& url,
|
| - const URLRequestStatus& status,
|
| - int response_code,
|
| - const ResponseCookies& cookies,
|
| - const std::string& data);
|
| - void HandleRegisterPrinterResponse(const URLFetcher* source,
|
| - const GURL& url,
|
| - const URLRequestStatus& status,
|
| - int response_code,
|
| - const ResponseCookies& cookies,
|
| - const std::string& data);
|
| + CloudPrintURLFetcher::ResponseAction HandlePrinterListResponse(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded);
|
| +
|
| + CloudPrintURLFetcher::ResponseAction HandleRegisterPrinterResponse(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded);
|
| // End response handlers
|
|
|
| // NotifyXXX is how the Core communicates with the frontend across
|
| @@ -112,6 +118,8 @@
|
| const std::string& email);
|
| void NotifyAuthenticationFailed();
|
|
|
| + URLFetcherProtectEntry* CreateDefaultRetryPolicy();
|
| +
|
| // Starts a new printer registration process.
|
| void StartRegistration();
|
| // Ends the printer registration process.
|
| @@ -122,7 +130,6 @@
|
| // Retrieves the list of registered printers for this user/proxy combination
|
| // from the cloud print server.
|
| void GetRegisteredPrinters();
|
| - void HandleServerError(Task* task_to_retry);
|
| // Removes the given printer from the list. Returns false if the printer
|
| // did not exist in the list.
|
| bool RemovePrinterFromList(const std::string& printer_name);
|
| @@ -152,16 +159,14 @@
|
| // user a chance to further trim the list. When the frontend gives us the
|
| // final list we make a copy into this so that we can start registering.
|
| printing::PrinterList printer_list_;
|
| - // The URLFetcher instance for the current request
|
| - scoped_ptr<URLFetcher> request_;
|
| + // The CloudPrintURLFetcher instance for the current request.
|
| + scoped_refptr<CloudPrintURLFetcher> request_;
|
| // The index of the nex printer to be uploaded.
|
| size_t next_upload_index_;
|
| // The unique id for this proxy
|
| std::string proxy_id_;
|
| // The GAIA auth token
|
| std::string auth_token_;
|
| - // The number of consecutive times that connecting to the server failed.
|
| - int server_error_count_;
|
| // Cached info about the last printer that we tried to upload. We cache this
|
| // so we won't have to requery the printer if the upload fails and we need
|
| // to retry.
|
| @@ -248,10 +253,13 @@
|
| CloudPrintProxyBackend::Core::Core(CloudPrintProxyBackend* backend,
|
| const GURL& cloud_print_server_url,
|
| const DictionaryValue* print_system_settings)
|
| - : backend_(backend), cloud_print_server_url_(cloud_print_server_url),
|
| - next_upload_index_(0), server_error_count_(0),
|
| - next_response_handler_(NULL), new_printers_available_(false),
|
| - notifications_enabled_(false), job_poll_scheduled_(false) {
|
| + : backend_(backend),
|
| + cloud_print_server_url_(cloud_print_server_url),
|
| + next_upload_index_(0),
|
| + next_response_handler_(NULL),
|
| + new_printers_available_(false),
|
| + notifications_enabled_(false),
|
| + job_poll_scheduled_(false) {
|
| if (print_system_settings) {
|
| // It is possible to have no print settings specified.
|
| print_system_settings_.reset(
|
| @@ -342,14 +350,41 @@
|
| print_server_watcher_->StartWatching(this);
|
|
|
| proxy_id_ = proxy_id;
|
| +
|
| + // Register the request retry policies for cloud print APIs and job data
|
| + // requests.
|
| + URLFetcherProtectManager::GetInstance()->Register(
|
| + kCloudPrintAPIRetryPolicy, CreateDefaultRetryPolicy());
|
| + URLFetcherProtectManager::GetInstance()->Register(
|
| + kJobDataRetryPolicy, CreateDefaultRetryPolicy())->SetMaxRetries(
|
| + kJobDataMaxRetryCount);
|
| +
|
| StartRegistration();
|
| }
|
|
|
| +URLFetcherProtectEntry*
|
| +CloudPrintProxyBackend::Core::CreateDefaultRetryPolicy() {
|
| + // Times are in milliseconds.
|
| + const int kSlidingWindowPeriod = 2000;
|
| + const int kMaxSendThreshold = 20;
|
| + const int kMaxRetries = -1;
|
| + const int kInitialTimeout = 100;
|
| + const double kMultiplier = 2.0;
|
| + const int kConstantFactor = 100;
|
| + const int kMaximumTimeout = 5*60*1000;
|
| + return new URLFetcherProtectEntry(kSlidingWindowPeriod,
|
| + kMaxSendThreshold,
|
| + kMaxRetries,
|
| + kInitialTimeout,
|
| + kMultiplier,
|
| + kConstantFactor,
|
| + kMaximumTimeout);
|
| +}
|
| +
|
| void CloudPrintProxyBackend::Core::StartRegistration() {
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| printer_list_.clear();
|
| print_system_->GetPrintBackend()->EnumeratePrinters(&printer_list_);
|
| - server_error_count_ = 0;
|
| // Now we need to ask the server about printers that were registered on the
|
| // server so that we can trim this list.
|
| GetRegisteredPrinters();
|
| @@ -357,7 +392,7 @@
|
|
|
| void CloudPrintProxyBackend::Core::EndRegistration() {
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| - request_.reset();
|
| + request_ = NULL;
|
| if (new_printers_available_) {
|
| new_printers_available_ = false;
|
| StartRegistration();
|
| @@ -380,7 +415,7 @@
|
| // Important to delete the TalkMediator on this thread.
|
| talk_mediator_.reset();
|
| notifications_enabled_ = false;
|
| - request_.reset();
|
| + request_ = NULL;
|
| MessageLoop::current()->QuitNow();
|
| }
|
|
|
| @@ -389,7 +424,6 @@
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| if (!print_system_.get())
|
| return; // No print system available.
|
| - server_error_count_ = 0;
|
| printer_list_.assign(printer_list.begin(), printer_list.end());
|
| next_upload_index_ = 0;
|
| RegisterNextPrinter();
|
| @@ -397,15 +431,14 @@
|
|
|
| void CloudPrintProxyBackend::Core::GetRegisteredPrinters() {
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| - request_.reset(
|
| - new URLFetcher(
|
| - CloudPrintHelpers::GetUrlForPrinterList(cloud_print_server_url_,
|
| - proxy_id_),
|
| - URLFetcher::GET, this));
|
| - CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_);
|
| + GURL printer_list_url =
|
| + CloudPrintHelpers::GetUrlForPrinterList(cloud_print_server_url_,
|
| + proxy_id_);
|
| next_response_handler_ =
|
| &CloudPrintProxyBackend::Core::HandlePrinterListResponse;
|
| - request_->Start();
|
| + request_ = new CloudPrintURLFetcher;
|
| + request_->StartGetRequest(printer_list_url, this, auth_token_,
|
| + kCloudPrintAPIRetryPolicy);
|
| }
|
|
|
| void CloudPrintProxyBackend::Core::RegisterNextPrinter() {
|
| @@ -465,16 +498,16 @@
|
| post_data.append("--" + mime_boundary + "--\r\n");
|
| std::string mime_type("multipart/form-data; boundary=");
|
| mime_type += mime_boundary;
|
| - request_.reset(
|
| - new URLFetcher(
|
| - CloudPrintHelpers::GetUrlForPrinterRegistration(
|
| - cloud_print_server_url_),
|
| - URLFetcher::POST, this));
|
| - CloudPrintHelpers::PrepCloudPrintRequest(request_.get(), auth_token_);
|
| - request_->set_upload_data(mime_type, post_data);
|
| + GURL register_url = CloudPrintHelpers::GetUrlForPrinterRegistration(
|
| + cloud_print_server_url_);
|
| +
|
| next_response_handler_ =
|
| &CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse;
|
| - request_->Start();
|
| + request_ = new CloudPrintURLFetcher;
|
| + request_->StartPostRequest(register_url, this, auth_token_,
|
| + kCloudPrintAPIRetryPolicy, mime_type,
|
| + post_data);
|
| +
|
| } else {
|
| LOG(ERROR) << "CP_PROXY: Failed to get printer info for: " <<
|
| info.printer_name;
|
| @@ -521,25 +554,21 @@
|
| }
|
| }
|
|
|
| -// URLFetcher::Delegate implementation.
|
| -void CloudPrintProxyBackend::Core::OnURLFetchComplete(
|
| - const URLFetcher* source, const GURL& url, const URLRequestStatus& status,
|
| - int response_code, const ResponseCookies& cookies,
|
| - const std::string& data) {
|
| - DCHECK(source == request_.get());
|
| - // If we get an auth error, we need to give up right away and notify the
|
| - // frontend loop.
|
| - if (RC_FORBIDDEN == response_code) {
|
| - backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
|
| - &Core::NotifyAuthenticationFailed));
|
| - } else {
|
| - // We need a next response handler
|
| - DCHECK(next_response_handler_);
|
| - (this->*next_response_handler_)(source, url, status, response_code,
|
| - cookies, data);
|
| - }
|
| +// CloudPrintURLFetcher::Delegate implementation.
|
| +CloudPrintURLFetcher::ResponseAction
|
| +CloudPrintProxyBackend::Core::HandleJSONData(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded) {
|
| + DCHECK(next_response_handler_);
|
| + return (this->*next_response_handler_)(source, url, json_data, succeeded);
|
| }
|
|
|
| +void CloudPrintProxyBackend::Core::OnRequestAuthError() {
|
| + OnAuthError();
|
| +}
|
| +
|
| void CloudPrintProxyBackend::Core::NotifyPrinterListAvailable(
|
| const printing::PrinterList& printer_list) {
|
| DCHECK(MessageLoop::current() == backend_->frontend_loop_);
|
| @@ -560,53 +589,44 @@
|
| backend_->frontend_->OnAuthenticationFailed();
|
| }
|
|
|
| -void CloudPrintProxyBackend::Core::HandlePrinterListResponse(
|
| - const URLFetcher* source, const GURL& url, const URLRequestStatus& status,
|
| - int response_code, const ResponseCookies& cookies,
|
| - const std::string& data) {
|
| +CloudPrintURLFetcher::ResponseAction
|
| +CloudPrintProxyBackend::Core::HandlePrinterListResponse(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded) {
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| - bool succeeded = false;
|
| - if (status.is_success() && response_code == 200) {
|
| - server_error_count_ = 0;
|
| - // Parse the response JSON for the list of printers already registered.
|
| - DictionaryValue* response_dict_temp = NULL;
|
| - CloudPrintHelpers::ParseResponseJSON(data, &succeeded,
|
| - &response_dict_temp);
|
| - scoped_ptr<DictionaryValue> response_dict;
|
| - response_dict.reset(response_dict_temp);
|
| - if (succeeded) {
|
| - DCHECK(response_dict.get());
|
| - ListValue* printer_list = NULL;
|
| - response_dict->GetList(kPrinterListValue, &printer_list);
|
| - // There may be no "printers" value in the JSON
|
| - if (printer_list) {
|
| - for (size_t index = 0; index < printer_list->GetSize(); index++) {
|
| - DictionaryValue* printer_data = NULL;
|
| - if (printer_list->GetDictionary(index, &printer_data)) {
|
| - std::string printer_name;
|
| - printer_data->GetString(kNameValue, &printer_name);
|
| - RemovePrinterFromList(printer_name);
|
| - InitJobHandlerForPrinter(printer_data);
|
| - } else {
|
| - NOTREACHED();
|
| - }
|
| - }
|
| - }
|
| - MessageLoop::current()->DeleteSoon(FROM_HERE, request_.release());
|
| - if (!printer_list_.empty()) {
|
| - // Let the frontend know that we have a list of printers available.
|
| - backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
|
| - &Core::NotifyPrinterListAvailable, printer_list_));
|
| + if (!succeeded) {
|
| + NOTREACHED();
|
| + return CloudPrintURLFetcher::RETRY_REQUEST;
|
| + }
|
| + ListValue* printer_list = NULL;
|
| + json_data->GetList(kPrinterListValue, &printer_list);
|
| + // There may be no "printers" value in the JSON
|
| + if (printer_list) {
|
| + for (size_t index = 0; index < printer_list->GetSize(); index++) {
|
| + DictionaryValue* printer_data = NULL;
|
| + if (printer_list->GetDictionary(index, &printer_data)) {
|
| + std::string printer_name;
|
| + printer_data->GetString(kNameValue, &printer_name);
|
| + RemovePrinterFromList(printer_name);
|
| + InitJobHandlerForPrinter(printer_data);
|
| } else {
|
| - // No more work to be done here.
|
| - MessageLoop::current()->PostTask(
|
| - FROM_HERE, NewRunnableMethod(this, &Core::EndRegistration));
|
| + NOTREACHED();
|
| }
|
| }
|
| }
|
| -
|
| - if (!succeeded)
|
| - HandleServerError(NewRunnableMethod(this, &Core::GetRegisteredPrinters));
|
| + request_ = NULL;
|
| + if (!printer_list_.empty()) {
|
| + // Let the frontend know that we have a list of printers available.
|
| + backend_->frontend_loop_->PostTask(FROM_HERE, NewRunnableMethod(this,
|
| + &Core::NotifyPrinterListAvailable, printer_list_));
|
| + } else {
|
| + // No more work to be done here.
|
| + MessageLoop::current()->PostTask(
|
| + FROM_HERE, NewRunnableMethod(this, &Core::EndRegistration));
|
| + }
|
| + return CloudPrintURLFetcher::STOP_PROCESSING;
|
| }
|
|
|
| void CloudPrintProxyBackend::Core::InitJobHandlerForPrinter(
|
| @@ -655,48 +675,32 @@
|
| }
|
| }
|
|
|
| -void CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse(
|
| - const URLFetcher* source, const GURL& url, const URLRequestStatus& status,
|
| - int response_code, const ResponseCookies& cookies,
|
| - const std::string& data) {
|
| +CloudPrintURLFetcher::ResponseAction
|
| +CloudPrintProxyBackend::Core::HandleRegisterPrinterResponse(
|
| + const URLFetcher* source,
|
| + const GURL& url,
|
| + DictionaryValue* json_data,
|
| + bool succeeded) {
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| - VLOG(1) << "CP_PROXY: Handle register printer response, code: "
|
| - << response_code;
|
| - Task* next_task =
|
| - NewRunnableMethod(this,
|
| - &CloudPrintProxyBackend::Core::RegisterNextPrinter);
|
| - if (status.is_success() && (response_code == 200)) {
|
| - bool succeeded = false;
|
| - DictionaryValue* response_dict = NULL;
|
| - CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict);
|
| - if (succeeded) {
|
| - DCHECK(response_dict);
|
| - ListValue* printer_list = NULL;
|
| - response_dict->GetList(kPrinterListValue, &printer_list);
|
| - // There should be a "printers" value in the JSON
|
| - DCHECK(printer_list);
|
| - if (printer_list) {
|
| - DictionaryValue* printer_data = NULL;
|
| - if (printer_list->GetDictionary(0, &printer_data))
|
| - InitJobHandlerForPrinter(printer_data);
|
| - }
|
| + if (succeeded) {
|
| + ListValue* printer_list = NULL;
|
| + json_data->GetList(kPrinterListValue, &printer_list);
|
| + // There should be a "printers" value in the JSON
|
| + DCHECK(printer_list);
|
| + if (printer_list) {
|
| + DictionaryValue* printer_data = NULL;
|
| + if (printer_list->GetDictionary(0, &printer_data))
|
| + InitJobHandlerForPrinter(printer_data);
|
| }
|
| - server_error_count_ = 0;
|
| - next_upload_index_++;
|
| - MessageLoop::current()->PostTask(FROM_HERE, next_task);
|
| - } else {
|
| - HandleServerError(next_task);
|
| }
|
| + next_upload_index_++;
|
| + MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + NewRunnableMethod(this,
|
| + &CloudPrintProxyBackend::Core::RegisterNextPrinter));
|
| + return CloudPrintURLFetcher::STOP_PROCESSING;
|
| }
|
|
|
| -void CloudPrintProxyBackend::Core::HandleServerError(Task* task_to_retry) {
|
| - DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
| - VLOG(1) << "CP_PROXY: Server error.";
|
| - CloudPrintHelpers::HandleServerError(
|
| - &server_error_count_, -1, kMaxRetryInterval, kBaseRetryInterval,
|
| - task_to_retry, NULL);
|
| -}
|
| -
|
| bool CloudPrintProxyBackend::Core::RemovePrinterFromList(
|
| const std::string& printer_name) {
|
| DCHECK(MessageLoop::current() == backend_->core_thread_.message_loop());
|
|
|