Home | History | Annotate | Download | only in local_discovery
      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