OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/service/cloud_print/cloud_print_url_fetcher.h" |
| 6 |
| 7 #include "base/values.h" |
| 8 #include "chrome/common/net/http_return.h" |
| 9 #include "chrome/common/net/url_fetcher_protect.h" |
| 10 #include "chrome/service/cloud_print/cloud_print_consts.h" |
| 11 #include "chrome/service/cloud_print/cloud_print_helpers.h" |
| 12 #include "chrome/service/net/service_url_request_context.h" |
| 13 #include "googleurl/src/gurl.h" |
| 14 #include "net/url_request/url_request_status.h" |
| 15 |
| 16 CloudPrintURLFetcher::CloudPrintURLFetcher() |
| 17 : protect_entry_(NULL), num_retries_(0) { |
| 18 } |
| 19 |
| 20 void CloudPrintURLFetcher::StartGetRequest(const GURL& url, |
| 21 Delegate* delegate, |
| 22 const std::string& auth_token, |
| 23 const std::string& retry_policy) { |
| 24 StartRequestHelper(url, URLFetcher::GET, delegate, auth_token, retry_policy, |
| 25 std::string(), std::string()); |
| 26 } |
| 27 |
| 28 void CloudPrintURLFetcher::StartPostRequest( |
| 29 const GURL& url, |
| 30 Delegate* delegate, |
| 31 const std::string& auth_token, |
| 32 const std::string& retry_policy, |
| 33 const std::string& post_data_mime_type, |
| 34 const std::string& post_data) { |
| 35 StartRequestHelper(url, URLFetcher::POST, delegate, auth_token, retry_policy, |
| 36 post_data_mime_type, post_data); |
| 37 } |
| 38 |
| 39 // URLFetcher::Delegate implementation. |
| 40 void CloudPrintURLFetcher::OnURLFetchComplete( |
| 41 const URLFetcher* source, |
| 42 const GURL& url, |
| 43 const URLRequestStatus& status, |
| 44 int response_code, |
| 45 const ResponseCookies& cookies, |
| 46 const std::string& data) { |
| 47 VLOG(1) << "CP_PROXY: OnURLFetchComplete, url: " << url |
| 48 << ", response code: " << response_code; |
| 49 // Make sure we stay alive through the body of this function. |
| 50 scoped_refptr<CloudPrintURLFetcher> keep_alive(this); |
| 51 ResponseAction action = delegate_->HandleRawResponse(source, |
| 52 url, |
| 53 status, |
| 54 response_code, |
| 55 cookies, |
| 56 data); |
| 57 if (action == CONTINUE_PROCESSING) { |
| 58 // If there was an auth error, we are done. |
| 59 if (RC_FORBIDDEN == response_code) { |
| 60 delegate_->OnRequestAuthError(); |
| 61 return; |
| 62 } |
| 63 // We need to retry on all network errors. |
| 64 if (!status.is_success() || (response_code != 200)) |
| 65 action = RETRY_REQUEST; |
| 66 else |
| 67 action = delegate_->HandleRawData(source, url, data); |
| 68 |
| 69 if (action == CONTINUE_PROCESSING) { |
| 70 // If the delegate is not interested in handling the raw response data, |
| 71 // we assume that a JSON response is expected. If we do not get a JSON |
| 72 // response, we will retry (to handle the case where we got redirected |
| 73 // to a non-cloudprint-server URL eg. for authentication). |
| 74 bool succeeded = false; |
| 75 DictionaryValue* response_dict = NULL; |
| 76 CloudPrintHelpers::ParseResponseJSON(data, &succeeded, &response_dict); |
| 77 if (response_dict) |
| 78 action = delegate_->HandleJSONData(source, |
| 79 url, |
| 80 response_dict, |
| 81 succeeded); |
| 82 else |
| 83 action = RETRY_REQUEST; |
| 84 } |
| 85 } |
| 86 // Retry the request if needed. |
| 87 if (action == RETRY_REQUEST) { |
| 88 int64 back_off_time = |
| 89 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::FAILURE); |
| 90 ++num_retries_; |
| 91 int max_retries = protect_entry_->max_retries(); |
| 92 if ((-1 != max_retries) && (num_retries_ > max_retries)) { |
| 93 // Retry limit reached. Give up. |
| 94 delegate_->OnRequestGiveUp(); |
| 95 } else { |
| 96 // Either no retry limit specified or retry limit has not yet been |
| 97 // reached. Try again. |
| 98 MessageLoop::current()->PostDelayedTask( |
| 99 FROM_HERE, |
| 100 NewRunnableMethod(this, &CloudPrintURLFetcher::StartRequestNow), |
| 101 back_off_time); |
| 102 } |
| 103 } else { |
| 104 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SUCCESS); |
| 105 } |
| 106 } |
| 107 |
| 108 void CloudPrintURLFetcher::StartRequestHelper( |
| 109 const GURL& url, |
| 110 URLFetcher::RequestType request_type, |
| 111 Delegate* delegate, |
| 112 const std::string& auth_token, |
| 113 const std::string& retry_policy, |
| 114 const std::string& post_data_mime_type, |
| 115 const std::string& post_data) { |
| 116 DCHECK(delegate); |
| 117 request_.reset(new URLFetcher(url, request_type, this)); |
| 118 request_->set_request_context(GetRequestContextGetter()); |
| 119 // Since we implement our own retry logic, disable the retry in URLFetcher. |
| 120 request_->set_automatically_retry_on_5xx(false); |
| 121 delegate_ = delegate; |
| 122 std::string headers = "Authorization: GoogleLogin auth="; |
| 123 headers += auth_token; |
| 124 headers += "\r\n"; |
| 125 headers += kChromeCloudPrintProxyHeader; |
| 126 request_->set_extra_request_headers(headers); |
| 127 if (request_type == URLFetcher::POST) { |
| 128 request_->set_upload_data(post_data_mime_type, post_data); |
| 129 } |
| 130 // Initialize the retry policy for this request. |
| 131 protect_entry_ = |
| 132 URLFetcherProtectManager::GetInstance()->Register(retry_policy); |
| 133 MessageLoop::current()->PostDelayedTask( |
| 134 FROM_HERE, |
| 135 NewRunnableMethod(this, &CloudPrintURLFetcher::StartRequestNow), |
| 136 protect_entry_->UpdateBackoff(URLFetcherProtectEntry::SEND)); |
| 137 } |
| 138 |
| 139 void CloudPrintURLFetcher::StartRequestNow() { |
| 140 request_->Start(); |
| 141 } |
| 142 |
| 143 URLRequestContextGetter* CloudPrintURLFetcher::GetRequestContextGetter() { |
| 144 return new ServiceURLRequestContextGetter(); |
| 145 } |
| 146 |
OLD | NEW |