NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / password_manager / password_store_win.cc
blobada21dcf71fc90943c23cf33cbc1bb614b56f4d3
1 // Copyright (c) 2012 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.
5 #include "chrome/browser/password_manager/password_store_win.h"
7 #include <map>
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "chrome/browser/password_manager/password_manager.h"
15 #include "chrome/browser/webdata/web_data_service.h"
16 #include "components/webdata/encryptor/ie7_password_win.h"
17 #include "content/public/browser/browser_thread.h"
19 using autofill::PasswordForm;
20 using content::BrowserThread;
22 // Handles requests to WebDataService.
23 class PasswordStoreWin::DBHandler : public WebDataServiceConsumer {
24 public:
25 DBHandler(WebDataService* web_data_service,
26 PasswordStoreWin* password_store)
27 : web_data_service_(web_data_service),
28 password_store_(password_store) {
31 ~DBHandler();
33 // Requests the IE7 login for |form|. This is async. |callback_runner| will be
34 // run when complete.
35 void GetIE7Login(
36 const PasswordForm& form,
37 const PasswordStoreWin::ConsumerCallbackRunner& callback_runner);
39 private:
40 struct RequestInfo {
41 RequestInfo() {}
43 RequestInfo(PasswordForm* request_form,
44 const PasswordStoreWin::ConsumerCallbackRunner& runner)
45 : form(request_form),
46 callback_runner(runner) {}
48 PasswordForm* form;
49 PasswordStoreWin::ConsumerCallbackRunner callback_runner;
52 // Holds info associated with in-flight GetIE7Login requests.
53 typedef std::map<WebDataService::Handle, RequestInfo> PendingRequestMap;
55 // Gets logins from IE7 if no others are found. Also copies them into
56 // Chrome's WebDatabase so we don't need to look next time.
57 std::vector<autofill::PasswordForm*> GetIE7Results(
58 const WDTypedResult* result,
59 const PasswordForm& form);
61 // WebDataServiceConsumer implementation.
62 virtual void OnWebDataServiceRequestDone(
63 WebDataService::Handle handle,
64 const WDTypedResult* result) OVERRIDE;
66 scoped_refptr<WebDataService> web_data_service_;
68 // This creates a cycle between us and PasswordStore. The cycle is broken
69 // from PasswordStoreWin::Shutdown, which deletes us.
70 scoped_refptr<PasswordStoreWin> password_store_;
72 PendingRequestMap pending_requests_;
74 DISALLOW_COPY_AND_ASSIGN(DBHandler);
77 PasswordStoreWin::DBHandler::~DBHandler() {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
79 for (PendingRequestMap::const_iterator i = pending_requests_.begin();
80 i != pending_requests_.end();
81 ++i) {
82 web_data_service_->CancelRequest(i->first);
83 delete i->second.form;
87 void PasswordStoreWin::DBHandler::GetIE7Login(
88 const PasswordForm& form,
89 const PasswordStoreWin::ConsumerCallbackRunner& callback_runner) {
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
91 IE7PasswordInfo info;
92 info.url_hash =
93 ie7_password::GetUrlHash(base::UTF8ToWide(form.origin.spec()));
94 WebDataService::Handle handle = web_data_service_->GetIE7Login(info, this);
95 pending_requests_[handle] =
96 RequestInfo(new PasswordForm(form), callback_runner);
99 std::vector<PasswordForm*> PasswordStoreWin::DBHandler::GetIE7Results(
100 const WDTypedResult *result,
101 const PasswordForm& form) {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
103 std::vector<PasswordForm*> matching_forms;
105 const WDResult<IE7PasswordInfo>* r =
106 static_cast<const WDResult<IE7PasswordInfo>*>(result);
107 IE7PasswordInfo info = r->GetValue();
109 if (!info.encrypted_data.empty()) {
110 // We got a result.
111 // Delete the entry. If it's good we will add it to the real saved password
112 // table.
113 web_data_service_->RemoveIE7Login(info);
114 std::vector<ie7_password::DecryptedCredentials> credentials;
115 std::wstring url = base::ASCIIToWide(form.origin.spec());
116 if (ie7_password::DecryptPasswords(url,
117 info.encrypted_data,
118 &credentials)) {
119 for (size_t i = 0; i < credentials.size(); ++i) {
120 PasswordForm* autofill = new PasswordForm();
121 autofill->username_value = credentials[i].username;
122 autofill->password_value = credentials[i].password;
123 autofill->signon_realm = form.signon_realm;
124 autofill->origin = form.origin;
125 autofill->preferred = true;
126 autofill->ssl_valid = form.origin.SchemeIsSecure();
127 autofill->date_created = info.date_created;
129 matching_forms.push_back(autofill);
130 // Add this PasswordForm to the saved password table. We're on the DB
131 // thread already, so we use AddLoginImpl.
132 password_store_->AddLoginImpl(*autofill);
136 return matching_forms;
139 void PasswordStoreWin::DBHandler::OnWebDataServiceRequestDone(
140 WebDataService::Handle handle,
141 const WDTypedResult* result) {
142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
144 PendingRequestMap::iterator i = pending_requests_.find(handle);
145 DCHECK(i != pending_requests_.end());
147 scoped_ptr<PasswordForm> form(i->second.form);
148 PasswordStoreWin::ConsumerCallbackRunner callback_runner(
149 i->second.callback_runner);
150 pending_requests_.erase(i);
152 if (!result) {
153 // The WDS returns NULL if it is shutting down. Run callback with empty
154 // result.
155 callback_runner.Run(std::vector<autofill::PasswordForm*>());
156 return;
159 DCHECK_EQ(PASSWORD_IE7_RESULT, result->GetType());
160 std::vector<autofill::PasswordForm*> matched_forms =
161 GetIE7Results(result, *form);
163 callback_runner.Run(matched_forms);
166 PasswordStoreWin::PasswordStoreWin(
167 scoped_refptr<base::SingleThreadTaskRunner> main_thread_runner,
168 scoped_refptr<base::SingleThreadTaskRunner> db_thread_runner,
169 LoginDatabase* login_database,
170 WebDataService* web_data_service)
171 : PasswordStoreDefault(main_thread_runner,
172 db_thread_runner,
173 login_database) {
174 db_handler_.reset(new DBHandler(web_data_service, this));
177 PasswordStoreWin::~PasswordStoreWin() {
180 void PasswordStoreWin::ShutdownOnDBThread() {
181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
182 db_handler_.reset();
185 void PasswordStoreWin::Shutdown() {
186 BrowserThread::PostTask(
187 BrowserThread::DB, FROM_HERE,
188 base::Bind(&PasswordStoreWin::ShutdownOnDBThread, this));
189 PasswordStoreDefault::Shutdown();
192 void PasswordStoreWin::GetIE7LoginIfNecessary(
193 const PasswordForm& form,
194 const ConsumerCallbackRunner& callback_runner,
195 const std::vector<autofill::PasswordForm*>& matched_forms) {
196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
197 if (matched_forms.empty() && db_handler_.get()) {
198 db_handler_->GetIE7Login(form, callback_runner);
199 } else {
200 // No need to get IE7 login.
201 callback_runner.Run(matched_forms);
205 void PasswordStoreWin::GetLoginsImpl(
206 const PasswordForm& form,
207 AuthorizationPromptPolicy prompt_policy,
208 const ConsumerCallbackRunner& callback_runner) {
209 ConsumerCallbackRunner get_ie7_login =
210 base::Bind(&PasswordStoreWin::GetIE7LoginIfNecessary,
211 this, form, callback_runner);
212 PasswordStoreDefault::GetLoginsImpl(form, prompt_policy, get_ie7_login);