permission_request_creator_apiary.cc revision 6e8cce623b6e4fe0c9e4af605d675dd9d0338c38
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/supervised_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 29using net::URLFetcher; 30 31const int kNumRetries = 1; 32const char kIdKey[] = "id"; 33const char kNamespace[] = "CHROME"; 34const char kState[] = "PENDING"; 35 36static const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s"; 37 38PermissionRequestCreatorApiary::PermissionRequestCreatorApiary( 39 OAuth2TokenService* oauth2_token_service, 40 scoped_ptr<SupervisedUserSigninManagerWrapper> 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 48PermissionRequestCreatorApiary::~PermissionRequestCreatorApiary() {} 49 50// static 51scoped_ptr<PermissionRequestCreator> 52PermissionRequestCreatorApiary::CreateWithProfile(Profile* profile) { 53 ProfileOAuth2TokenService* token_service = 54 ProfileOAuth2TokenServiceFactory::GetForProfile(profile); 55 SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile); 56 scoped_ptr<SupervisedUserSigninManagerWrapper> signin_wrapper( 57 new SupervisedUserSigninManagerWrapper(profile, signin)); 58 scoped_ptr<PermissionRequestCreator> creator( 59 new PermissionRequestCreatorApiary( 60 token_service, signin_wrapper.Pass(), profile->GetRequestContext())); 61 return creator.Pass(); 62} 63 64void 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 72void PermissionRequestCreatorApiary::StartFetching() { 73 OAuth2TokenService::ScopeSet scopes; 74 if (CommandLine::ForCurrentProcess()->HasSwitch( 75 switches::kPermissionRequestApiScope)) { 76 scopes.insert(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 77 switches::kPermissionRequestApiScope)); 78 } else { 79 scopes.insert(signin_wrapper_->GetSyncScopeToUse()); 80 } 81 access_token_request_ = oauth2_token_service_->StartRequest( 82 signin_wrapper_->GetAccountIdToUse(), scopes, this); 83} 84 85void PermissionRequestCreatorApiary::OnGetTokenSuccess( 86 const OAuth2TokenService::Request* request, 87 const std::string& access_token, 88 const base::Time& expiration_time) { 89 DCHECK_EQ(access_token_request_.get(), request); 90 access_token_ = access_token; 91 GURL url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII( 92 switches::kPermissionRequestApiUrl)); 93 const int id = 0; 94 95 url_fetcher_.reset(URLFetcher::Create(id, url, URLFetcher::POST, this)); 96 97 url_fetcher_->SetRequestContext(context_); 98 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 99 net::LOAD_DO_NOT_SAVE_COOKIES); 100 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries); 101 url_fetcher_->AddExtraRequestHeader( 102 base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str())); 103 104 base::DictionaryValue dict; 105 dict.SetStringWithoutPathExpansion("namespace", kNamespace); 106 dict.SetStringWithoutPathExpansion("objectRef", url_requested_); 107 dict.SetStringWithoutPathExpansion("state", kState); 108 std::string body; 109 base::JSONWriter::Write(&dict, &body); 110 url_fetcher_->SetUploadData("application/json", body); 111 112 url_fetcher_->Start(); 113} 114 115void PermissionRequestCreatorApiary::OnGetTokenFailure( 116 const OAuth2TokenService::Request* request, 117 const GoogleServiceAuthError& error) { 118 DCHECK_EQ(access_token_request_.get(), request); 119 callback_.Run(); 120 callback_.Reset(); 121} 122 123void PermissionRequestCreatorApiary::OnURLFetchComplete( 124 const URLFetcher* source) { 125 const net::URLRequestStatus& status = source->GetStatus(); 126 if (!status.is_success()) { 127 DispatchNetworkError(status.error()); 128 return; 129 } 130 131 int response_code = source->GetResponseCode(); 132 if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) { 133 access_token_expired_ = true; 134 OAuth2TokenService::ScopeSet scopes; 135 scopes.insert(signin_wrapper_->GetSyncScopeToUse()); 136 oauth2_token_service_->InvalidateToken( 137 signin_wrapper_->GetAccountIdToUse(), scopes, access_token_); 138 StartFetching(); 139 return; 140 } 141 142 if (response_code != net::HTTP_OK) { 143 DLOG(WARNING) << "HTTP error " << response_code; 144 DispatchGoogleServiceAuthError( 145 GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED)); 146 return; 147 } 148 149 std::string response_body; 150 source->GetResponseAsString(&response_body); 151 scoped_ptr<base::Value> value(base::JSONReader::Read(response_body)); 152 base::DictionaryValue* dict = NULL; 153 if (!value || !value->GetAsDictionary(&dict)) { 154 DispatchNetworkError(net::ERR_INVALID_RESPONSE); 155 return; 156 } 157 std::string id; 158 if (!dict->GetString(kIdKey, &id)) { 159 DispatchNetworkError(net::ERR_INVALID_RESPONSE); 160 return; 161 } 162 callback_.Run(); 163 callback_.Reset(); 164} 165 166void PermissionRequestCreatorApiary::DispatchNetworkError(int error_code) { 167 DispatchGoogleServiceAuthError( 168 GoogleServiceAuthError::FromConnectionError(error_code)); 169} 170 171void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError( 172 const GoogleServiceAuthError& error) { 173 callback_.Run(); 174 callback_.Reset(); 175} 176