Index: chrome/browser/chrome_to_mobile/common/cloud_print_request_impl.cc |
diff --git a/chrome/browser/chrome_to_mobile/common/cloud_print_request_impl.cc b/chrome/browser/chrome_to_mobile/common/cloud_print_request_impl.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..70dcd0884667620235813276a5869f5d594c1293 |
--- /dev/null |
+++ b/chrome/browser/chrome_to_mobile/common/cloud_print_request_impl.cc |
@@ -0,0 +1,280 @@ |
+// Copyright 2012 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "chrome/browser/chrome_to_mobile/common/cloud_print_request_impl.h" |
+ |
+#include "base/memory/ref_counted.h" |
+#include "chrome/browser/signin/oauth2_token_service.h" |
+#include "chrome/common/cloud_print/cloud_print_consts.h" |
+#include "chrome/common/cloud_print/cloud_print_helpers.h" |
+#include "google_apis/gaia/google_service_auth_error.h" |
+#include "google_apis/gaia/oauth2_access_token_consumer.h" |
+#include "googleurl/src/gurl.h" |
+#include "net/base/load_flags.h" |
+#include "net/http/http_response_headers.h" |
+#include "net/http/http_status_code.h" |
+#include "net/url_request/url_fetcher.h" |
+#include "net/url_request/url_request_context_getter.h" |
+#include "net/url_request/url_request_status.h" |
+ |
+namespace { |
+ |
+// The OAuth2 scope of the google cloud print server. |
+const char kCloudPrintOAuthScope[] = |
+ "https://www.googleapis.com/auth/cloudprint"; |
+ |
+// Returns a |GURL| built from |origin_url| and the information required by |
+// cloud print server for all the cloud print requests. |
+GURL PrepareURL(const GURL& origin_url, |
+ const std::string& cloud_print_client_id) { |
+ std::string query = "client=" + cloud_print_client_id; |
+ if (origin_url.has_query()) |
+ query = origin_url.query() + "&" + query; |
+ GURL::Replacements replacements; |
+ replacements.SetQueryStr(query); |
+ return origin_url.ReplaceComponents(replacements); |
+} |
+ |
+// Returns a |std::string| that includes the required request headers by cloud |
+// printer server, |oauth2_access_token| and |additional_headers|. |
+std::string GenerateCloudPrintFetcherHeaders( |
+ const std::string& oauth2_access_token, |
+ const std::string& additional_headers) { |
+ std::string headers; |
+ if (!oauth2_access_token.empty()) { |
+ headers = "Authorization: OAuth "; |
+ headers += oauth2_access_token; |
+ headers += "\r\n"; |
+ } |
+ headers += cloud_print::kChromeCloudPrintProxyHeader; |
+ |
+ if (!additional_headers.empty()) { |
+ headers += "\r\n"; |
+ headers += additional_headers; |
+ } |
+ return headers; |
+} |
+ |
+// Creates a |net::URLFetcher| at cloud print |url| with authentication |
+// |oauth2_access_token|. It is sent with the headers required by |
+// cloud print server and |additional_header|. The request is of type |
+// |request_type|; if it is a POST request, mime type and post data are given by |
+// |post_data_mime_type| and |post_data|. The request is sent in the request |
+// context obtained by |request_context_getter|. |
+net::URLFetcher* CreateCloudPrintURLFetcher( |
+ const GURL& url, |
+ const std::string& oauth2_access_token, |
+ const std::string& additional_headers, |
+ net::URLFetcher::RequestType request_type, |
+ std::string post_data_mime_type, |
+ std::string post_data, |
+ net::URLRequestContextGetter* request_context_getter, |
+ net::URLFetcherDelegate* delegate) { |
+ net::URLFetcher* request = net::URLFetcher::Create( |
+ 0, url, request_type, delegate); |
+ request->SetRequestContext(request_context_getter); |
+ request->SetExtraRequestHeaders(GenerateCloudPrintFetcherHeaders( |
+ oauth2_access_token, additional_headers)); |
+ request->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
+ net::LOAD_DO_NOT_SAVE_COOKIES); |
+ if (request_type == net::URLFetcher::POST) |
+ request->SetUploadData(post_data_mime_type, post_data); |
+ return request; |
+} |
+ |
+} // namespace |
+ |
+namespace chrome_to_mobile { |
+ |
+// Class that handles cloud print requests authenticated with oauth2 refresh |
+// tokens. It calls back its owner when the request completes; it can be deleted |
+// at any time and once it is deleted before the request completes, its owner |
+// will not be called back. |
+class CloudPrintRequestImpl::Fetcher : public OAuth2AccessTokenConsumer, |
+ public net::URLFetcherDelegate { |
+ public: |
+ Fetcher(const GURL& url, |
+ const std::string& additional_headers, |
+ const net::URLFetcher::RequestType& request_type, |
+ const std::string& post_data_mime_type, |
+ const std::string& post_data, |
+ net::URLRequestContextGetter* request_context_getter, |
+ CloudPrintRequestImpl* owner); |
+ ~Fetcher(); |
+ |
+ // Starts the request authenticated by |oauth2_refrech_token| |
+ // This method starts with fetching an oauth2 access token using |
+ // |oauth2_token_service| with |oauth2_refresh_token|. If it fails to |
+ // obtain an oauth2 access token, |owner_| will be called back; otherwise it |
+ // continues to send request to cloud printer server and |owner_| will be |
+ // called back when the request completes. |
+ void Start(OAuth2TokenService* oauth2_token_service); |
+ |
+ protected: |
+ // |OAuth2AccessTokenConsumer| |
+ virtual void OnGetTokenSuccess(const std::string& access_token, |
+ const base::Time& expiration_date) OVERRIDE; |
+ virtual void OnGetTokenFailure(const GoogleServiceAuthError& error) OVERRIDE; |
+ // |net::URLFetcherDelegate| |
+ virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; |
+ |
+ private: |
+ friend CloudPrintRequestImpl; |
+ |
+ const GURL url_; |
+ const std::string additional_headers_; |
+ const net::URLFetcher::RequestType request_type_; |
+ const std::string post_data_mime_type_; |
+ const std::string post_data_; |
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_; |
+ CloudPrintRequestImpl* const owner_; |
+ |
+ scoped_ptr<OAuth2TokenService::Request> oauth2_access_token_request_; |
+ scoped_ptr<net::URLFetcher> cloud_print_request_; |
+}; |
+ |
+CloudPrintRequestImpl::Fetcher::Fetcher( |
+ const GURL& url, |
+ const std::string& additional_headers, |
+ const net::URLFetcher::RequestType& request_type, |
+ const std::string& post_data_mime_type, |
+ const std::string& post_data, |
+ net::URLRequestContextGetter* request_context_getter, |
+ CloudPrintRequestImpl* owner) |
+ : url_(url), |
+ additional_headers_(additional_headers), |
+ request_type_(request_type), |
+ post_data_mime_type_(post_data_mime_type), |
+ post_data_(post_data), |
+ request_context_getter_(request_context_getter), |
+ owner_(owner) { |
+} |
+ |
+CloudPrintRequestImpl::Fetcher::~Fetcher() { |
+} |
+ |
+void CloudPrintRequestImpl::Fetcher::Start( |
+ OAuth2TokenService* oauth2_token_service) { |
+ DCHECK(oauth2_token_service); |
+ std::vector<std::string> scopes(1, kCloudPrintOAuthScope); |
+ oauth2_access_token_request_.reset(oauth2_token_service->StartRequest( |
+ scopes, this)); |
+} |
+ |
+void CloudPrintRequestImpl::Fetcher::OnGetTokenSuccess( |
+ const std::string& oauth2_access_token, |
+ const base::Time& expiration_date) { |
+ oauth2_access_token_request_.reset(); |
+ cloud_print_request_.reset(CreateCloudPrintURLFetcher( |
+ url_, |
+ oauth2_access_token, |
+ additional_headers_, |
+ request_type_, |
+ post_data_mime_type_, |
+ post_data_, |
+ request_context_getter_, |
+ this)); |
+ cloud_print_request_->Start(); |
+} |
+ |
+void CloudPrintRequestImpl::Fetcher::OnGetTokenFailure( |
+ const GoogleServiceAuthError& error) { |
+ LOG(ERROR) << "Fail to fetch oauth token due to error: " << error.state(); |
+ oauth2_access_token_request_.reset(); |
+ owner_->OnGetOAuth2AccessTokenFailure(); |
+} |
+ |
+void CloudPrintRequestImpl::Fetcher::OnURLFetchComplete( |
+ const net::URLFetcher* source) { |
+ owner_->OnFetchComplete(source); |
+} |
+ |
+CloudPrintRequestImpl::CloudPrintRequestImpl( |
+ const GURL& url, |
+ const std::string& additional_headers, |
+ const net::URLFetcher::RequestType& request_type, |
+ const std::string& post_data_mime_type, |
+ const std::string& post_data, |
+ const Settings& settings, |
+ CloudPrintRequestImpl::Delegate* delegate) |
+ : settings_(settings), |
+ delegate_(delegate), |
+ fetcher_(new Fetcher(PrepareURL(url, settings.cloud_print_client_id), |
+ additional_headers, |
+ request_type, |
+ post_data_mime_type, |
+ post_data, |
+ settings.request_context_getter, |
+ this)), |
+ auth_token_failure_(false) { |
+} |
+ |
+CloudPrintRequestImpl::~CloudPrintRequestImpl() { |
+} |
+ |
+void CloudPrintRequestImpl::Start() { |
+ DCHECK(CalledOnValidThread()); |
+ fetcher_->Start(settings_.oauth2_token_service); |
+} |
+ |
+void CloudPrintRequestImpl::OnGetOAuth2AccessTokenFailure() { |
+ DCHECK(CalledOnValidThread()); |
+ auth_token_failure_ = true; |
+ delegate_->OnRequestComplete(this); |
+} |
+ |
+void CloudPrintRequestImpl::OnFetchComplete(const net::URLFetcher* fetcher) { |
+ DCHECK(CalledOnValidThread()); |
+ if (!fetcher->GetStatus().is_success() || fetcher->GetResponseCode() != 200) { |
+ std::string response_data; |
+ fetcher->GetResponseAsString(&response_data); |
+ LOG(ERROR) << "Fail to get cloud print response: " << response_data; |
+ } |
+ |
+ delegate_->OnRequestComplete(this); |
+} |
+ |
+std::string CloudPrintRequestImpl::GetResponseData(bool* success) const { |
+ DCHECK(CalledOnValidThread()); |
+ const net::URLFetcher* cloud_print_request = |
+ fetcher_->cloud_print_request_.get(); |
+ |
+ if (!cloud_print_request || |
+ !cloud_print_request->GetStatus().is_success() || |
+ cloud_print_request->GetResponseCode() != 200) { |
+ *success = false; |
+ return std::string(); |
+ } |
+ |
+ *success = true; |
+ std::string data; |
+ fetcher_->cloud_print_request_->GetResponseAsString(&data); |
+ return data; |
+} |
+ |
+std::string CloudPrintRequestImpl::GetResponseMimeType() const { |
+ if (!fetcher_->cloud_print_request_.get()) |
+ return std::string(); |
+ |
+ std::string mime_type; |
+ net::HttpResponseHeaders* headers = |
+ fetcher_->cloud_print_request_->GetResponseHeaders(); |
+ if (headers) |
+ headers->GetMimeType(&mime_type); |
+ return mime_type; |
+} |
+ |
+bool CloudPrintRequestImpl::HasOAuth2AccessTokenFailure() const { |
+ return auth_token_failure_; |
+} |
+ |
+bool CloudPrintRequestImpl::HasCloudPrintAuthError() const { |
+ if (!fetcher_->cloud_print_request_.get()) |
+ return false; |
+ return fetcher_->cloud_print_request_->GetResponseCode() == |
+ net::HTTP_FORBIDDEN; |
+} |
+ |
+} // namespace chrome_to_mobile |
+ |