password_store_win.cc revision 58537e28ecd584eab876aee8be7156509866d23a
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" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_manager.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/webdata/web_data_service.h" 17c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "components/webdata/encryptor/ie7_password.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)using autofill::PasswordForm; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 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) 14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) std::vector<autofill::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, 18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) const std::vector<autofill::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