obfuscated_gaia_id_fetcher.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 "chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.h"
6
7#include <vector>
8
9#include "base/json/json_reader.h"
10#include "base/values.h"
11#include "google_apis/gaia/google_service_auth_error.h"
12#include "net/url_request/url_fetcher.h"
13#include "net/url_request/url_request_status.h"
14
15using net::URLFetcher;
16using net::URLRequestContextGetter;
17using net::URLRequestStatus;
18
19namespace {
20
21// URL of the service to get obfuscated Gaia ID (here misnamed channel ID).
22static const char kCWSChannelServiceURL[] =
23    "https://www.googleapis.com/gcm_for_chrome/v1/channels/id";
24
25GoogleServiceAuthError CreateAuthError(const URLFetcher* source) {
26  if (source->GetStatus().status() == URLRequestStatus::CANCELED) {
27    return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
28  } else {
29    // TODO(munjal): Improve error handling. Currently we return connection
30    // error for even application level errors. We need to either expand the
31    // GoogleServiceAuthError enum or create a new one to report better
32    // errors.
33    if (source->GetStatus().is_success()) {
34      DLOG(WARNING) << "Remote server returned " << source->GetResponseCode();
35      return GoogleServiceAuthError::FromConnectionError(
36          source->GetResponseCode());
37    } else {
38      DLOG(WARNING) << "URLFetcher failed: " << source->GetStatus().error();
39      return GoogleServiceAuthError::FromConnectionError(
40          source->GetStatus().error());
41    }
42  }
43}
44
45// Returns a vector of scopes needed to call the API to get obfuscated Gaia ID.
46std::vector<std::string> GetScopes() {
47  std::vector<std::string> scopes;
48  scopes.push_back("https://www.googleapis.com/auth/gcm_for_chrome.readonly");
49  return scopes;
50}
51
52}  // namespace
53
54namespace extensions {
55
56ObfuscatedGaiaIdFetcher::ObfuscatedGaiaIdFetcher(
57    URLRequestContextGetter* context,
58    Delegate* delegate,
59    const std::string& refresh_token)
60    : OAuth2ApiCallFlow(context, refresh_token, std::string(), GetScopes()),
61      delegate_(delegate) {
62  DCHECK(delegate);
63}
64
65ObfuscatedGaiaIdFetcher::~ObfuscatedGaiaIdFetcher() { }
66
67void ObfuscatedGaiaIdFetcher::ReportSuccess(const std::string& obfuscated_id) {
68  if (delegate_)
69    delegate_->OnObfuscatedGaiaIdFetchSuccess(obfuscated_id);
70}
71
72void ObfuscatedGaiaIdFetcher::ReportFailure(
73    const GoogleServiceAuthError& error) {
74  if (delegate_)
75    delegate_->OnObfuscatedGaiaIdFetchFailure(error);
76}
77
78GURL ObfuscatedGaiaIdFetcher::CreateApiCallUrl() {
79  return GURL(kCWSChannelServiceURL);
80}
81
82std::string ObfuscatedGaiaIdFetcher::CreateApiCallBody() {
83  // Nothing to do here, we don't need a body for this request, the URL
84  // encodes all the proper arguments.
85  return std::string();
86}
87
88void ObfuscatedGaiaIdFetcher::ProcessApiCallSuccess(
89    const net::URLFetcher* source) {
90  // TODO(munjal): Change error code paths in this method to report an
91  // internal error.
92  std::string response_body;
93  CHECK(source->GetResponseAsString(&response_body));
94
95  std::string obfuscated_id;
96  if (ParseResponse(response_body, &obfuscated_id))
97    ReportSuccess(obfuscated_id);
98  else
99    // we picked 101 arbitrarily to help us correlate the error with this code.
100    ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
101}
102
103void ObfuscatedGaiaIdFetcher::ProcessApiCallFailure(
104    const net::URLFetcher* source) {
105  ReportFailure(CreateAuthError(source));
106}
107
108void ObfuscatedGaiaIdFetcher::ProcessNewAccessToken(
109    const std::string& obfuscated_id)  {
110  // We generate a new access token every time instead of storing the access
111  // token since access tokens expire every hour and we expect to get
112  // obfuscated Gaia ID very infrequently.
113}
114
115void ObfuscatedGaiaIdFetcher::ProcessMintAccessTokenFailure(
116    const GoogleServiceAuthError& error)  {
117  // We failed to generate the token needed to call the API to get
118  // the obfuscated Gaia ID, so report failure to the caller.
119  ReportFailure(error);
120}
121
122// static
123bool ObfuscatedGaiaIdFetcher::ParseResponse(
124    const std::string& data, std::string* result) {
125  scoped_ptr<base::Value> value(base::JSONReader::Read(data));
126
127  if (!value.get())
128    return false;
129
130  base::DictionaryValue* dict = NULL;
131  if (!value->GetAsDictionary(&dict))
132    return false;
133
134  return dict->GetString("id", result);
135}
136
137}  // namespace extensions
138