Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(440)

Side by Side Diff: chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc

Issue 783083002: Add support for child accounts. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: remove CrOS for now Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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/child_accounts/family_info_fetcher.h"
6
7 #include "base/json/json_reader.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/values.h"
10 #include "net/base/load_flags.h"
11 #include "net/http/http_status_code.h"
12 #include "net/url_request/url_request_status.h"
13 #include "url/gurl.h"
14
15 const char kFamilyApiUrl[] = "https://www.googleapis.com/kidsmanagement/v1/";
16 const char kGetFamilyProfileApiSuffix[] = "families/mine?alt=json";
17 const char kGetFamilyMembersApiSuffix[] = "families/mine/members?alt=json";
18 const char kScope[] = "https://www.googleapis.com/auth/kid.family";
19 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
20 const int kNumRetries = 1;
21
22 const char kIdFamily[] = "family";
23 const char kIdFamilyId[] = "familyId";
24 const char kIdProfile[] = "profile";
25 const char kIdFamilyName[] = "name";
26 const char kIdMembers[] = "members";
27 const char kIdUserId[] = "userId";
28 const char kIdRole[] = "role";
29 const char kIdDisplayName[] = "displayName";
30 const char kIdEmail[] = "email";
31 const char kIdProfileUrl[] = "profileUrl";
32 const char kIdProfileImageUrl[] = "profileImageUrl";
33
34 // These correspond to enum FamilyInfoFetcher::FamilyMemberRole, in order.
35 const char* kFamilyMemberRoleStrings[] = {
36 "headOfHousehold",
37 "parent",
38 "member",
39 "child"
40 };
41
42 FamilyInfoFetcher::FamilyProfile::FamilyProfile() {
43 }
44
45 FamilyInfoFetcher::FamilyProfile::FamilyProfile(const std::string& id,
46 const std::string& name)
47 : id(id), name(name) {
48 }
49
50 FamilyInfoFetcher::FamilyProfile::~FamilyProfile() {
51 }
52
53 FamilyInfoFetcher::FamilyMember::FamilyMember() {
54 }
55
56 FamilyInfoFetcher::FamilyMember::FamilyMember(
57 const std::string& obfuscated_gaia_id,
58 FamilyMemberRole role,
59 const std::string& display_name,
60 const std::string& email,
61 const std::string& profile_url,
62 const std::string& profile_image_url)
63 : obfuscated_gaia_id(obfuscated_gaia_id),
64 role(role),
65 display_name(display_name),
66 email(email),
67 profile_url(profile_url),
68 profile_image_url(profile_image_url) {
69 }
70
71 FamilyInfoFetcher::FamilyMember::~FamilyMember() {
72 }
73
74 FamilyInfoFetcher::FamilyInfoFetcher(
75 Consumer* consumer,
76 const std::string& account_id,
77 OAuth2TokenService* token_service,
78 net::URLRequestContextGetter* request_context)
79 : OAuth2TokenService::Consumer("family_info_fetcher"),
80 consumer_(consumer),
81 account_id_(account_id),
82 token_service_(token_service),
83 request_context_(request_context),
84 request_type_(net::URLFetcher::GET),
85 access_token_expired_(false) {
86 }
87
88 FamilyInfoFetcher::~FamilyInfoFetcher() {
89 // Ensures O2TS observation is cleared when FamilyInfoFetcher is destructed
90 // before refresh token is available.
91 token_service_->RemoveObserver(this);
92 }
93
94 // static
95 std::string FamilyInfoFetcher::RoleToString(FamilyMemberRole role) {
96 return kFamilyMemberRoleStrings[role];
97 }
98
99 // static
100 bool FamilyInfoFetcher::StringToRole(
101 const std::string& str,
102 FamilyInfoFetcher::FamilyMemberRole* role) {
103 for (size_t i = 0; i < arraysize(kFamilyMemberRoleStrings); i++) {
104 if (str == kFamilyMemberRoleStrings[i]) {
105 *role = FamilyMemberRole(i);
106 return true;
107 }
108 }
109 return false;
110 }
111
112 void FamilyInfoFetcher::StartGetFamilyProfile() {
113 request_suffix_ = kGetFamilyProfileApiSuffix;
114 request_type_ = net::URLFetcher::GET;
115 StartFetching();
116 }
117
118 void FamilyInfoFetcher::StartGetFamilyMembers() {
119 request_suffix_ = kGetFamilyMembersApiSuffix;
120 request_type_ = net::URLFetcher::GET;
121 StartFetching();
122 }
123
124 void FamilyInfoFetcher::StartFetching() {
125 if (token_service_->RefreshTokenIsAvailable(account_id_)) {
126 StartFetchingAccessToken();
127 } else {
128 // Wait until we get a refresh token.
129 token_service_->AddObserver(this);
130 }
131 }
132
133 void FamilyInfoFetcher::StartFetchingAccessToken() {
134 OAuth2TokenService::ScopeSet scopes;
135 scopes.insert(kScope);
136 access_token_request_ = token_service_->StartRequest(
137 account_id_, scopes, this);
138 }
139
140 void FamilyInfoFetcher::OnRefreshTokenAvailable(
141 const std::string& account_id) {
142 // Wait until we get a refresh token for the requested account.
143 if (account_id != account_id_)
144 return;
145
146 token_service_->RemoveObserver(this);
147
148 StartFetchingAccessToken();
149 }
150
151 void FamilyInfoFetcher::OnRefreshTokensLoaded() {
152 token_service_->RemoveObserver(this);
153
154 // The PO2TS has loaded all tokens, but we didn't get one for the account we
155 // want. We probably won't get one any time soon, so report an error.
156 DLOG(WARNING) << "Did not get a refresh token for account " << account_id_;
157 consumer_->OnFailure(TOKEN_ERROR);
158 }
159
160 void FamilyInfoFetcher::OnGetTokenSuccess(
161 const OAuth2TokenService::Request* request,
162 const std::string& access_token,
163 const base::Time& expiration_time) {
164 DCHECK_EQ(access_token_request_.get(), request);
165 access_token_ = access_token;
166
167 GURL url(kFamilyApiUrl + request_suffix_);
168 const int id = 0;
169 url_fetcher_.reset(
170 net::URLFetcher::Create(id, url, request_type_, this));
171
172 url_fetcher_->SetRequestContext(request_context_);
173 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
174 net::LOAD_DO_NOT_SAVE_COOKIES);
175 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
176 url_fetcher_->AddExtraRequestHeader(
177 base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
178
179 url_fetcher_->Start();
180 }
181
182 void FamilyInfoFetcher::OnGetTokenFailure(
183 const OAuth2TokenService::Request* request,
184 const GoogleServiceAuthError& error) {
185 DCHECK_EQ(access_token_request_.get(), request);
186 DLOG(WARNING) << "Failed to get an access token: " << error.ToString();
187 consumer_->OnFailure(TOKEN_ERROR);
188 }
189
190 void FamilyInfoFetcher::OnURLFetchComplete(
191 const net::URLFetcher* source) {
192 const net::URLRequestStatus& status = source->GetStatus();
193 if (!status.is_success()) {
194 DLOG(WARNING) << "URLRequestStatus error " << status.error();
195 consumer_->OnFailure(NETWORK_ERROR);
196 return;
197 }
198
199 int response_code = source->GetResponseCode();
200 if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
201 DVLOG(1) << "Access token expired, retrying";
202 access_token_expired_ = true;
203 OAuth2TokenService::ScopeSet scopes;
204 scopes.insert(kScope);
205 token_service_->InvalidateToken(account_id_, scopes, access_token_);
206 StartFetching();
207 return;
208 }
209
210 if (response_code != net::HTTP_OK) {
211 DLOG(WARNING) << "HTTP error " << response_code;
212 consumer_->OnFailure(NETWORK_ERROR);
213 return;
214 }
215
216 std::string response_body;
217 source->GetResponseAsString(&response_body);
218
219 if (request_suffix_ == kGetFamilyProfileApiSuffix) {
220 FamilyProfileFetched(response_body);
221 } else if (request_suffix_ == kGetFamilyMembersApiSuffix) {
222 FamilyMembersFetched(response_body);
223 } else {
224 NOTREACHED();
225 }
226 }
227
228 // static
229 bool FamilyInfoFetcher::ParseMembers(const base::ListValue* list,
230 std::vector<FamilyMember>* members) {
231 for (base::ListValue::const_iterator it = list->begin();
232 it != list->end();
233 it++) {
234 FamilyMember member;
235 base::DictionaryValue* dict = NULL;
236 if (!(*it)->GetAsDictionary(&dict) || !ParseMember(dict, &member)) {
237 return false;
238 }
239 members->push_back(member);
240 }
241 return true;
242 }
243
244 // static
245 bool FamilyInfoFetcher::ParseMember(const base::DictionaryValue* dict,
246 FamilyMember* member) {
247 if (!dict->GetString(kIdUserId, &member->obfuscated_gaia_id))
248 return false;
249 std::string role_str;
250 if (!dict->GetString(kIdRole, &role_str))
251 return false;
252 if (!StringToRole(role_str, &member->role))
253 return false;
254 const base::DictionaryValue* profile_dict = NULL;
255 if (dict->GetDictionary(kIdProfile, &profile_dict))
256 ParseProfile(profile_dict, member);
257 return true;
258 }
259
260 // static
261 void FamilyInfoFetcher::ParseProfile(const base::DictionaryValue* dict,
262 FamilyMember* member) {
263 dict->GetString(kIdDisplayName, &member->display_name);
264 dict->GetString(kIdEmail, &member->email);
265 dict->GetString(kIdProfileUrl, &member->profile_url);
266 dict->GetString(kIdProfileImageUrl, &member->profile_image_url);
267 }
268
269 void FamilyInfoFetcher::FamilyProfileFetched(const std::string& response) {
270 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
271 const base::DictionaryValue* dict = NULL;
272 if (!value || !value->GetAsDictionary(&dict)) {
273 consumer_->OnFailure(SERVICE_ERROR);
274 return;
275 }
276 const base::DictionaryValue* family_dict = NULL;
277 if (!dict->GetDictionary(kIdFamily, &family_dict)) {
278 consumer_->OnFailure(SERVICE_ERROR);
279 return;
280 }
281 FamilyProfile family;
282 if (!family_dict->GetStringWithoutPathExpansion(kIdFamilyId, &family.id)) {
283 consumer_->OnFailure(SERVICE_ERROR);
284 return;
285 }
286 const base::DictionaryValue* profile_dict = NULL;
287 if (!family_dict->GetDictionary(kIdProfile, &profile_dict)) {
288 consumer_->OnFailure(SERVICE_ERROR);
289 return;
290 }
291 if (!profile_dict->GetStringWithoutPathExpansion(kIdFamilyName,
292 &family.name)) {
293 consumer_->OnFailure(SERVICE_ERROR);
294 return;
295 }
296 consumer_->OnGetFamilyProfileSuccess(family);
297 }
298
299 void FamilyInfoFetcher::FamilyMembersFetched(const std::string& response) {
300 scoped_ptr<base::Value> value(base::JSONReader::Read(response));
301 const base::DictionaryValue* dict = NULL;
302 if (!value || !value->GetAsDictionary(&dict)) {
303 consumer_->OnFailure(SERVICE_ERROR);
304 return;
305 }
306 const base::ListValue* members_list = NULL;
307 if (!dict->GetList(kIdMembers, &members_list)) {
308 consumer_->OnFailure(SERVICE_ERROR);
309 return;
310 }
311 std::vector<FamilyMember> members;
312 if (!ParseMembers(members_list, &members)){
313 consumer_->OnFailure(SERVICE_ERROR);
314 return;
315 }
316 consumer_->OnGetFamilyMembersSuccess(members);
317 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698