password_store_win.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/password_manager/password_store_win.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <map>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/utf_string_conversions.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/ie7_password.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_manager.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/webdata/web_data_service.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::PasswordForm;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handles requests to WebDataService.
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PasswordStoreWin::DBHandler : public WebDataServiceConsumer {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DBHandler(WebDataService* web_data_service,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PasswordStoreWin* password_store)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : web_data_service_(web_data_service),
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        password_store_(password_store) {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DBHandler();
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Requests the IE7 login for |form|. This is async. |callback_runner| will be
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // run when complete.
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void GetIE7Login(
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const PasswordForm& form,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const PasswordStoreWin::ConsumerCallbackRunner& callback_runner);
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct RequestInfo {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestInfo() {}
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    RequestInfo(PasswordForm* request_form,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                const PasswordStoreWin::ConsumerCallbackRunner& runner)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        : form(request_form),
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          callback_runner(runner) {}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PasswordForm* form;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    PasswordStoreWin::ConsumerCallbackRunner callback_runner;
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Holds info associated with in-flight GetIE7Login requests.
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<WebDataService::Handle, RequestInfo> PendingRequestMap;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Gets logins from IE7 if no others are found. Also copies them into
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Chrome's WebDatabase so we don't need to look next time.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordForm* GetIE7Result(const WDTypedResult* result,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             const PasswordForm& form);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // WebDataServiceConsumer implementation.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnWebDataServiceRequestDone(
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WebDataService::Handle handle,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const WDTypedResult* result) OVERRIDE;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<WebDataService> web_data_service_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This creates a cycle between us and PasswordStore. The cycle is broken
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from PasswordStoreWin::Shutdown, which deletes us.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<PasswordStoreWin> password_store_;
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PendingRequestMap pending_requests_;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(DBHandler);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordStoreWin::DBHandler::~DBHandler() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (PendingRequestMap::const_iterator i = pending_requests_.begin();
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i != pending_requests_.end();
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       ++i) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_data_service_->CancelRequest(i->first);
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    delete i->second.form;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordStoreWin::DBHandler::GetIE7Login(
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PasswordForm& form,
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PasswordStoreWin::ConsumerCallbackRunner& callback_runner) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IE7PasswordInfo info;
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  info.url_hash = ie7_password::GetUrlHash(UTF8ToWide(form.origin.spec()));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WebDataService::Handle handle = web_data_service_->GetIE7Login(info, this);
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_requests_[handle] =
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      RequestInfo(new PasswordForm(form), callback_runner);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordForm* PasswordStoreWin::DBHandler::GetIE7Result(
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WDTypedResult *result,
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const PasswordForm& form) {
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const WDResult<IE7PasswordInfo>* r =
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<const WDResult<IE7PasswordInfo>*>(result);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IE7PasswordInfo info = r->GetValue();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info.encrypted_data.empty()) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We got a result.
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Delete the entry. If it's good we will add it to the real saved password
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // table.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    web_data_service_->RemoveIE7Login(info);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring username;
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring password;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::wstring url = ASCIIToWide(form.origin.spec());
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ie7_password::DecryptPassword(url, info.encrypted_data,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       &username, &password)) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PasswordForm* autofill = new PasswordForm(form);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    autofill->username_value = username;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    autofill->password_value = password;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    autofill->preferred = true;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    autofill->ssl_valid = form.origin.SchemeIsSecure();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    autofill->date_created = info.date_created;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add this PasswordForm to the saved password table. We're on the DB thread
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // already, so we use AddLoginImpl.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    password_store_->AddLoginImpl(*autofill);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return autofill;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreWin::DBHandler::OnWebDataServiceRequestDone(
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebDataService::Handle handle,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WDTypedResult* result) {
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PendingRequestMap::iterator i = pending_requests_.find(handle);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(i != pending_requests_.end());
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<PasswordForm> form(i->second.form);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PasswordStoreWin::ConsumerCallbackRunner callback_runner(
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      i->second.callback_runner);
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pending_requests_.erase(i);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<content::PasswordForm*> matched_forms;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!result) {
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The WDS returns NULL if it is shutting down. Run callback with empty
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // result.
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_runner.Run(matched_forms);
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(PASSWORD_IE7_RESULT, result->GetType());
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordForm* ie7_form = GetIE7Result(result, *form);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ie7_form)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    matched_forms.push_back(ie7_form);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_runner.Run(matched_forms);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordStoreWin::PasswordStoreWin(LoginDatabase* login_database,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   Profile* profile,
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   WebDataService* web_data_service)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : PasswordStoreDefault(login_database, profile) {
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_handler_.reset(new DBHandler(web_data_service, this));
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PasswordStoreWin::~PasswordStoreWin() {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreWin::ShutdownOnDBThread() {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  db_handler_.reset();
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PasswordStoreWin::ShutdownOnUIThread() {
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::DB, FROM_HERE,
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&PasswordStoreWin::ShutdownOnDBThread, this));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PasswordStoreDefault::ShutdownOnUIThread();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordStoreWin::GetIE7LoginIfNecessary(
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PasswordForm& form,
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConsumerCallbackRunner& callback_runner,
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::vector<content::PasswordForm*>& matched_forms) {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (matched_forms.empty() && db_handler_.get()) {
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    db_handler_->GetIE7Login(form, callback_runner);
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // No need to get IE7 login.
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    callback_runner.Run(matched_forms);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void PasswordStoreWin::GetLoginsImpl(
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const PasswordForm& form,
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ConsumerCallbackRunner& callback_runner) {
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ConsumerCallbackRunner get_ie7_login =
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&PasswordStoreWin::GetIE7LoginIfNecessary,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                 this, form, callback_runner);
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  PasswordStoreDefault::GetLoginsImpl(form, get_ie7_login);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
207