Home | History | Annotate | Download | only in supervised_user
      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/supervised_user/permission_request_creator_apiary.h"
      6 
      7 #include "base/callback.h"
      8 #include "base/command_line.h"
      9 #include "base/json/json_reader.h"
     10 #include "base/json/json_writer.h"
     11 #include "base/logging.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "base/values.h"
     14 #include "chrome/browser/profiles/profile.h"
     15 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
     16 #include "chrome/browser/signin/signin_manager_factory.h"
     17 #include "chrome/browser/sync/managed_user_signin_manager_wrapper.h"
     18 #include "chrome/common/chrome_switches.h"
     19 #include "components/signin/core/browser/profile_oauth2_token_service.h"
     20 #include "components/signin/core/browser/signin_manager.h"
     21 #include "components/signin/core/browser/signin_manager_base.h"
     22 #include "google_apis/gaia/google_service_auth_error.h"
     23 #include "net/base/load_flags.h"
     24 #include "net/base/net_errors.h"
     25 #include "net/http/http_status_code.h"
     26 #include "net/url_request/url_fetcher.h"
     27 #include "net/url_request/url_request_status.h"
     28 
     29 using net::URLFetcher;
     30 
     31 const int kNumRetries = 1;
     32 const char kIdKey[] = "id";
     33 const char kNamespace[] = "CHROME";
     34 const char kState[] = "PENDING";
     35 
     36 static const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
     37 
     38 PermissionRequestCreatorApiary::PermissionRequestCreatorApiary(
     39     OAuth2TokenService* oauth2_token_service,
     40     scoped_ptr<ManagedUserSigninManagerWrapper> signin_wrapper,
     41     net::URLRequestContextGetter* context)
     42     : OAuth2TokenService::Consumer("permissions_creator"),
     43       oauth2_token_service_(oauth2_token_service),
     44       signin_wrapper_(signin_wrapper.Pass()),
     45       context_(context),
     46       access_token_expired_(false) {}
     47 
     48 PermissionRequestCreatorApiary::~PermissionRequestCreatorApiary() {}
     49 
     50 // static
     51 scoped_ptr<PermissionRequestCreator>
     52 PermissionRequestCreatorApiary::CreateWithProfile(Profile* profile) {
     53   ProfileOAuth2TokenService* token_service =
     54       ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
     55   SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile);
     56   scoped_ptr<ManagedUserSigninManagerWrapper> signin_wrapper(
     57       new ManagedUserSigninManagerWrapper(profile, signin));
     58   scoped_ptr<PermissionRequestCreator> creator(
     59       new PermissionRequestCreatorApiary(
     60           token_service, signin_wrapper.Pass(), profile->GetRequestContext()));
     61   return creator.Pass();
     62 }
     63 
     64 void PermissionRequestCreatorApiary::CreatePermissionRequest(
     65     const std::string& url_requested,
     66     const base::Closure& callback) {
     67   url_requested_ = url_requested;
     68   callback_ = callback;
     69   StartFetching();
     70 }
     71 
     72 void PermissionRequestCreatorApiary::StartFetching() {
     73   OAuth2TokenService::ScopeSet scopes;
     74   scopes.insert(signin_wrapper_->GetSyncScopeToUse());
     75   access_token_request_ = oauth2_token_service_->StartRequest(
     76       signin_wrapper_->GetAccountIdToUse(), scopes, this);
     77 }
     78 
     79 void PermissionRequestCreatorApiary::OnGetTokenSuccess(
     80     const OAuth2TokenService::Request* request,
     81     const std::string& access_token,
     82     const base::Time& expiration_time) {
     83   DCHECK_EQ(access_token_request_.get(), request);
     84   access_token_ = access_token;
     85   GURL url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
     86       switches::kPermissionRequestApiUrl));
     87   const int id = 0;
     88 
     89   url_fetcher_.reset(URLFetcher::Create(id, url, URLFetcher::POST, this));
     90 
     91   url_fetcher_->SetRequestContext(context_);
     92   url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
     93                              net::LOAD_DO_NOT_SAVE_COOKIES);
     94   url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
     95   url_fetcher_->AddExtraRequestHeader(
     96       base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
     97 
     98   base::DictionaryValue dict;
     99   dict.SetStringWithoutPathExpansion("namespace", kNamespace);
    100   dict.SetStringWithoutPathExpansion("objectRef", url_requested_);
    101   dict.SetStringWithoutPathExpansion("state", kState);
    102   std::string body;
    103   base::JSONWriter::Write(&dict, &body);
    104   url_fetcher_->SetUploadData("application/json", body);
    105 
    106   url_fetcher_->Start();
    107 }
    108 
    109 void PermissionRequestCreatorApiary::OnGetTokenFailure(
    110     const OAuth2TokenService::Request* request,
    111     const GoogleServiceAuthError& error) {
    112   DCHECK_EQ(access_token_request_.get(), request);
    113   callback_.Run();
    114   callback_.Reset();
    115 }
    116 
    117 void PermissionRequestCreatorApiary::OnURLFetchComplete(
    118     const URLFetcher* source) {
    119   const net::URLRequestStatus& status = source->GetStatus();
    120   if (!status.is_success()) {
    121     DispatchNetworkError(status.error());
    122     return;
    123   }
    124 
    125   int response_code = source->GetResponseCode();
    126   if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
    127     access_token_expired_ = true;
    128     OAuth2TokenService::ScopeSet scopes;
    129     scopes.insert(signin_wrapper_->GetSyncScopeToUse());
    130     oauth2_token_service_->InvalidateToken(
    131         signin_wrapper_->GetAccountIdToUse(), scopes, access_token_);
    132     StartFetching();
    133     return;
    134   }
    135 
    136   if (response_code != net::HTTP_OK) {
    137     DLOG(WARNING) << "HTTP error " << response_code;
    138     DispatchGoogleServiceAuthError(
    139         GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
    140     return;
    141   }
    142 
    143   std::string response_body;
    144   source->GetResponseAsString(&response_body);
    145   scoped_ptr<base::Value> value(base::JSONReader::Read(response_body));
    146   base::DictionaryValue* dict = NULL;
    147   if (!value || !value->GetAsDictionary(&dict)) {
    148     DispatchNetworkError(net::ERR_INVALID_RESPONSE);
    149     return;
    150   }
    151   std::string id;
    152   if (!dict->GetString(kIdKey, &id)) {
    153     DispatchNetworkError(net::ERR_INVALID_RESPONSE);
    154     return;
    155   }
    156   callback_.Run();
    157   callback_.Reset();
    158 }
    159 
    160 void PermissionRequestCreatorApiary::DispatchNetworkError(int error_code) {
    161   DispatchGoogleServiceAuthError(
    162       GoogleServiceAuthError::FromConnectionError(error_code));
    163 }
    164 
    165 void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError(
    166     const GoogleServiceAuthError& error) {
    167   callback_.Run();
    168   callback_.Reset();
    169 }
    170