obfuscated_gaia_id_fetcher.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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)// Returns a vector of scopes needed to call the API to get obfuscated Gaia ID. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::vector<std::string> GetScopes() { 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<std::string> scopes; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scopes.push_back("https://www.googleapis.com/auth/gcm_for_chrome.readonly"); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scopes; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObfuscatedGaiaIdFetcher::ObfuscatedGaiaIdFetcher( 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) URLRequestContextGetter* context, 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Delegate* delegate, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& refresh_token) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : OAuth2ApiCallFlow(context, refresh_token, std::string(), GetScopes()), 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(delegate) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(delegate); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ObfuscatedGaiaIdFetcher::~ObfuscatedGaiaIdFetcher() { } 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 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