obfuscated_gaia_id_fetcher.cc revision 7dbb3d5cf0c15f500944d211057644d6a2f37371
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/push_messaging/obfuscated_gaia_id_fetcher.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/gaia/google_service_auth_error.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_fetcher.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/url_request/url_request_status.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::URLFetcher;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::URLRequestContextGetter;
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using net::URLRequestStatus;
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// URL of the service to get obfuscated Gaia ID (here misnamed channel ID).
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char kCWSChannelServiceURL[] =
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    "https://www.googleapis.com/gcm_for_chrome/v1/channels/id";
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)GoogleServiceAuthError CreateAuthError(const URLFetcher* source) {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (source->GetStatus().status() == URLRequestStatus::CANCELED) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(munjal): Improve error handling. Currently we return connection
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // error for even application level errors. We need to either expand the
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // GoogleServiceAuthError enum or create a new one to report better
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // errors.
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (source->GetStatus().is_success()) {
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "Remote server returned " << source->GetResponseCode();
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return GoogleServiceAuthError::FromConnectionError(
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          source->GetResponseCode());
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      DLOG(WARNING) << "URLFetcher failed: " << source->GetStatus().error();
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return GoogleServiceAuthError::FromConnectionError(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          source->GetStatus().error());
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObfuscatedGaiaIdFetcher::ObfuscatedGaiaIdFetcher(
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    URLRequestContextGetter* context,
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Delegate* delegate,
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    const std::string& access_token)
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : OAuth2ApiCallFlow(context, std::string(), access_token, GetScopes()),
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_(delegate) {
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(delegate);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObfuscatedGaiaIdFetcher::~ObfuscatedGaiaIdFetcher() { }
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch// Returns a vector of scopes needed to call the API to get obfuscated Gaia ID.
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochstd::vector<std::string> ObfuscatedGaiaIdFetcher::GetScopes() {
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  std::vector<std::string> scopes;
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  scopes.push_back("https://www.googleapis.com/auth/gcm_for_chrome.readonly");
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return scopes;
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObfuscatedGaiaIdFetcher::ReportSuccess(const std::string& obfuscated_id) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnObfuscatedGaiaIdFetchSuccess(obfuscated_id);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObfuscatedGaiaIdFetcher::ReportFailure(
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GoogleServiceAuthError& error) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delegate_->OnObfuscatedGaiaIdFetchFailure(error);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL ObfuscatedGaiaIdFetcher::CreateApiCallUrl() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(kCWSChannelServiceURL);
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ObfuscatedGaiaIdFetcher::CreateApiCallBody() {
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Nothing to do here, we don't need a body for this request, the URL
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // encodes all the proper arguments.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObfuscatedGaiaIdFetcher::ProcessApiCallSuccess(
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(munjal): Change error code paths in this method to report an
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // internal error.
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string response_body;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(source->GetResponseAsString(&response_body));
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string obfuscated_id;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ParseResponse(response_body, &obfuscated_id))
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportSuccess(obfuscated_id);
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we picked 101 arbitrarily to help us correlate the error with this code.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObfuscatedGaiaIdFetcher::ProcessApiCallFailure(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLFetcher* source) {
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReportFailure(CreateAuthError(source));
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObfuscatedGaiaIdFetcher::ProcessNewAccessToken(
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& obfuscated_id)  {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We generate a new access token every time instead of storing the access
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // token since access tokens expire every hour and we expect to get
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // obfuscated Gaia ID very infrequently.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ObfuscatedGaiaIdFetcher::ProcessMintAccessTokenFailure(
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GoogleServiceAuthError& error)  {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We failed to generate the token needed to call the API to get
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the obfuscated Gaia ID, so report failure to the caller.
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportFailure(error);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ObfuscatedGaiaIdFetcher::ParseResponse(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& data, std::string* result) {
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<base::Value> value(base::JSONReader::Read(data));
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value.get())
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  base::DictionaryValue* dict = NULL;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!value->GetAsDictionary(&dict))
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict->GetString("id", result);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
138