1// Copyright 2014 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/signin/easy_unlock_toggle_flow.h" 6 7#include <vector> 8 9#include "base/logging.h" 10#include "base/strings/stringprintf.h" 11#include "chrome/browser/extensions/extension_service.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 14#include "chrome/browser/signin/signin_manager_factory.h" 15#include "chrome/common/extensions/api/identity/oauth2_manifest_handler.h" 16#include "chrome/common/extensions/extension_constants.h" 17#include "components/signin/core/browser/profile_oauth2_token_service.h" 18#include "components/signin/core/browser/signin_manager.h" 19#include "extensions/browser/extension_system.h" 20#include "google_apis/gaia/oauth2_api_call_flow.h" 21#include "net/url_request/url_fetcher.h" 22 23namespace { 24 25const char kEasyUnlockToggleUrl[] = 26 "https://www.googleapis.com/cryptauth/v1/deviceSync/toggleeasyunlock"; 27 28std::vector<std::string> GetScopes() { 29 std::vector<std::string> scopes; 30 scopes.push_back("https://www.googleapis.com/auth/proximity_auth"); 31 scopes.push_back("https://www.googleapis.com/auth/cryptauth"); 32 return scopes; 33} 34 35std::string GetEasyUnlockAppClientId(Profile * profile) { 36 extensions::ExtensionSystem* extension_system = 37 extensions::ExtensionSystem::Get(profile); 38 ExtensionService* extension_service = extension_system->extension_service(); 39 const extensions::Extension* easy_unlock_app = 40 extension_service->GetInstalledExtension( 41 extension_misc::kEasyUnlockAppId); 42 if (!easy_unlock_app) 43 return std::string(); 44 45 const extensions::OAuth2Info& oauth2_info = 46 extensions::OAuth2Info::GetOAuth2Info(easy_unlock_app); 47 return oauth2_info.client_id; 48} 49 50} // namespace 51 52class EasyUnlockToggleFlow::ToggleApiCall : public OAuth2ApiCallFlow { 53 public: 54 ToggleApiCall(EasyUnlockToggleFlow* flow, 55 net::URLRequestContextGetter* context, 56 const std::string& access_token, 57 const std::string& phone_public_key, 58 bool toggle_enable); 59 virtual ~ToggleApiCall(); 60 61 // OAuth2ApiCallFlow 62 virtual GURL CreateApiCallUrl() OVERRIDE; 63 virtual std::string CreateApiCallBody() OVERRIDE; 64 virtual std::string CreateApiCallBodyContentType() OVERRIDE; 65 virtual void ProcessApiCallSuccess(const net::URLFetcher* source) OVERRIDE; 66 virtual void ProcessApiCallFailure(const net::URLFetcher* source) OVERRIDE; 67 virtual void ProcessNewAccessToken(const std::string& access_token) OVERRIDE; 68 virtual void ProcessMintAccessTokenFailure( 69 const GoogleServiceAuthError& error) OVERRIDE; 70 71 private: 72 EasyUnlockToggleFlow* flow_; 73 const std::string phone_public_key_; 74 const bool toggle_enable_; 75 76 DISALLOW_COPY_AND_ASSIGN(ToggleApiCall); 77}; 78 79EasyUnlockToggleFlow::ToggleApiCall::ToggleApiCall( 80 EasyUnlockToggleFlow* flow, 81 net::URLRequestContextGetter* context, 82 const std::string& access_token, 83 const std::string& phone_public_key, 84 bool toggle_enable) 85 : OAuth2ApiCallFlow(context, 86 std::string(), 87 access_token, 88 GetScopes()), 89 flow_(flow), 90 phone_public_key_(phone_public_key), 91 toggle_enable_(toggle_enable) { 92} 93 94EasyUnlockToggleFlow::ToggleApiCall::~ToggleApiCall() { 95} 96 97GURL EasyUnlockToggleFlow::ToggleApiCall::CreateApiCallUrl() { 98 return GURL(kEasyUnlockToggleUrl); 99} 100 101std::string EasyUnlockToggleFlow::ToggleApiCall::CreateApiCallBody() { 102 const char kBodyFormat[] = "{\"enable\":%s,\"publicKey\":\"%s\"}"; 103 return base::StringPrintf( 104 kBodyFormat, 105 toggle_enable_ ? "true" : "false", 106 phone_public_key_.c_str()); 107} 108 109std::string 110EasyUnlockToggleFlow::ToggleApiCall::CreateApiCallBodyContentType() { 111 return "application/json"; 112} 113 114void EasyUnlockToggleFlow::ToggleApiCall::ProcessApiCallSuccess( 115 const net::URLFetcher* source) { 116 flow_->ReportToggleApiCallResult(true); 117} 118 119void EasyUnlockToggleFlow::ToggleApiCall::ProcessApiCallFailure( 120 const net::URLFetcher* source) { 121 flow_->ReportToggleApiCallResult(false); 122} 123 124void EasyUnlockToggleFlow::ToggleApiCall::ProcessNewAccessToken( 125 const std::string& access_token) { 126 NOTREACHED(); 127} 128 129void EasyUnlockToggleFlow::ToggleApiCall::ProcessMintAccessTokenFailure( 130 const GoogleServiceAuthError& error) { 131 NOTREACHED(); 132} 133 134EasyUnlockToggleFlow::EasyUnlockToggleFlow(Profile* profile, 135 const std::string& phone_public_key, 136 bool toggle_enable, 137 const ToggleFlowCallback& callback) 138 : OAuth2TokenService::Consumer("easy_unlock_toggle"), 139 profile_(profile), 140 phone_public_key_(phone_public_key), 141 toggle_enable_(toggle_enable), 142 callback_(callback) { 143} 144 145EasyUnlockToggleFlow::~EasyUnlockToggleFlow() { 146} 147 148void EasyUnlockToggleFlow::Start() { 149 ProfileOAuth2TokenService* token_service = 150 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 151 SigninManagerBase* signin_manager = 152 SigninManagerFactory::GetForProfile(profile_); 153 token_request_ = 154 token_service->StartRequest(signin_manager->GetAuthenticatedAccountId(), 155 OAuth2TokenService::ScopeSet(), 156 this); 157} 158 159void EasyUnlockToggleFlow::OnGetTokenSuccess( 160 const OAuth2TokenService::Request* request, 161 const std::string& access_token, 162 const base::Time& expiration_time) { 163 DCHECK_EQ(token_request_.get(), request); 164 token_request_.reset(); 165 166 mint_token_flow_.reset( 167 new OAuth2MintTokenFlow(profile_->GetRequestContext(), 168 this, 169 OAuth2MintTokenFlow::Parameters( 170 access_token, 171 extension_misc::kEasyUnlockAppId, 172 GetEasyUnlockAppClientId(profile_), 173 GetScopes(), 174 OAuth2MintTokenFlow::MODE_MINT_TOKEN_FORCE))); 175 mint_token_flow_->Start(); 176} 177 178void EasyUnlockToggleFlow::OnGetTokenFailure( 179 const OAuth2TokenService::Request* request, 180 const GoogleServiceAuthError& error) { 181 DCHECK_EQ(token_request_.get(), request); 182 token_request_.reset(); 183 184 LOG(ERROR) << "Easy unlock toggle flow, failed to get access token," 185 << "error=" << error.state(); 186 callback_.Run(false); 187} 188 189void EasyUnlockToggleFlow::OnMintTokenSuccess(const std::string& access_token, 190 int time_to_live) { 191 toggle_api_call_.reset(new ToggleApiCall(this, 192 profile_->GetRequestContext(), 193 access_token, 194 phone_public_key_, 195 toggle_enable_)); 196 toggle_api_call_->Start(); 197} 198 199void EasyUnlockToggleFlow::OnMintTokenFailure( 200 const GoogleServiceAuthError& error) { 201 LOG(ERROR) << "Easy unlock toggle flow, failed to mint access token," 202 << "error=" << error.state(); 203 callback_.Run(false); 204} 205 206void EasyUnlockToggleFlow::OnIssueAdviceSuccess( 207 const IssueAdviceInfo& issue_advice) { 208 NOTREACHED(); 209} 210 211void EasyUnlockToggleFlow::ReportToggleApiCallResult(bool success) { 212 callback_.Run(success); 213} 214