1// Copyright (c) 2012 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 "components/policy/core/common/cloud/user_info_fetcher.h"
6
7#include "base/json/json_reader.h"
8#include "base/logging.h"
9#include "base/strings/stringprintf.h"
10#include "base/values.h"
11#include "google_apis/gaia/gaia_urls.h"
12#include "google_apis/gaia/google_service_auth_error.h"
13#include "net/base/load_flags.h"
14#include "net/http/http_status_code.h"
15#include "net/url_request/url_fetcher.h"
16#include "net/url_request/url_request_status.h"
17#include "url/gurl.h"
18
19namespace {
20
21static const char kAuthorizationHeaderFormat[] =
22    "Authorization: Bearer %s";
23
24static std::string MakeAuthorizationHeader(const std::string& auth_token) {
25  return base::StringPrintf(kAuthorizationHeaderFormat, auth_token.c_str());
26}
27
28}  // namespace
29
30namespace policy {
31
32UserInfoFetcher::UserInfoFetcher(Delegate* delegate,
33                                 net::URLRequestContextGetter* context)
34    : delegate_(delegate),
35      context_(context) {
36  DCHECK(delegate);
37}
38
39UserInfoFetcher::~UserInfoFetcher() {
40}
41
42void UserInfoFetcher::Start(const std::string& access_token) {
43  // Create a URLFetcher and start it.
44  url_fetcher_.reset(net::URLFetcher::Create(
45      0, GaiaUrls::GetInstance()->oauth_user_info_url(),
46      net::URLFetcher::GET, this));
47  url_fetcher_->SetRequestContext(context_);
48  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
49                             net::LOAD_DO_NOT_SAVE_COOKIES);
50  url_fetcher_->AddExtraRequestHeader(MakeAuthorizationHeader(access_token));
51  url_fetcher_->Start();  // Results in a call to OnURLFetchComplete().
52}
53
54void UserInfoFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
55  net::URLRequestStatus status = source->GetStatus();
56  GoogleServiceAuthError error = GoogleServiceAuthError::AuthErrorNone();
57  if (!status.is_success()) {
58    if (status.status() == net::URLRequestStatus::CANCELED)
59      error = GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
60    else
61      error = GoogleServiceAuthError::FromConnectionError(status.error());
62  } else if (source->GetResponseCode() != net::HTTP_OK) {
63    DLOG(WARNING) << "UserInfo request failed with HTTP code: "
64                  << source->GetResponseCode();
65    error = GoogleServiceAuthError(
66        GoogleServiceAuthError::CONNECTION_FAILED);
67  }
68  if (error.state() != GoogleServiceAuthError::NONE) {
69    delegate_->OnGetUserInfoFailure(error);
70    return;
71  }
72
73  // Successfully fetched userinfo from the server - parse it and hand it off
74  // to the delegate.
75  std::string unparsed_data;
76  source->GetResponseAsString(&unparsed_data);
77  DVLOG(1) << "Received UserInfo response: " << unparsed_data;
78  scoped_ptr<base::Value> parsed_value(base::JSONReader::Read(unparsed_data));
79  base::DictionaryValue* dict;
80  if (parsed_value.get() && parsed_value->GetAsDictionary(&dict)) {
81    delegate_->OnGetUserInfoSuccess(dict);
82  } else {
83    NOTREACHED() << "Could not parse userinfo response from server";
84    delegate_->OnGetUserInfoFailure(GoogleServiceAuthError(
85        GoogleServiceAuthError::CONNECTION_FAILED));
86  }
87}
88
89};  // namespace policy
90