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.
5 #include "chrome/browser/supervised_user/permission_request_creator_apiary.h"
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"
29 using net::URLFetcher
;
31 const int kNumRetries
= 1;
32 const char kIdKey
[] = "id";
33 const char kNamespace
[] = "CHROME";
34 const char kState
[] = "PENDING";
36 static const char kAuthorizationHeaderFormat
[] = "Authorization: Bearer %s";
38 PermissionRequestCreatorApiary::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()),
46 access_token_expired_(false) {}
48 PermissionRequestCreatorApiary::~PermissionRequestCreatorApiary() {}
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
<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();
64 void PermissionRequestCreatorApiary::CreatePermissionRequest(
65 const GURL
& url_requested
,
66 const base::Closure
& callback
) {
67 url_requested_
= url_requested
;
72 std::string
PermissionRequestCreatorApiary::GetApiScopeToUse() const {
73 if (CommandLine::ForCurrentProcess()->HasSwitch(
74 switches::kPermissionRequestApiScope
)) {
75 return CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
76 switches::kPermissionRequestApiScope
);
78 return signin_wrapper_
->GetSyncScopeToUse();
82 void PermissionRequestCreatorApiary::StartFetching() {
83 OAuth2TokenService::ScopeSet scopes
;
84 scopes
.insert(GetApiScopeToUse());
85 access_token_request_
= oauth2_token_service_
->StartRequest(
86 signin_wrapper_
->GetAccountIdToUse(), scopes
, this);
89 void PermissionRequestCreatorApiary::OnGetTokenSuccess(
90 const OAuth2TokenService::Request
* request
,
91 const std::string
& access_token
,
92 const base::Time
& expiration_time
) {
93 DCHECK_EQ(access_token_request_
.get(), request
);
94 access_token_
= access_token
;
95 GURL
url(CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
96 switches::kPermissionRequestApiUrl
));
99 url_fetcher_
.reset(URLFetcher::Create(id
, url
, URLFetcher::POST
, this));
101 url_fetcher_
->SetRequestContext(context_
);
102 url_fetcher_
->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES
|
103 net::LOAD_DO_NOT_SAVE_COOKIES
);
104 url_fetcher_
->SetAutomaticallyRetryOnNetworkChanges(kNumRetries
);
105 url_fetcher_
->AddExtraRequestHeader(
106 base::StringPrintf(kAuthorizationHeaderFormat
, access_token
.c_str()));
108 base::DictionaryValue dict
;
109 dict
.SetStringWithoutPathExpansion("namespace", kNamespace
);
110 dict
.SetStringWithoutPathExpansion("objectRef", url_requested_
.spec());
111 dict
.SetStringWithoutPathExpansion("state", kState
);
113 base::JSONWriter::Write(&dict
, &body
);
114 url_fetcher_
->SetUploadData("application/json", body
);
116 url_fetcher_
->Start();
119 void PermissionRequestCreatorApiary::OnGetTokenFailure(
120 const OAuth2TokenService::Request
* request
,
121 const GoogleServiceAuthError
& error
) {
122 DCHECK_EQ(access_token_request_
.get(), request
);
127 void PermissionRequestCreatorApiary::OnURLFetchComplete(
128 const URLFetcher
* source
) {
129 const net::URLRequestStatus
& status
= source
->GetStatus();
130 if (!status
.is_success()) {
131 DispatchNetworkError(status
.error());
135 int response_code
= source
->GetResponseCode();
136 if (response_code
== net::HTTP_UNAUTHORIZED
&& !access_token_expired_
) {
137 access_token_expired_
= true;
138 OAuth2TokenService::ScopeSet scopes
;
139 scopes
.insert(GetApiScopeToUse());
140 oauth2_token_service_
->InvalidateToken(
141 signin_wrapper_
->GetAccountIdToUse(), scopes
, access_token_
);
146 if (response_code
!= net::HTTP_OK
) {
147 DLOG(WARNING
) << "HTTP error " << response_code
;
148 DispatchGoogleServiceAuthError(
149 GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED
));
153 std::string response_body
;
154 source
->GetResponseAsString(&response_body
);
155 scoped_ptr
<base::Value
> value(base::JSONReader::Read(response_body
));
156 base::DictionaryValue
* dict
= NULL
;
157 if (!value
|| !value
->GetAsDictionary(&dict
)) {
158 DispatchNetworkError(net::ERR_INVALID_RESPONSE
);
162 if (!dict
->GetString(kIdKey
, &id
)) {
163 DispatchNetworkError(net::ERR_INVALID_RESPONSE
);
170 void PermissionRequestCreatorApiary::DispatchNetworkError(int error_code
) {
171 DispatchGoogleServiceAuthError(
172 GoogleServiceAuthError::FromConnectionError(error_code
));
175 void PermissionRequestCreatorApiary::DispatchGoogleServiceAuthError(
176 const GoogleServiceAuthError
& error
) {