Home | History | Annotate | Download | only in wallet
      1 // Copyright 2013 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 "components/autofill/content/browser/wallet/wallet_signin_helper.h"
      6 
      7 #include "base/callback_helpers.h"
      8 #include "base/json/json_reader.h"
      9 #include "base/logging.h"
     10 #include "base/rand_util.h"
     11 #include "base/strings/string_util.h"
     12 #include "base/strings/stringprintf.h"
     13 #include "base/time/time.h"
     14 #include "base/values.h"
     15 #include "components/autofill/content/browser/wallet/wallet_service_url.h"
     16 #include "components/autofill/content/browser/wallet/wallet_signin_helper_delegate.h"
     17 #include "content/public/browser/browser_thread.h"
     18 #include "google_apis/gaia/google_service_auth_error.h"
     19 #include "net/base/escape.h"
     20 #include "net/cookies/canonical_cookie.h"
     21 #include "net/cookies/cookie_monster.h"
     22 #include "net/cookies/cookie_options.h"
     23 #include "net/cookies/cookie_store.h"
     24 #include "net/url_request/url_fetcher.h"
     25 #include "net/url_request/url_request_context.h"
     26 #include "net/url_request/url_request_context_getter.h"
     27 
     28 namespace autofill {
     29 namespace wallet {
     30 
     31 namespace {
     32 
     33 const char kWalletCookieName[] = "gdtoken";
     34 
     35 // Callback for retrieving Google Wallet cookies. |callback| is passed the
     36 // retrieved cookies and posted back to the UI thread. |cookies| is any Google
     37 // Wallet cookies.
     38 void GetGoogleCookiesCallback(
     39     const base::Callback<void(const std::string&)>& callback,
     40     const net::CookieList& cookies) {
     41   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
     42 
     43   // Cookies for parent domains will also be returned; we only want cookies with
     44   // exact host matches. TODO(estade): really?
     45   std::string host = wallet::GetPassiveAuthUrl(0).host();
     46   std::string wallet_cookie;
     47   for (size_t i = 0; i < cookies.size(); ++i) {
     48     if (LowerCaseEqualsASCII(cookies[i].Name(), kWalletCookieName) &&
     49         LowerCaseEqualsASCII(cookies[i].Domain(), host.c_str())) {
     50       wallet_cookie = cookies[i].Value();
     51       break;
     52     }
     53   }
     54   content::BrowserThread::PostTask(content::BrowserThread::UI,
     55                                    FROM_HERE,
     56                                    base::Bind(callback, wallet_cookie));
     57 }
     58 
     59 // Gets Google Wallet cookies. Must be called on the IO thread.
     60 // |request_context_getter| is a getter for the current request context.
     61 // |callback| is called when retrieving cookies is completed.
     62 void GetGoogleCookies(
     63     scoped_refptr<net::URLRequestContextGetter> request_context_getter,
     64     const base::Callback<void(const std::string&)>& callback) {
     65   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
     66 
     67   net::URLRequestContext* url_request_context =
     68       request_context_getter->GetURLRequestContext();
     69   net::CookieStore* cookie_store = url_request_context ?
     70       url_request_context->cookie_store() : NULL;
     71   net::CookieMonster* cookie_monster = cookie_store ?
     72       cookie_store->GetCookieMonster() : NULL;
     73   if (!cookie_monster) {
     74     content::BrowserThread::PostTask(content::BrowserThread::UI,
     75                                      FROM_HERE,
     76                                      base::Bind(callback, std::string()));
     77     return;
     78   }
     79 
     80   net::CookieOptions cookie_options;
     81   cookie_options.set_include_httponly();
     82   cookie_monster->GetAllCookiesForURLWithOptionsAsync(
     83       wallet::GetPassiveAuthUrl(0).GetWithEmptyPath(),
     84       cookie_options,
     85       base::Bind(&GetGoogleCookiesCallback, callback));
     86 }
     87 
     88 }  // namespace
     89 
     90 WalletSigninHelper::WalletSigninHelper(
     91     WalletSigninHelperDelegate* delegate,
     92     net::URLRequestContextGetter* getter)
     93     : delegate_(delegate),
     94       getter_(getter),
     95       weak_ptr_factory_(this) {
     96   DCHECK(delegate_);
     97 }
     98 
     99 WalletSigninHelper::~WalletSigninHelper() {
    100 }
    101 
    102 void WalletSigninHelper::StartPassiveSignin(size_t user_index) {
    103   DCHECK(!url_fetcher_);
    104 
    105   const GURL& url = wallet::GetPassiveAuthUrl(user_index);
    106   url_fetcher_.reset(net::URLFetcher::Create(
    107       0, url, net::URLFetcher::GET, this));
    108   url_fetcher_->SetRequestContext(getter_);
    109   url_fetcher_->Start();
    110 }
    111 
    112 void WalletSigninHelper::StartWalletCookieValueFetch() {
    113   scoped_refptr<net::URLRequestContextGetter> request_context(getter_);
    114   if (!request_context.get()) {
    115     ReturnWalletCookieValue(std::string());
    116     return;
    117   }
    118 
    119   base::Callback<void(const std::string&)> callback = base::Bind(
    120       &WalletSigninHelper::ReturnWalletCookieValue,
    121       weak_ptr_factory_.GetWeakPtr());
    122 
    123   base::Closure task = base::Bind(&GetGoogleCookies, request_context, callback);
    124   content::BrowserThread::PostTask(content::BrowserThread::IO, FROM_HERE, task);
    125 }
    126 
    127 void WalletSigninHelper::OnServiceError(const GoogleServiceAuthError& error) {
    128   delegate_->OnPassiveSigninFailure(error);
    129 }
    130 
    131 void WalletSigninHelper::OnOtherError() {
    132   OnServiceError(GoogleServiceAuthError::AuthErrorNone());
    133 }
    134 
    135 void WalletSigninHelper::OnURLFetchComplete(
    136     const net::URLFetcher* fetcher) {
    137   DCHECK_EQ(url_fetcher_.get(), fetcher);
    138   scoped_ptr<net::URLFetcher> url_fetcher(url_fetcher_.release());
    139 
    140   if (!fetcher->GetStatus().is_success() ||
    141       fetcher->GetResponseCode() < 200 ||
    142       fetcher->GetResponseCode() >= 300) {
    143     DVLOG(1) << "URLFetchFailure:"
    144              << " r=" << fetcher->GetResponseCode()
    145              << " s=" << fetcher->GetStatus().status()
    146              << " e=" << fetcher->GetStatus().error();
    147     OnOtherError();
    148     return;
    149   }
    150 
    151   std::string data;
    152   if (!fetcher->GetResponseAsString(&data)) {
    153     DVLOG(1) << "failed to GetResponseAsString";
    154     OnOtherError();
    155     return;
    156   }
    157 
    158   if (!LowerCaseEqualsASCII(data, "yes")) {
    159     OnServiceError(
    160         GoogleServiceAuthError(GoogleServiceAuthError::USER_NOT_SIGNED_UP));
    161     return;
    162   }
    163 
    164   delegate_->OnPassiveSigninSuccess();
    165 }
    166 
    167 void WalletSigninHelper::ReturnWalletCookieValue(
    168     const std::string& cookie_value) {
    169   DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
    170 
    171   delegate_->OnDidFetchWalletCookieValue(cookie_value);
    172 }
    173 
    174 }  // namespace wallet
    175 }  // namespace autofill
    176