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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
diff --git a/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
new file mode 100644
index 0000000000000000000000000000000000000000..37f59f5ebcdcb3cee6348a3da1a25ab1f8f735c9
--- /dev/null
+++ b/chrome/browser/supervised_user/child_accounts/family_info_fetcher.cc
@@ -0,0 +1,317 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/supervised_user/child_accounts/family_info_fetcher.h"
+
+#include "base/json/json_reader.h"
+#include "base/strings/stringprintf.h"
+#include "base/values.h"
+#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
+#include "net/url_request/url_request_status.h"
+#include "url/gurl.h"
+
+const char kFamilyApiUrl[] = "https://www.googleapis.com/kidsmanagement/v1/";
+const char kGetFamilyProfileApiSuffix[] = "families/mine?alt=json";
+const char kGetFamilyMembersApiSuffix[] = "families/mine/members?alt=json";
+const char kScope[] = "https://www.googleapis.com/auth/kid.family";
+const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
+const int kNumRetries = 1;
+
+const char kIdFamily[] = "family";
+const char kIdFamilyId[] = "familyId";
+const char kIdProfile[] = "profile";
+const char kIdFamilyName[] = "name";
+const char kIdMembers[] = "members";
+const char kIdUserId[] = "userId";
+const char kIdRole[] = "role";
+const char kIdDisplayName[] = "displayName";
+const char kIdEmail[] = "email";
+const char kIdProfileUrl[] = "profileUrl";
+const char kIdProfileImageUrl[] = "profileImageUrl";
+
+// These correspond to enum FamilyInfoFetcher::FamilyMemberRole, in order.
+const char* kFamilyMemberRoleStrings[] = {
+ "headOfHousehold",
+ "parent",
+ "member",
+ "child"
+};
+
+FamilyInfoFetcher::FamilyProfile::FamilyProfile() {
+}
+
+FamilyInfoFetcher::FamilyProfile::FamilyProfile(const std::string& id,
+ const std::string& name)
+ : id(id), name(name) {
+}
+
+FamilyInfoFetcher::FamilyProfile::~FamilyProfile() {
+}
+
+FamilyInfoFetcher::FamilyMember::FamilyMember() {
+}
+
+FamilyInfoFetcher::FamilyMember::FamilyMember(
+ const std::string& obfuscated_gaia_id,
+ FamilyMemberRole role,
+ const std::string& display_name,
+ const std::string& email,
+ const std::string& profile_url,
+ const std::string& profile_image_url)
+ : obfuscated_gaia_id(obfuscated_gaia_id),
+ role(role),
+ display_name(display_name),
+ email(email),
+ profile_url(profile_url),
+ profile_image_url(profile_image_url) {
+}
+
+FamilyInfoFetcher::FamilyMember::~FamilyMember() {
+}
+
+FamilyInfoFetcher::FamilyInfoFetcher(
+ Consumer* consumer,
+ const std::string& account_id,
+ OAuth2TokenService* token_service,
+ net::URLRequestContextGetter* request_context)
+ : OAuth2TokenService::Consumer("family_info_fetcher"),
+ consumer_(consumer),
+ account_id_(account_id),
+ token_service_(token_service),
+ request_context_(request_context),
+ request_type_(net::URLFetcher::GET),
+ access_token_expired_(false) {
+}
+
+FamilyInfoFetcher::~FamilyInfoFetcher() {
+ // Ensures O2TS observation is cleared when FamilyInfoFetcher is destructed
+ // before refresh token is available.
+ token_service_->RemoveObserver(this);
+}
+
+// static
+std::string FamilyInfoFetcher::RoleToString(FamilyMemberRole role) {
+ return kFamilyMemberRoleStrings[role];
+}
+
+// static
+bool FamilyInfoFetcher::StringToRole(
+ const std::string& str,
+ FamilyInfoFetcher::FamilyMemberRole* role) {
+ for (size_t i = 0; i < arraysize(kFamilyMemberRoleStrings); i++) {
+ if (str == kFamilyMemberRoleStrings[i]) {
+ *role = FamilyMemberRole(i);
+ return true;
+ }
+ }
+ return false;
+}
+
+void FamilyInfoFetcher::StartGetFamilyProfile() {
+ request_suffix_ = kGetFamilyProfileApiSuffix;
+ request_type_ = net::URLFetcher::GET;
+ StartFetching();
+}
+
+void FamilyInfoFetcher::StartGetFamilyMembers() {
+ request_suffix_ = kGetFamilyMembersApiSuffix;
+ request_type_ = net::URLFetcher::GET;
+ StartFetching();
+}
+
+void FamilyInfoFetcher::StartFetching() {
+ if (token_service_->RefreshTokenIsAvailable(account_id_)) {
+ StartFetchingAccessToken();
+ } else {
+ // Wait until we get a refresh token.
+ token_service_->AddObserver(this);
+ }
+}
+
+void FamilyInfoFetcher::StartFetchingAccessToken() {
+ OAuth2TokenService::ScopeSet scopes;
+ scopes.insert(kScope);
+ access_token_request_ = token_service_->StartRequest(
+ account_id_, scopes, this);
+}
+
+void FamilyInfoFetcher::OnRefreshTokenAvailable(
+ const std::string& account_id) {
+ // Wait until we get a refresh token for the requested account.
+ if (account_id != account_id_)
+ return;
+
+ token_service_->RemoveObserver(this);
+
+ StartFetchingAccessToken();
+}
+
+void FamilyInfoFetcher::OnRefreshTokensLoaded() {
+ token_service_->RemoveObserver(this);
+
+ // The PO2TS has loaded all tokens, but we didn't get one for the account we
+ // want. We probably won't get one any time soon, so report an error.
+ DLOG(WARNING) << "Did not get a refresh token for account " << account_id_;
+ consumer_->OnFailure(TOKEN_ERROR);
+}
+
+void FamilyInfoFetcher::OnGetTokenSuccess(
+ const OAuth2TokenService::Request* request,
+ const std::string& access_token,
+ const base::Time& expiration_time) {
+ DCHECK_EQ(access_token_request_.get(), request);
+ access_token_ = access_token;
+
+ GURL url(kFamilyApiUrl + request_suffix_);
+ const int id = 0;
+ url_fetcher_.reset(
+ net::URLFetcher::Create(id, url, request_type_, this));
+
+ url_fetcher_->SetRequestContext(request_context_);
+ url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
+ net::LOAD_DO_NOT_SAVE_COOKIES);
+ url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
+ url_fetcher_->AddExtraRequestHeader(
+ base::StringPrintf(kAuthorizationHeaderFormat, access_token.c_str()));
+
+ url_fetcher_->Start();
+}
+
+void FamilyInfoFetcher::OnGetTokenFailure(
+ const OAuth2TokenService::Request* request,
+ const GoogleServiceAuthError& error) {
+ DCHECK_EQ(access_token_request_.get(), request);
+ DLOG(WARNING) << "Failed to get an access token: " << error.ToString();
+ consumer_->OnFailure(TOKEN_ERROR);
+}
+
+void FamilyInfoFetcher::OnURLFetchComplete(
+ const net::URLFetcher* source) {
+ const net::URLRequestStatus& status = source->GetStatus();
+ if (!status.is_success()) {
+ DLOG(WARNING) << "URLRequestStatus error " << status.error();
+ consumer_->OnFailure(NETWORK_ERROR);
+ return;
+ }
+
+ int response_code = source->GetResponseCode();
+ if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
+ DVLOG(1) << "Access token expired, retrying";
+ access_token_expired_ = true;
+ OAuth2TokenService::ScopeSet scopes;
+ scopes.insert(kScope);
+ token_service_->InvalidateToken(account_id_, scopes, access_token_);
+ StartFetching();
+ return;
+ }
+
+ if (response_code != net::HTTP_OK) {
+ DLOG(WARNING) << "HTTP error " << response_code;
+ consumer_->OnFailure(NETWORK_ERROR);
+ return;
+ }
+
+ std::string response_body;
+ source->GetResponseAsString(&response_body);
+
+ if (request_suffix_ == kGetFamilyProfileApiSuffix) {
+ FamilyProfileFetched(response_body);
+ } else if (request_suffix_ == kGetFamilyMembersApiSuffix) {
+ FamilyMembersFetched(response_body);
+ } else {
+ NOTREACHED();
+ }
+}
+
+// static
+bool FamilyInfoFetcher::ParseMembers(const base::ListValue* list,
+ std::vector<FamilyMember>* members) {
+ for (base::ListValue::const_iterator it = list->begin();
+ it != list->end();
+ it++) {
+ FamilyMember member;
+ base::DictionaryValue* dict = NULL;
+ if (!(*it)->GetAsDictionary(&dict) || !ParseMember(dict, &member)) {
+ return false;
+ }
+ members->push_back(member);
+ }
+ return true;
+}
+
+// static
+bool FamilyInfoFetcher::ParseMember(const base::DictionaryValue* dict,
+ FamilyMember* member) {
+ if (!dict->GetString(kIdUserId, &member->obfuscated_gaia_id))
+ return false;
+ std::string role_str;
+ if (!dict->GetString(kIdRole, &role_str))
+ return false;
+ if (!StringToRole(role_str, &member->role))
+ return false;
+ const base::DictionaryValue* profile_dict = NULL;
+ if (dict->GetDictionary(kIdProfile, &profile_dict))
+ ParseProfile(profile_dict, member);
+ return true;
+}
+
+// static
+void FamilyInfoFetcher::ParseProfile(const base::DictionaryValue* dict,
+ FamilyMember* member) {
+ dict->GetString(kIdDisplayName, &member->display_name);
+ dict->GetString(kIdEmail, &member->email);
+ dict->GetString(kIdProfileUrl, &member->profile_url);
+ dict->GetString(kIdProfileImageUrl, &member->profile_image_url);
+}
+
+void FamilyInfoFetcher::FamilyProfileFetched(const std::string& response) {
+ scoped_ptr<base::Value> value(base::JSONReader::Read(response));
+ const base::DictionaryValue* dict = NULL;
+ if (!value || !value->GetAsDictionary(&dict)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ const base::DictionaryValue* family_dict = NULL;
+ if (!dict->GetDictionary(kIdFamily, &family_dict)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ FamilyProfile family;
+ if (!family_dict->GetStringWithoutPathExpansion(kIdFamilyId, &family.id)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ const base::DictionaryValue* profile_dict = NULL;
+ if (!family_dict->GetDictionary(kIdProfile, &profile_dict)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ if (!profile_dict->GetStringWithoutPathExpansion(kIdFamilyName,
+ &family.name)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ consumer_->OnGetFamilyProfileSuccess(family);
+}
+
+void FamilyInfoFetcher::FamilyMembersFetched(const std::string& response) {
+ scoped_ptr<base::Value> value(base::JSONReader::Read(response));
+ const base::DictionaryValue* dict = NULL;
+ if (!value || !value->GetAsDictionary(&dict)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ const base::ListValue* members_list = NULL;
+ if (!dict->GetList(kIdMembers, &members_list)) {
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ std::vector<FamilyMember> members;
+ if (!ParseMembers(members_list, &members)){
+ consumer_->OnFailure(SERVICE_ERROR);
+ return;
+ }
+ consumer_->OnGetFamilyMembersSuccess(members);
+}

Powered by Google App Engine
This is Rietveld 408576698