1 // Copyright 2014 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/browser/local_discovery/gcd_api_flow_impl.h" 6 7 #include "base/json/json_reader.h" 8 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/stringprintf.h" 10 #include "base/values.h" 11 #include "chrome/browser/local_discovery/gcd_constants.h" 12 #include "chrome/common/cloud_print/cloud_print_constants.h" 13 #include "components/cloud_devices/common/cloud_devices_urls.h" 14 #include "google_apis/gaia/google_service_auth_error.h" 15 #include "net/base/load_flags.h" 16 #include "net/base/url_util.h" 17 #include "net/http/http_status_code.h" 18 #include "net/url_request/url_request_status.h" 19 20 namespace local_discovery { 21 22 GCDApiFlowImpl::GCDApiFlowImpl(net::URLRequestContextGetter* request_context, 23 OAuth2TokenService* token_service, 24 const std::string& account_id) 25 : OAuth2TokenService::Consumer("cloud_print"), 26 request_context_(request_context), 27 token_service_(token_service), 28 account_id_(account_id) { 29 } 30 31 GCDApiFlowImpl::~GCDApiFlowImpl() { 32 } 33 34 void GCDApiFlowImpl::Start(scoped_ptr<Request> request) { 35 request_ = request.Pass(); 36 OAuth2TokenService::ScopeSet oauth_scopes; 37 oauth_scopes.insert(request_->GetOAuthScope()); 38 oauth_request_ = 39 token_service_->StartRequest(account_id_, oauth_scopes, this); 40 } 41 42 void GCDApiFlowImpl::OnGetTokenSuccess( 43 const OAuth2TokenService::Request* request, 44 const std::string& access_token, 45 const base::Time& expiration_time) { 46 CreateRequest(request_->GetURL()); 47 48 std::string authorization_header = 49 base::StringPrintf(kCloudPrintOAuthHeaderFormat, access_token.c_str()); 50 51 url_fetcher_->AddExtraRequestHeader(authorization_header); 52 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES | 53 net::LOAD_DO_NOT_SEND_COOKIES); 54 url_fetcher_->Start(); 55 } 56 57 void GCDApiFlowImpl::OnGetTokenFailure( 58 const OAuth2TokenService::Request* request, 59 const GoogleServiceAuthError& error) { 60 request_->OnGCDAPIFlowError(ERROR_TOKEN); 61 } 62 63 void GCDApiFlowImpl::CreateRequest(const GURL& url) { 64 net::URLFetcher::RequestType request_type = request_->GetRequestType(); 65 66 url_fetcher_.reset(net::URLFetcher::Create(url, request_type, this)); 67 68 if (request_type != net::URLFetcher::GET) { 69 std::string upload_type; 70 std::string upload_data; 71 request_->GetUploadData(&upload_type, &upload_data); 72 url_fetcher_->SetUploadData(upload_type, upload_data); 73 } 74 75 url_fetcher_->SetRequestContext(request_context_.get()); 76 77 std::vector<std::string> extra_headers = request_->GetExtraRequestHeaders(); 78 for (size_t i = 0; i < extra_headers.size(); ++i) 79 url_fetcher_->AddExtraRequestHeader(extra_headers[i]); 80 } 81 82 void GCDApiFlowImpl::OnURLFetchComplete(const net::URLFetcher* source) { 83 // TODO(noamsml): Error logging. 84 85 // TODO(noamsml): Extract this and PrivetURLFetcher::OnURLFetchComplete into 86 // one helper method. 87 std::string response_str; 88 89 if (source->GetStatus().status() != net::URLRequestStatus::SUCCESS || 90 !source->GetResponseAsString(&response_str)) { 91 request_->OnGCDAPIFlowError(ERROR_NETWORK); 92 return; 93 } 94 95 if (source->GetResponseCode() != net::HTTP_OK) { 96 request_->OnGCDAPIFlowError(ERROR_HTTP_CODE); 97 return; 98 } 99 100 base::JSONReader reader; 101 scoped_ptr<const base::Value> value(reader.Read(response_str)); 102 const base::DictionaryValue* dictionary_value = NULL; 103 104 if (!value || !value->GetAsDictionary(&dictionary_value)) { 105 request_->OnGCDAPIFlowError(ERROR_MALFORMED_RESPONSE); 106 return; 107 } 108 109 request_->OnGCDAPIFlowComplete(*dictionary_value); 110 } 111 112 } // namespace local_discovery 113