diff options
author | estade <estade@chromium.org> | 2015-01-26 15:28:13 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-01-26 23:29:16 +0000 |
commit | 494f8e6689b13f54bcf2e8f933c630e852514920 (patch) | |
tree | b655c654cafb5cb8eb35ca828f50f88a62f4e425 | |
parent | a74227892c867e3b709b87e76c51f0cd764cc73b (diff) | |
download | chromium_src-494f8e6689b13f54bcf2e8f933c630e852514920.zip chromium_src-494f8e6689b13f54bcf2e8f933c630e852514920.tar.gz chromium_src-494f8e6689b13f54bcf2e8f933c630e852514920.tar.bz2 |
Add OAuth2 token to RealPanRequest.
Depends on https://codereview.chromium.org/869003003/
BUG=451286
TBR=sgurun@chromium.org
Review URL: https://codereview.chromium.org/873583007
Cr-Commit-Position: refs/heads/master@{#313165}
11 files changed, 151 insertions, 20 deletions
diff --git a/android_webview/native/aw_autofill_client.cc b/android_webview/native/aw_autofill_client.cc index b14b24e..c0427fa 100644 --- a/android_webview/native/aw_autofill_client.cc +++ b/android_webview/native/aw_autofill_client.cc @@ -66,8 +66,12 @@ PrefService* AwAutofillClient::GetPrefs() { AwContentBrowserClient::GetAwBrowserContext()); } +IdentityProvider* AwAutofillClient::GetIdentityProvider() { + return nullptr; +} + autofill::PersonalDataManager* AwAutofillClient::GetPersonalDataManager() { - return NULL; + return nullptr; } scoped_refptr<autofill::AutofillWebDataService> diff --git a/android_webview/native/aw_autofill_client.h b/android_webview/native/aw_autofill_client.h index 11085f4..dd85587 100644 --- a/android_webview/native/aw_autofill_client.h +++ b/android_webview/native/aw_autofill_client.h @@ -60,6 +60,7 @@ class AwAutofillClient : public autofill::AutofillClient, virtual scoped_refptr<autofill::AutofillWebDataService> GetDatabase() override; virtual PrefService* GetPrefs() override; + IdentityProvider* GetIdentityProvider() override; virtual void HideRequestAutocompleteDialog() override; virtual void ShowAutofillSettings() override; virtual void ShowUnmaskPrompt( diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.cc b/chrome/browser/ui/autofill/chrome_autofill_client.cc index 47b8219..dbc94d9 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.cc +++ b/chrome/browser/ui/autofill/chrome_autofill_client.cc @@ -10,6 +10,9 @@ #include "chrome/browser/infobars/infobar_service.h" #include "chrome/browser/password_manager/chrome_password_manager_client.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/profile_identity_provider.h" +#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" +#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/ui/autofill/autofill_dialog_controller.h" #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" #include "chrome/browser/ui/autofill/card_unmask_prompt_view.h" @@ -33,6 +36,7 @@ #include "chrome/browser/android/chromium_application.h" #include "chrome/browser/ui/android/autofill/autofill_logger_android.h" #else +#include "chrome/browser/ui/webui/signin/login_ui_service_factory.h" #include "components/ui/zoom/zoom_controller.h" #endif @@ -99,6 +103,23 @@ PrefService* ChromeAutofillClient::GetPrefs() { ->GetPrefs(); } +IdentityProvider* ChromeAutofillClient::GetIdentityProvider() { + if (!identity_provider_) { + Profile* profile = + Profile::FromBrowserContext(web_contents()->GetBrowserContext()); + LoginUIService* login_service = nullptr; +#if !defined(OS_ANDROID) + login_service = LoginUIServiceFactory::GetForProfile(profile); +#endif + identity_provider_.reset(new ProfileIdentityProvider( + SigninManagerFactory::GetForProfile(profile), + ProfileOAuth2TokenServiceFactory::GetForProfile(profile), + login_service)); + } + + return identity_provider_.get(); +} + void ChromeAutofillClient::ShowAutofillSettings() { #if defined(OS_ANDROID) chrome::android::ChromiumApplication::ShowAutofillSettings(); diff --git a/chrome/browser/ui/autofill/chrome_autofill_client.h b/chrome/browser/ui/autofill/chrome_autofill_client.h index 28f1032..6385f3c 100644 --- a/chrome/browser/ui/autofill/chrome_autofill_client.h +++ b/chrome/browser/ui/autofill/chrome_autofill_client.h @@ -46,6 +46,7 @@ class ChromeAutofillClient PersonalDataManager* GetPersonalDataManager() override; scoped_refptr<AutofillWebDataService> GetDatabase() override; PrefService* GetPrefs() override; + IdentityProvider* GetIdentityProvider() override; void HideRequestAutocompleteDialog() override; void ShowAutofillSettings() override; void ShowUnmaskPrompt(const CreditCard& card, @@ -129,6 +130,9 @@ class ChromeAutofillClient // The last render frame that called requestAutocomplete. content::RenderFrameHost* last_rfh_to_rac_; + // The identity provider, used for Wallet integration. + scoped_ptr<IdentityProvider> identity_provider_; + DISALLOW_COPY_AND_ASSIGN(ChromeAutofillClient); }; diff --git a/components/autofill/core/browser/autofill_client.h b/components/autofill/core/browser/autofill_client.h index 6096d01..534aa68 100644 --- a/components/autofill/core/browser/autofill_client.h +++ b/components/autofill/core/browser/autofill_client.h @@ -13,6 +13,8 @@ #include "base/strings/string16.h" #include "ui/base/window_open_disposition.h" +class IdentityProvider; + namespace content { class RenderFrameHost; } @@ -72,6 +74,9 @@ class AutofillClient { // Gets the preferences associated with the client. virtual PrefService* GetPrefs() = 0; + // Gets the IdentityProvider associated with the client (for OAuth2). + virtual IdentityProvider* GetIdentityProvider() = 0; + // Hides the associated request autocomplete dialog (if it exists). virtual void HideRequestAutocompleteDialog() = 0; diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc index c25c99c..cb5030a 100644 --- a/components/autofill/core/browser/autofill_manager.cc +++ b/components/autofill/core/browser/autofill_manager.cc @@ -561,6 +561,8 @@ void AutofillManager::FillOrPreviewForm( unmasking_query_id_ = query_id; unmasking_form_ = form; unmasking_field_ = field; + // TODO(estade): uncomment this after the demo. + // real_pan_client_.Prepare(); client()->ShowUnmaskPrompt(unmasking_card_, weak_ptr_factory_.GetWeakPtr()); return; @@ -708,13 +710,12 @@ void AutofillManager::OnUnmaskPromptClosed() { unmasking_cvc_.clear(); } -void AutofillManager::OnDidGetRealPan(const std::string& real_pan) { - NOTIMPLEMENTED(); +IdentityProvider* AutofillManager::GetIdentityProvider() { + return client()->GetIdentityProvider(); } -std::string AutofillManager::GetOAuth2Token() { +void AutofillManager::OnDidGetRealPan(const std::string& real_pan) { NOTIMPLEMENTED(); - return "would_I_lie_to_you?"; } void AutofillManager::OnUnmaskVerificationResult(bool success) { diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h index fd177d6..9ba6e63 100644 --- a/components/autofill/core/browser/autofill_manager.h +++ b/components/autofill/core/browser/autofill_manager.h @@ -230,8 +230,8 @@ class AutofillManager : public AutofillDownloadManager::Observer, void OnUnmaskPromptClosed() override; // wallet::RealPanWalletClient::Delegate: + IdentityProvider* GetIdentityProvider() override; void OnDidGetRealPan(const std::string& real_pan) override; - std::string GetOAuth2Token() override; // A toy method called when the (fake) unmasking process has finished. void OnUnmaskVerificationResult(bool success); diff --git a/components/autofill/core/browser/test_autofill_client.cc b/components/autofill/core/browser/test_autofill_client.cc index 34523dd..e193a3a 100644 --- a/components/autofill/core/browser/test_autofill_client.cc +++ b/components/autofill/core/browser/test_autofill_client.cc @@ -14,17 +14,21 @@ TestAutofillClient::~TestAutofillClient() { } PersonalDataManager* TestAutofillClient::GetPersonalDataManager() { - return NULL; + return nullptr; } scoped_refptr<AutofillWebDataService> TestAutofillClient::GetDatabase() { - return scoped_refptr<AutofillWebDataService>(NULL); + return scoped_refptr<AutofillWebDataService>(nullptr); } PrefService* TestAutofillClient::GetPrefs() { return prefs_.get(); } +IdentityProvider* TestAutofillClient::GetIdentityProvider() { + return nullptr; +} + void TestAutofillClient::HideRequestAutocompleteDialog() { } diff --git a/components/autofill/core/browser/test_autofill_client.h b/components/autofill/core/browser/test_autofill_client.h index 25c5308..571d04e 100644 --- a/components/autofill/core/browser/test_autofill_client.h +++ b/components/autofill/core/browser/test_autofill_client.h @@ -23,6 +23,7 @@ class TestAutofillClient : public AutofillClient { PersonalDataManager* GetPersonalDataManager() override; scoped_refptr<AutofillWebDataService> GetDatabase() override; PrefService* GetPrefs() override; + IdentityProvider* GetIdentityProvider() override; void HideRequestAutocompleteDialog() override; void ShowAutofillSettings() override; void ShowUnmaskPrompt(const CreditCard& card, diff --git a/components/autofill/core/browser/wallet/real_pan_wallet_client.cc b/components/autofill/core/browser/wallet/real_pan_wallet_client.cc index ab63674..35c6cbd 100644 --- a/components/autofill/core/browser/wallet/real_pan_wallet_client.cc +++ b/components/autofill/core/browser/wallet/real_pan_wallet_client.cc @@ -10,6 +10,8 @@ #include "base/memory/scoped_ptr.h" #include "base/strings/stringprintf.h" #include "base/values.h" +#include "components/autofill/core/browser/credit_card.h" +#include "google_apis/gaia/identity_provider.h" #include "net/base/escape.h" #include "net/http/http_status_code.h" #include "net/url_request/url_fetcher.h" @@ -28,12 +30,17 @@ const char kUnmaskCardRequestUrl[] = "https://wallet.google.com/payments/apis-secure/creditcardservice" "/GetRealPan?s7e=cvc"; +const char kTokenServiceConsumerId[] = "real_pan_wallet_client"; +const char kWalletOAuth2Scope[] = + "https://www.googleapis.com/auth/wallet.chrome"; + } // namespace RealPanWalletClient::RealPanWalletClient( net::URLRequestContextGetter* context_getter, Delegate* delegate) - : context_getter_(context_getter), + : OAuth2TokenService::Consumer(kTokenServiceConsumerId), + context_getter_(context_getter), delegate_(delegate), weak_ptr_factory_(this) { DCHECK(delegate); @@ -42,16 +49,23 @@ RealPanWalletClient::RealPanWalletClient( RealPanWalletClient::~RealPanWalletClient() { } +void RealPanWalletClient::Prepare() { + if (access_token_.empty()) + StartTokenFetch(); +} + void RealPanWalletClient::UnmaskCard(const CreditCard& card, const std::string& cvc) { + DCHECK_EQ(CreditCard::MASKED_SERVER_CARD, card.record_type()); + request_.reset(net::URLFetcher::Create( 0, GURL(kUnmaskCardRequestUrl), net::URLFetcher::POST, this)); request_->SetRequestContext(context_getter_.get()); base::DictionaryValue request_dict; request_dict.SetString("encrypted_cvc", "__param:cvc"); - // TODO(estade): get the token from |card|. - request_dict.SetString("credit_card_token", "deadbeefee"); + // TODO(estade): is this the correct "token"? + request_dict.SetString("credit_card_token", card.server_id()); std::string json_request; base::JSONWriter::Write(&request_dict, &json_request); std::string post_body = base::StringPrintf(kUnmaskCardRequestFormat, @@ -59,9 +73,10 @@ void RealPanWalletClient::UnmaskCard(const CreditCard& card, net::EscapeUrlEncodedData(cvc, true).c_str()); request_->SetUploadData("application/x-www-form-urlencoded", post_body); - request_->AddExtraRequestHeader( - "Authorization: " + delegate_->GetOAuth2Token()); - request_->Start(); + if (access_token_.empty()) + StartTokenFetch(); + else + SetOAuth2TokenAndStartRequest(); } void RealPanWalletClient::CancelRequest() { @@ -77,6 +92,9 @@ void RealPanWalletClient::OnURLFetchComplete(const net::URLFetcher* source) { scoped_ptr<base::DictionaryValue> response_dict; int response_code = source->GetResponseCode(); + // TODO(estade): OAuth2 may fail due to an expired access token, in which case + // we should invalidate the token and try again. How is that failure reported? + switch (response_code) { // Valid response. case net::HTTP_OK: { @@ -118,5 +136,51 @@ void RealPanWalletClient::OnURLFetchComplete(const net::URLFetcher* source) { delegate_->OnDidGetRealPan(real_pan); } +void RealPanWalletClient::OnGetTokenSuccess( + const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) { + DCHECK_EQ(request, access_token_request_.get()); + access_token_ = access_token; + if (request_) + SetOAuth2TokenAndStartRequest(); + + access_token_request_.reset(); +} + +void RealPanWalletClient::OnGetTokenFailure( + const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) { + DCHECK_EQ(request, access_token_request_.get()); + if (request_) { + request_.reset(); + delegate_->OnDidGetRealPan(std::string()); + } + // TODO(estade): what do we do in the failure case? + NOTIMPLEMENTED(); + + access_token_request_.reset(); +} + +void RealPanWalletClient::StartTokenFetch() { + // Don't cancel outstanding requests. + if (access_token_request_) + return; + + // However, do clear old tokens. + access_token_.clear(); + + OAuth2TokenService::ScopeSet wallet_scopes; + wallet_scopes.insert(kWalletOAuth2Scope); + IdentityProvider* identity = delegate_->GetIdentityProvider(); + access_token_request_ = identity->GetTokenService()->StartRequest( + identity->GetActiveAccountId(), wallet_scopes, this); +} + +void RealPanWalletClient::SetOAuth2TokenAndStartRequest() { + request_->AddExtraRequestHeader("Authorization: " + access_token_); + request_->Start(); +} + } // namespace wallet } // namespace autofill diff --git a/components/autofill/core/browser/wallet/real_pan_wallet_client.h b/components/autofill/core/browser/wallet/real_pan_wallet_client.h index c58168d..3323f91 100644 --- a/components/autofill/core/browser/wallet/real_pan_wallet_client.h +++ b/components/autofill/core/browser/wallet/real_pan_wallet_client.h @@ -7,8 +7,11 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" +#include "google_apis/gaia/oauth2_token_service.h" #include "net/url_request/url_fetcher_delegate.h" +class IdentityProvider; + namespace net { class URLFetcher; class URLRequestContextGetter; @@ -23,17 +26,17 @@ namespace wallet { // RealPanWalletClient is modelled on WalletClient. Whereas the latter is used // for requestAutocomplete-related requests, RealPanWalletClient is used to // import user data from Wallet for normal web Autofill. -class RealPanWalletClient : public net::URLFetcherDelegate { +class RealPanWalletClient : public net::URLFetcherDelegate, + public OAuth2TokenService::Consumer { public: class Delegate { public: + // The identity provider used to get OAuth2 tokens. + virtual IdentityProvider* GetIdentityProvider() = 0; + // Returns the real PAN retrieved from Wallet. |real_pan| will be empty // on failure. virtual void OnDidGetRealPan(const std::string& real_pan) = 0; - - // Called to retrieve the OAuth2 token that should be used for requests - // to Wallet. - virtual std::string GetOAuth2Token() = 0; }; // |context_getter| is reference counted so it has no lifetime or ownership @@ -44,6 +47,10 @@ class RealPanWalletClient : public net::URLFetcherDelegate { ~RealPanWalletClient() override; + // Starts fetching the OAuth2 token in anticipation of future wallet requests. + // Called as an optimization, but not strictly necessary. + void Prepare(); + // The user has attempted to unmask a card with the given cvc. void UnmaskCard(const CreditCard& card, const std::string& cvc); @@ -54,6 +61,19 @@ class RealPanWalletClient : public net::URLFetcherDelegate { // net::URLFetcherDelegate: void OnURLFetchComplete(const net::URLFetcher* source) override; + // OAuth2TokenService::Consumer implementation. + void OnGetTokenSuccess(const OAuth2TokenService::Request* request, + const std::string& access_token, + const base::Time& expiration_time) override; + void OnGetTokenFailure(const OAuth2TokenService::Request* request, + const GoogleServiceAuthError& error) override; + + // Initiates a new OAuth2 token request. + void StartTokenFetch(); + + // Adds the token to |request_| and starts the request. + void SetOAuth2TokenAndStartRequest(); + // The context for the request. Ensures the gdToken cookie is set as a header // in the requests to Online Wallet if it is present. scoped_refptr<net::URLRequestContextGetter> context_getter_; @@ -62,9 +82,15 @@ class RealPanWalletClient : public net::URLFetcherDelegate { // of a request to Online Wallet. Delegate* const delegate_; // must outlive |this|. - // The current request object. + // The current Wallet request object. scoped_ptr<net::URLFetcher> request_; + // The current OAuth2 token request object; + scoped_ptr<OAuth2TokenService::Request> access_token_request_; + + // The OAuth2 token, or empty if not fetched. + std::string access_token_; + base::WeakPtrFactory<RealPanWalletClient> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(RealPanWalletClient); |