• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 using net::URLFetcher;
16 using net::URLRequestContextGetter;
17 using net::URLRequestStatus;
18 
19 namespace {
20 
21 // URL of the service to get obfuscated Gaia ID (here misnamed channel ID).
22 static const char kCWSChannelServiceURL[] =
23     "https://www.googleapis.com/gcm_for_chrome/v1/channels/id";
24 
CreateAuthError(const URLFetcher * source)25 GoogleServiceAuthError 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 }  // namespace
46 
47 namespace extensions {
48 
ObfuscatedGaiaIdFetcher(URLRequestContextGetter * context,Delegate * delegate,const std::string & access_token)49 ObfuscatedGaiaIdFetcher::ObfuscatedGaiaIdFetcher(
50     URLRequestContextGetter* context,
51     Delegate* delegate,
52     const std::string& access_token)
53     : OAuth2ApiCallFlow(context, std::string(), access_token, GetScopes()),
54       delegate_(delegate) {
55   DCHECK(delegate);
56 }
57 
~ObfuscatedGaiaIdFetcher()58 ObfuscatedGaiaIdFetcher::~ObfuscatedGaiaIdFetcher() { }
59 
60 // Returns a vector of scopes needed to call the API to get obfuscated Gaia ID.
GetScopes()61 std::vector<std::string> ObfuscatedGaiaIdFetcher::GetScopes() {
62   std::vector<std::string> scopes;
63   scopes.push_back("https://www.googleapis.com/auth/gcm_for_chrome.readonly");
64   return scopes;
65 }
66 
ReportSuccess(const std::string & obfuscated_id)67 void ObfuscatedGaiaIdFetcher::ReportSuccess(const std::string& obfuscated_id) {
68   if (delegate_)
69     delegate_->OnObfuscatedGaiaIdFetchSuccess(obfuscated_id);
70 }
71 
ReportFailure(const GoogleServiceAuthError & error)72 void ObfuscatedGaiaIdFetcher::ReportFailure(
73     const GoogleServiceAuthError& error) {
74   if (delegate_)
75     delegate_->OnObfuscatedGaiaIdFetchFailure(error);
76 }
77 
CreateApiCallUrl()78 GURL ObfuscatedGaiaIdFetcher::CreateApiCallUrl() {
79   return GURL(kCWSChannelServiceURL);
80 }
81 
CreateApiCallBody()82 std::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 
ProcessApiCallSuccess(const net::URLFetcher * source)88 void 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 
ProcessApiCallFailure(const net::URLFetcher * source)103 void ObfuscatedGaiaIdFetcher::ProcessApiCallFailure(
104     const net::URLFetcher* source) {
105   ReportFailure(CreateAuthError(source));
106 }
107 
ProcessNewAccessToken(const std::string & obfuscated_id)108 void 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 
ProcessMintAccessTokenFailure(const GoogleServiceAuthError & error)115 void 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
ParseResponse(const std::string & data,std::string * result)123 bool 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