summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/password_manager/password_form_data.h54
-rw-r--r--chrome/browser/password_manager/password_store.h22
-rw-r--r--chrome/browser/password_manager/password_store_default.cc158
-rw-r--r--chrome/browser/password_manager/password_store_default.h63
-rw-r--r--chrome/browser/password_manager/password_store_default_unittest.cc (renamed from chrome/browser/password_manager/password_store_linux_unittest.cc)92
-rw-r--r--chrome/browser/password_manager/password_store_linux.cc100
-rw-r--r--chrome/browser/password_manager/password_store_linux.h61
-rw-r--r--chrome/browser/password_manager/password_store_win.cc119
-rw-r--r--chrome/browser/password_manager/password_store_win.h28
-rw-r--r--chrome/browser/password_manager/password_store_win_unittest.cc327
-rw-r--r--chrome/browser/profile.cc31
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi4
13 files changed, 576 insertions, 485 deletions
diff --git a/chrome/browser/password_manager/password_form_data.h b/chrome/browser/password_manager/password_form_data.h
index 0bfa487..04b78df 100644
--- a/chrome/browser/password_manager/password_form_data.h
+++ b/chrome/browser/password_manager/password_form_data.h
@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_DATA_H_
#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_DATA_H_
+#include "testing/gmock/include/gmock/gmock.h"
#include "webkit/glue/password_form.h"
// Struct used for creation of PasswordForms from static arrays of data.
@@ -29,4 +30,57 @@ struct PasswordFormData {
webkit_glue::PasswordForm* CreatePasswordFormFromData(
const PasswordFormData& form_data);
+typedef std::set<webkit_glue::PasswordForm*> SetOfForms;
+
+// This gmock matcher is used to check that the |arg| contains exactly the same
+// PasswordForms as |forms|, regardless of order.
+MATCHER_P(ContainsAllPasswordForms, forms, "") {
+ if (forms.size() != arg.size())
+ return false;
+ SetOfForms expectations(forms.begin(), forms.end());
+ for (unsigned int i = 0; i < arg.size(); ++i) {
+ webkit_glue::PasswordForm* actual = arg[i];
+ bool found_match = false;
+ for (SetOfForms::iterator it = expectations.begin();
+ it != expectations.end(); ++it) {
+ webkit_glue::PasswordForm* expected = *it;
+ if (expected->scheme == actual->scheme &&
+ expected->signon_realm == actual->signon_realm &&
+ expected->origin == actual->origin &&
+ expected->action == actual->action &&
+ expected->submit_element == actual->submit_element &&
+ expected->username_element == actual->username_element &&
+ expected->password_element == actual->password_element &&
+ expected->username_value == actual->username_value &&
+ expected->password_value == actual->password_value &&
+ expected->blacklisted_by_user == actual->blacklisted_by_user &&
+ expected->preferred == actual->preferred &&
+ expected->ssl_valid == actual->ssl_valid &&
+ expected->date_created == actual->date_created) {
+ found_match = true;
+ expectations.erase(it);
+ break;
+ }
+ }
+ if (!found_match) {
+ LOG(ERROR) << "No match for:" << std::endl
+ << "scheme: " << actual->scheme << std::endl
+ << "signon_realm: " << actual->signon_realm << std::endl
+ << "origin: " << actual->origin << std::endl
+ << "action: " << actual->action << std::endl
+ << "submit_element: " << actual->submit_element << std::endl
+ << "username_elem: " << actual->username_element << std::endl
+ << "password_elem: " << actual->password_element << std::endl
+ << "username_value: " << actual->username_value << std::endl
+ << "password_value: " << actual->password_value << std::endl
+ << "blacklisted: " << actual->blacklisted_by_user << std::endl
+ << "preferred: " << actual->preferred << std::endl
+ << "ssl_valid: " << actual->ssl_valid << std::endl
+ << "date_created: " << actual->date_created.ToDoubleT();
+ return false;
+ }
+ }
+ return true;
+}
+
#endif // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_FORM_DATA_H_
diff --git a/chrome/browser/password_manager/password_store.h b/chrome/browser/password_manager/password_store.h
index f963611..d105240 100644
--- a/chrome/browser/password_manager/password_store.h
+++ b/chrome/browser/password_manager/password_store.h
@@ -35,21 +35,18 @@ class PasswordStore : public base::RefCountedThreadSafe<PasswordStore> {
// Reimplement this to add custom initialization. Always call this too.
virtual bool Init();
- // TODO(stuartmorgan): These are only virtual to support the shim version of
- // password_store_default; once that is fixed, they can become non-virtual.
-
// Adds the given PasswordForm to the secure password store asynchronously.
virtual void AddLogin(const webkit_glue::PasswordForm& form);
// Updates the matching PasswordForm in the secure password store (async).
- virtual void UpdateLogin(const webkit_glue::PasswordForm& form);
+ void UpdateLogin(const webkit_glue::PasswordForm& form);
// Removes the matching PasswordForm from the secure password store (async).
- virtual void RemoveLogin(const webkit_glue::PasswordForm& form);
+ void RemoveLogin(const webkit_glue::PasswordForm& form);
// Removes all logins created in the given date range.
- virtual void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
- const base::Time& delete_end);
+ void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
+ const base::Time& delete_end);
// Searches for a matching PasswordForm and returns a handle so the async
// request can be tracked. Implement the PasswordStoreConsumer interface to
@@ -61,15 +58,15 @@ class PasswordStore : public base::RefCountedThreadSafe<PasswordStore> {
// are thus auto-fillable--and returns a handle so the async request can be
// tracked. Implement the PasswordStoreConsumer interface to be notified
// on completion.
- virtual int GetAutofillableLogins(PasswordStoreConsumer* consumer);
+ int GetAutofillableLogins(PasswordStoreConsumer* consumer);
// Gets the complete list of PasswordForms that are blacklist entries, and
// returns a handle so the async request can be tracked. Implement the
// PasswordStoreConsumer interface to be notified on completion.
- virtual int GetBlacklistLogins(PasswordStoreConsumer* consumer);
+ int GetBlacklistLogins(PasswordStoreConsumer* consumer);
// Cancels a previous Get*Logins query (async)
- virtual void CancelLoginsQuery(int handle);
+ void CancelLoginsQuery(int handle);
protected:
friend class base::RefCountedThreadSafe<PasswordStore>;
@@ -117,8 +114,9 @@ class PasswordStore : public base::RefCountedThreadSafe<PasswordStore> {
virtual void GetBlacklistLoginsImpl(GetLoginsRequest* request) = 0;
// Notifies the consumer that a Get*Logins() request is complete.
- void NotifyConsumer(GetLoginsRequest* request,
- const std::vector<webkit_glue::PasswordForm*> forms);
+ virtual void NotifyConsumer(
+ GetLoginsRequest* request,
+ const std::vector<webkit_glue::PasswordForm*> forms);
private:
// Called by NotifyConsumer, but runs in the consumer's thread. Will not
diff --git a/chrome/browser/password_manager/password_store_default.cc b/chrome/browser/password_manager/password_store_default.cc
index c27d932..0628294 100644
--- a/chrome/browser/password_manager/password_store_default.cc
+++ b/chrome/browser/password_manager/password_store_default.cc
@@ -1,152 +1,100 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/password_manager/password_store_default.h"
+#include "chrome/browser/pref_service.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/chrome_constants.h"
+#include "chrome/common/pref_names.h"
#include "base/logging.h"
#include "base/task.h"
using webkit_glue::PasswordForm;
-PasswordStoreDefault::PasswordStoreDefault(WebDataService* web_data_service)
- : web_data_service_(web_data_service), handle_(0) {
+PasswordStoreDefault::PasswordStoreDefault(LoginDatabase* login_db,
+ Profile* profile,
+ WebDataService* web_data_service)
+ : web_data_service_(web_data_service),
+ login_db_(login_db), profile_(profile) {
+ DCHECK(login_db);
+ DCHECK(profile);
+ DCHECK(web_data_service);
+ MigrateIfNecessary();
}
PasswordStoreDefault::~PasswordStoreDefault() {
- for (PendingRequestMap::const_iterator it = pending_requests_.begin();
- it != pending_requests_.end(); ++it) {
- web_data_service_->CancelRequest(it->first);
- }
-}
-
-// Override all the public methods to avoid passthroughs to the Impl
-// versions. Since we are calling through to WebDataService, which is
-// asynchronous, we'll still behave as the caller expects.
-void PasswordStoreDefault::AddLogin(const PasswordForm& form) {
- web_data_service_->AddLogin(form);
-}
-
-void PasswordStoreDefault::UpdateLogin(const PasswordForm& form) {
- web_data_service_->UpdateLogin(form);
-}
-
-void PasswordStoreDefault::RemoveLogin(const PasswordForm& form) {
- web_data_service_->RemoveLogin(form);
-}
-
-void PasswordStoreDefault::RemoveLoginsCreatedBetween(
- const base::Time& delete_begin, const base::Time& delete_end) {
- web_data_service_->RemoveLoginsCreatedBetween(delete_begin, delete_end);
}
-int PasswordStoreDefault::GetLogins(const PasswordForm& form,
- PasswordStoreConsumer* consumer) {
- WebDataService::Handle web_data_handle = web_data_service_->GetLogins(form,
- this);
- return CreateNewRequestForQuery(web_data_handle, consumer);
-}
-
-int PasswordStoreDefault::GetAutofillableLogins(
- PasswordStoreConsumer* consumer) {
- WebDataService::Handle web_data_handle =
- web_data_service_->GetAutofillableLogins(this);
- return CreateNewRequestForQuery(web_data_handle, consumer);
-}
-
-int PasswordStoreDefault::GetBlacklistLogins(
- PasswordStoreConsumer* consumer) {
- WebDataService::Handle web_data_handle =
- web_data_service_->GetBlacklistLogins(this);
- return CreateNewRequestForQuery(web_data_handle, consumer);
-}
-
-void PasswordStoreDefault::CancelLoginsQuery(int handle) {
- for (PendingRequestMap::iterator it = pending_requests_.begin();
- it != pending_requests_.end(); ++it) {
- GetLoginsRequest* request = it->second;
- if (request->handle == handle) {
- web_data_service_->CancelRequest(it->first);
- delete request;
- pending_requests_.erase(it);
- return;
- }
- }
+void PasswordStoreDefault::AddLoginImpl(const PasswordForm& form) {
+ login_db_->AddLogin(form);
}
-void PasswordStoreDefault::AddLoginImpl(const PasswordForm& form) {
- NOTREACHED();
+void PasswordStoreDefault::UpdateLoginImpl(const PasswordForm& form) {
+ login_db_->UpdateLogin(form, NULL);
}
void PasswordStoreDefault::RemoveLoginImpl(const PasswordForm& form) {
- NOTREACHED();
+ login_db_->RemoveLogin(form);
}
void PasswordStoreDefault::RemoveLoginsCreatedBetweenImpl(
const base::Time& delete_begin, const base::Time& delete_end) {
- NOTREACHED();
-}
-
-void PasswordStoreDefault::UpdateLoginImpl(const PasswordForm& form) {
- NOTREACHED();
+ login_db_->RemoveLoginsCreatedBetween(delete_begin, delete_end);
}
void PasswordStoreDefault::GetLoginsImpl(
GetLoginsRequest* request, const webkit_glue::PasswordForm& form) {
- NOTREACHED();
+ std::vector<PasswordForm*> forms;
+ login_db_->GetLogins(form, &forms);
+ NotifyConsumer(request, forms);
}
void PasswordStoreDefault::GetAutofillableLoginsImpl(
GetLoginsRequest* request) {
- NOTREACHED();
+ std::vector<PasswordForm*> forms;
+ login_db_->GetAutofillableLogins(&forms);
+ NotifyConsumer(request, forms);
}
void PasswordStoreDefault::GetBlacklistLoginsImpl(
GetLoginsRequest* request) {
- NOTREACHED();
+ std::vector<PasswordForm*> forms;
+ login_db_->GetBlacklistLogins(&forms);
+ NotifyConsumer(request, forms);
}
-void PasswordStoreDefault::OnWebDataServiceRequestDone(
- WebDataService::Handle h,
- const WDTypedResult *result) {
- scoped_ptr<GetLoginsRequest> request(TakeRequestWithHandle(h));
- // If the request was cancelled, we are done.
- if (!request.get())
- return;
-
- DCHECK(result);
- if (!result)
+void PasswordStoreDefault::MigrateIfNecessary() {
+ PrefService* prefs = profile_->GetPrefs();
+ if (prefs->FindPreference(prefs::kLoginDatabaseMigrated))
return;
-
- const WDResult<std::vector<PasswordForm*> >* r =
- static_cast<const WDResult<std::vector<PasswordForm*> >*>(result);
-
- request->consumer->OnPasswordStoreRequestDone(request->handle,
- r->GetValue());
+ handles_.insert(web_data_service_->GetAutofillableLogins(this));
+ handles_.insert(web_data_service_->GetBlacklistLogins(this));
}
-PasswordStoreDefault::GetLoginsRequest*
- PasswordStoreDefault::TakeRequestWithHandle(WebDataService::Handle handle) {
- PendingRequestMap::iterator it(pending_requests_.find(handle));
- if (it == pending_requests_.end())
- return NULL;
+typedef std::vector<const PasswordForm*> PasswordForms;
- GetLoginsRequest* request = it->second;
- pending_requests_.erase(it);
- return request;
-}
+void PasswordStoreDefault::OnWebDataServiceRequestDone(
+ WebDataService::Handle handle,
+ const WDTypedResult *result) {
+ DCHECK(handles_.end() != handles_.find(handle));
+ DCHECK(result);
-int PasswordStoreDefault::CreateNewRequestForQuery(
- WebDataService::Handle web_data_handle, PasswordStoreConsumer* consumer) {
- int api_handle = handle_++;
- GetLoginsRequest* request = new GetLoginsRequest(consumer, api_handle);
- TrackRequest(web_data_handle, request);
- return api_handle;
-}
+ handles_.erase(handle);
+ if (!result)
+ return;
-void PasswordStoreDefault::TrackRequest(WebDataService::Handle handle,
- GetLoginsRequest* request) {
- pending_requests_.insert(PendingRequestMap::value_type(handle, request));
+ const PasswordForms& forms =
+ static_cast<const WDResult<PasswordForms>*>(result)->GetValue();
+ for (PasswordForms::const_iterator it = forms.begin();
+ it != forms.end(); ++it) {
+ AddLoginImpl(**it);
+ web_data_service_->RemoveLogin(**it);
+ delete *it;
+ }
+ if (handles_.empty()) {
+ profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated,
+ true);
+ }
}
diff --git a/chrome/browser/password_manager/password_store_default.h b/chrome/browser/password_manager/password_store_default.h
index 2c26a7b..5ca06ca 100644
--- a/chrome/browser/password_manager/password_store_default.h
+++ b/chrome/browser/password_manager/password_store_default.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -10,34 +10,22 @@
#include "base/file_path.h"
#include "base/ref_counted.h"
#include "base/scoped_ptr.h"
+#include "chrome/browser/password_manager/login_database.h"
#include "chrome/browser/password_manager/password_store.h"
+#include "chrome/browser/profile.h"
#include "chrome/browser/webdata/web_data_service.h"
class Task;
// Simple password store implementation that delegates everything to
-// the WebDatabase.
-// TODO(stuartmorgan): This is a temprorary shim for Windows from the new
-// PasswordStore interface to the old model of storing passwords in the
-// WebDatabase. This should be replaced by a self-contained Windows
-// implementation once PasswordStore is completed.
+// the LoginDatabase.
class PasswordStoreDefault : public PasswordStore,
public WebDataServiceConsumer {
public:
- explicit PasswordStoreDefault(WebDataService* web_data_service);
-
- // Overridden to bypass the threading logic in PasswordStore, since
- // WebDataService's API is not threadsafe.
- virtual void AddLogin(const webkit_glue::PasswordForm& form);
- virtual void UpdateLogin(const webkit_glue::PasswordForm& form);
- virtual void RemoveLogin(const webkit_glue::PasswordForm& form);
- virtual void RemoveLoginsCreatedBetween(const base::Time& delete_begin,
- const base::Time& delete_end);
- virtual int GetLogins(const webkit_glue::PasswordForm& form,
- PasswordStoreConsumer* consumer);
- virtual int GetAutofillableLogins(PasswordStoreConsumer* consumer);
- virtual int GetBlacklistLogins(PasswordStoreConsumer* consumer);
- virtual void CancelLoginsQuery(int handle);
+ // Takes ownership of |login_db|.
+ PasswordStoreDefault(LoginDatabase* login_db,
+ Profile* profile,
+ WebDataService* web_data_service);
protected:
virtual ~PasswordStoreDefault();
@@ -53,37 +41,20 @@ class PasswordStoreDefault : public PasswordStore,
void GetAutofillableLoginsImpl(GetLoginsRequest* request);
void GetBlacklistLoginsImpl(GetLoginsRequest* request);
- // Called when a WebDataService method finishes.
- virtual void OnWebDataServiceRequestDone(WebDataService::Handle h,
- const WDTypedResult* result);
-
- // Finds the GetLoginsRequest associated with the in-flight WebDataService
- // request identified by |handle|, removes it from the tracking list, and
- // returns it. Ownership of the GetLoginsRequest passes to the caller.
- // Returns NULL if the request has been cancelled.
- GetLoginsRequest* TakeRequestWithHandle(WebDataService::Handle handle);
-
- // Takes ownership of |request| and tracks it under |handle|.
- void TrackRequest(WebDataService::Handle handle, GetLoginsRequest* request);
-
scoped_refptr<WebDataService> web_data_service_;
private:
- // Creates a new request, stored in pending_requests_, for the given
- // WebDataService query, and returns the request handle that should be used
- // for it in the client API.
- int CreateNewRequestForQuery(WebDataService::Handle web_data_handle,
- PasswordStoreConsumer* consumer);
+ // Migrates logins from the WDS to the LoginDatabase.
+ void MigrateIfNecessary();
+
+ // Implements the WebDataService consumer interface.
+ void OnWebDataServiceRequestDone(WebDataService::Handle handle,
+ const WDTypedResult *result);
- // Next handle to return from our Get*Logins() overrides to allow callers to
- // track their request.
- int handle_;
+ scoped_ptr<LoginDatabase> login_db_;
+ Profile* profile_;
- // Methods in this class call async WebDataService methods. This mapping
- // remembers which WebDataService request corresponds to which PasswordStore
- // request.
- typedef std::map<WebDataService::Handle, GetLoginsRequest*> PendingRequestMap;
- PendingRequestMap pending_requests_;
+ std::set<WebDataService::Handle> handles_;
DISALLOW_COPY_AND_ASSIGN(PasswordStoreDefault);
};
diff --git a/chrome/browser/password_manager/password_store_linux_unittest.cc b/chrome/browser/password_manager/password_store_default_unittest.cc
index c93c9f24..b94a361 100644
--- a/chrome/browser/password_manager/password_store_linux_unittest.cc
+++ b/chrome/browser/password_manager/password_store_default_unittest.cc
@@ -9,12 +9,9 @@
#include "base/time.h"
#include "base/waitable_event.h"
#include "chrome/browser/password_manager/password_store_change.h"
-#include "chrome/browser/password_manager/password_store_linux.h"
+#include "chrome/browser/password_manager/password_store_default.h"
#include "chrome/browser/password_manager/password_form_data.h"
#include "chrome/browser/webdata/web_data_service.h"
-#include "chrome/common/notification_details.h"
-#include "chrome/common/notification_service.h"
-#include "chrome/common/notification_type.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/testing_profile.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -28,9 +25,6 @@ using webkit_glue::PasswordForm;
namespace {
-typedef std::vector<PasswordForm*> VectorOfForms;
-typedef std::set<PasswordForm*> SetOfForms;
-
class MockPasswordStoreConsumer : public PasswordStoreConsumer {
public:
MOCK_METHOD2(OnPasswordStoreRequestDone,
@@ -43,9 +37,24 @@ class MockWebDataServiceConsumer : public WebDataServiceConsumer {
const WDTypedResult*));
};
-class PasswordStoreLinuxTest : public testing::Test {
+class SignalingTask : public Task {
+ public:
+ explicit SignalingTask(WaitableEvent* event) : event_(event) {
+ }
+ virtual void Run() {
+ event_->Signal();
+ }
+ private:
+ WaitableEvent* event_;
+};
+
+} // anonymous namespace
+
+typedef std::vector<PasswordForm*> VectorOfForms;
+
+class PasswordStoreDefaultTest : public testing::Test {
protected:
- PasswordStoreLinuxTest()
+ PasswordStoreDefaultTest()
: ui_thread_(ChromeThread::UI, &message_loop_),
db_thread_(ChromeThread::DB) {
}
@@ -81,19 +90,6 @@ class PasswordStoreLinuxTest : public testing::Test {
ScopedTempDir temp_dir_;
};
-class SignalingTask : public Task {
- public:
- explicit SignalingTask(WaitableEvent* event) : event_(event) {
- }
- virtual void Run() {
- event_->Signal();
- }
- private:
- WaitableEvent* event_;
-};
-
-} // anonymous namespace
-
ACTION(STLDeleteElements0) {
STLDeleteContainerPointers(arg0.begin(), arg0.end());
}
@@ -103,51 +99,12 @@ ACTION(QuitUIMessageLoop) {
MessageLoop::current()->Quit();
}
-// This matcher is used to check that the |arg| contains exactly the same
-// PasswordForms as |forms|, regardless of order.
-// TODO(albertb): Convince GMock to pretty-print PasswordForms instead of just
-// printing pointers when expectations fail.
-MATCHER_P(ContainsAllPasswordForms, forms, "") {
- if (forms.size() != arg.size())
- return false;
- SetOfForms expectations(forms.begin(), forms.end());
- for (unsigned int i = 0; i < arg.size(); ++i) {
- PasswordForm* actual = arg[i];
- bool found_match = false;
- for (SetOfForms::iterator it = expectations.begin();
- it != expectations.end(); ++it) {
- PasswordForm* expected = *it;
- if (expected->scheme == actual->scheme &&
- expected->signon_realm == actual->signon_realm &&
- expected->origin == actual->origin &&
- expected->action == actual->action &&
- expected->submit_element == actual->submit_element &&
- expected->username_element == actual->username_element &&
- expected->password_element == actual->password_element &&
- expected->username_value == actual->username_value &&
- expected->password_value == actual->password_value &&
- expected->blacklisted_by_user == actual->blacklisted_by_user &&
- expected->preferred == actual->preferred &&
- expected->ssl_valid == actual->ssl_valid &&
- expected->date_created == actual->date_created) {
- found_match = true;
- expectations.erase(it);
- break;
- }
- }
- if (!found_match) {
- return false;
- }
- }
- return true; // Both forms and arg are empty.
-}
-
MATCHER(EmptyWDResult,"") {
return static_cast<const WDResult<std::vector<PasswordForm*> >*>(
arg)->GetValue().empty();
}
-TEST_F(PasswordStoreLinuxTest, Migration) {
+TEST_F(PasswordStoreDefaultTest, Migration) {
PasswordFormData autofillable_data[] = {
{ PasswordForm::SCHEME_HTML,
"http://foo.example.com",
@@ -232,8 +189,8 @@ TEST_F(PasswordStoreLinuxTest, Migration) {
done.Wait();
// Initializing the PasswordStore should trigger a migration.
- scoped_refptr<PasswordStoreLinux> store(
- new PasswordStoreLinux(login_db_.release(), profile_.get(), wds_.get()));
+ scoped_refptr<PasswordStoreDefault> store(
+ new PasswordStoreDefault(login_db_.release(), profile_.get(), wds_.get()));
store->Init();
// Check that the migration preference has not been initialized;
@@ -309,7 +266,7 @@ TEST_F(PasswordStoreLinuxTest, Migration) {
STLDeleteElements(&expected_blacklisted);
}
-TEST_F(PasswordStoreLinuxTest, MigrationAlreadyDone) {
+TEST_F(PasswordStoreDefaultTest, MigrationAlreadyDone) {
PasswordFormData wds_data[] = {
{ PasswordForm::SCHEME_HTML,
"http://bar.example.com",
@@ -346,8 +303,9 @@ TEST_F(PasswordStoreLinuxTest, MigrationAlreadyDone) {
true);
// Initializing the PasswordStore shouldn't trigger a migration.
- scoped_refptr<PasswordStoreLinux> store(
- new PasswordStoreLinux(login_db_.release(), profile_.get(), wds_.get()));
+ scoped_refptr<PasswordStoreDefault> store(
+ new PasswordStoreDefault(login_db_.release(), profile_.get(),
+ wds_.get()));
store->Init();
MockPasswordStoreConsumer consumer;
diff --git a/chrome/browser/password_manager/password_store_linux.cc b/chrome/browser/password_manager/password_store_linux.cc
deleted file mode 100644
index 481d861..0000000
--- a/chrome/browser/password_manager/password_store_linux.cc
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/password_manager/password_store_linux.h"
-#include "chrome/browser/pref_service.h"
-#include "chrome/browser/webdata/web_data_service.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/pref_names.h"
-
-#include "base/logging.h"
-#include "base/task.h"
-
-using webkit_glue::PasswordForm;
-
-PasswordStoreLinux::PasswordStoreLinux(LoginDatabase* login_db,
- Profile* profile,
- WebDataService* web_data_service)
- : login_db_(login_db), profile_(profile),
- web_data_service_(web_data_service) {
- DCHECK(login_db);
- DCHECK(profile);
- DCHECK(web_data_service);
- MigrateIfNecessary();
-}
-
-PasswordStoreLinux::~PasswordStoreLinux() {
-}
-
-void PasswordStoreLinux::AddLoginImpl(const PasswordForm& form) {
- login_db_->AddLogin(form);
-}
-
-void PasswordStoreLinux::UpdateLoginImpl(const PasswordForm& form) {
- login_db_->UpdateLogin(form, NULL);
-}
-
-void PasswordStoreLinux::RemoveLoginImpl(const PasswordForm& form) {
- login_db_->RemoveLogin(form);
-}
-
-void PasswordStoreLinux::RemoveLoginsCreatedBetweenImpl(
- const base::Time& delete_begin, const base::Time& delete_end) {
- login_db_->RemoveLoginsCreatedBetween(delete_begin, delete_end);
-}
-
-void PasswordStoreLinux::GetLoginsImpl(
- GetLoginsRequest* request, const webkit_glue::PasswordForm& form) {
- std::vector<PasswordForm*> forms;
- login_db_->GetLogins(form, &forms);
- NotifyConsumer(request, forms);
-}
-
-void PasswordStoreLinux::GetAutofillableLoginsImpl(
- GetLoginsRequest* request) {
- std::vector<PasswordForm*> forms;
- login_db_->GetAutofillableLogins(&forms);
- NotifyConsumer(request, forms);
-}
-
-void PasswordStoreLinux::GetBlacklistLoginsImpl(
- GetLoginsRequest* request) {
- std::vector<PasswordForm*> forms;
- login_db_->GetBlacklistLogins(&forms);
- NotifyConsumer(request, forms);
-}
-
-void PasswordStoreLinux::MigrateIfNecessary() {
- PrefService* prefs = profile_->GetPrefs();
- if (prefs->FindPreference(prefs::kLoginDatabaseMigrated))
- return;
- handles_.insert(web_data_service_->GetAutofillableLogins(this));
- handles_.insert(web_data_service_->GetBlacklistLogins(this));
-}
-
-typedef std::vector<const PasswordForm*> PasswordForms;
-
-void PasswordStoreLinux::OnWebDataServiceRequestDone(
- WebDataService::Handle handle,
- const WDTypedResult *result) {
- DCHECK(handles_.end() != handles_.find(handle));
- DCHECK(result);
-
- handles_.erase(handle);
- if (!result)
- return;
-
- const PasswordForms& forms =
- static_cast<const WDResult<PasswordForms>*>(result)->GetValue();
- for (PasswordForms::const_iterator it = forms.begin();
- it != forms.end(); ++it) {
- AddLoginImpl(**it);
- web_data_service_->RemoveLogin(**it);
- delete *it;
- }
- if (handles_.empty()) {
- profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated,
- true);
- }
-}
diff --git a/chrome/browser/password_manager/password_store_linux.h b/chrome/browser/password_manager/password_store_linux.h
deleted file mode 100644
index d3c6f59..0000000
--- a/chrome/browser/password_manager/password_store_linux.h
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_LINUX_H_
-#define CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_LINUX_H_
-
-#include <map>
-
-#include "base/file_path.h"
-#include "base/ref_counted.h"
-#include "base/scoped_ptr.h"
-#include "chrome/browser/password_manager/login_database.h"
-#include "chrome/browser/password_manager/password_store.h"
-#include "chrome/browser/profile.h"
-#include "chrome/browser/webdata/web_data_service.h"
-
-class Task;
-
-// Simple password store implementation that delegates everything to
-// the LoginDatabase.
-class PasswordStoreLinux : public PasswordStore,
- public WebDataServiceConsumer {
- public:
- // Takes ownership of |login_db|.
- PasswordStoreLinux(LoginDatabase* login_db,
- Profile* profile,
- WebDataService* web_data_service);
-
- protected:
- virtual ~PasswordStoreLinux();
-
- // Implements PasswordStore interface.
- void AddLoginImpl(const webkit_glue::PasswordForm& form);
- void UpdateLoginImpl(const webkit_glue::PasswordForm& form);
- void RemoveLoginImpl(const webkit_glue::PasswordForm& form);
- void RemoveLoginsCreatedBetweenImpl(const base::Time& delete_begin,
- const base::Time& delete_end);
- void GetLoginsImpl(GetLoginsRequest* request,
- const webkit_glue::PasswordForm& form);
- void GetAutofillableLoginsImpl(GetLoginsRequest* request);
- void GetBlacklistLoginsImpl(GetLoginsRequest* request);
-
- private:
- // Migrates logins from the WDS to the LoginDatabase.
- void MigrateIfNecessary();
-
- // Implements the WebDataService consumer interface.
- void OnWebDataServiceRequestDone(WebDataService::Handle handle,
- const WDTypedResult *result);
-
- scoped_ptr<LoginDatabase> login_db_;
- Profile* profile_;
- scoped_refptr<WebDataService> web_data_service_;
-
- std::set<WebDataService::Handle> handles_;
-
- DISALLOW_COPY_AND_ASSIGN(PasswordStoreLinux);
-};
-
-#endif // CHROME_BROWSER_PASSWORD_MANAGER_PASSWORD_STORE_LINUX_H_
diff --git a/chrome/browser/password_manager/password_store_win.cc b/chrome/browser/password_manager/password_store_win.cc
index 1e5a6c6..3280f40 100644
--- a/chrome/browser/password_manager/password_store_win.cc
+++ b/chrome/browser/password_manager/password_store_win.cc
@@ -14,13 +14,17 @@ using std::map;
using std::vector;
using webkit_glue::PasswordForm;
-PasswordStoreWin::PasswordStoreWin(WebDataService* web_data_service)
- : PasswordStoreDefault(web_data_service) {
+PasswordStoreWin::PasswordStoreWin(LoginDatabase* login_database,
+ Profile* profile,
+ WebDataService* web_data_service)
+ : PasswordStoreDefault(login_database, profile, web_data_service) {
}
-void PasswordStoreWin::CancelLoginsQuery(int handle) {
- PasswordStoreDefault::CancelLoginsQuery(handle);
- DeleteFormForRequest(handle);
+PasswordStoreWin::~PasswordStoreWin() {
+ for (PendingRequestMap::const_iterator it = pending_requests_.begin();
+ it != pending_requests_.end(); ++it) {
+ web_data_service_->CancelRequest(it->first);
+ }
}
int PasswordStoreWin::GetLogins(const webkit_glue::PasswordForm& form,
@@ -31,82 +35,73 @@ int PasswordStoreWin::GetLogins(const webkit_glue::PasswordForm& form,
return request_handle;
}
+void PasswordStoreWin::NotifyConsumer(GetLoginsRequest* request,
+ const std::vector<PasswordForm*> forms) {
+ if (!forms.empty()) {
+ pending_request_forms_.erase(request->handle);
+ PasswordStore::NotifyConsumer(request, forms);
+ } else {
+ PendingRequestFormMap::iterator it(pending_request_forms_.find(
+ request->handle));
+ if (it != pending_request_forms_.end()) {
+ IE7PasswordInfo info;
+ std::wstring url = ASCIIToWide(it->second.origin.spec());
+ info.url_hash = ie7_password::GetUrlHash(url);
+ WebDataService::Handle handle = web_data_service_->GetIE7Login(info,
+ this);
+ TrackRequest(handle, request);
+ }
+ }
+}
+
void PasswordStoreWin::OnWebDataServiceRequestDone(
- WebDataService::Handle h, const WDTypedResult *result) {
- scoped_ptr<GetLoginsRequest> request(TakeRequestWithHandle(h));
+ WebDataService::Handle handle, const WDTypedResult *result) {
+ scoped_ptr<GetLoginsRequest> request(TakeRequestWithHandle(handle));
// If the request was cancelled, we are done.
if (!request.get())
return;
- DCHECK(result);
if (!result)
- return;
+ return; // The WDS returns NULL if it is shutting down.
- switch (result->GetType()) {
- case PASSWORD_RESULT: {
- // This is a response from a WebDataService::Get*Logins method.
- const WDResult<std::vector<PasswordForm*> >* r =
- static_cast<const WDResult<std::vector<PasswordForm*> >*>(result);
- std::vector<PasswordForm*> result_value = r->GetValue();
-
- if (result_value.size()) {
- // If we found some results then return them now.
- CompleteRequest(request.get(), result_value);
- return;
- } else {
- // Otherwise try finding IE7 logins if we were looking for a specific
- // page.
- PendingRequestFormMap::iterator it(pending_request_forms_.find(
- request->handle));
- if (it != pending_request_forms_.end()) {
- IE7PasswordInfo info;
- std::wstring url = ASCIIToWide(it->second.origin.spec());
- info.url_hash = ie7_password::GetUrlHash(url);
-
- if (web_data_service_->IsRunning()) {
- WebDataService::Handle web_data_handle =
- web_data_service_->GetIE7Login(info, this);
- TrackRequest(web_data_handle, request.release());
- }
- }
- }
- break;
- }
+ if (PASSWORD_IE7_RESULT == result->GetType()) {
+ // This is a response from WebDataService::GetIE7Login.
+ PendingRequestFormMap::iterator it(pending_request_forms_.find(
+ request->handle));
+ DCHECK(pending_request_forms_.end() != it);
+ PasswordForm* ie7_form = GetIE7Result(result, it->second);
- case PASSWORD_IE7_RESULT: {
- // This is a response from WebDataService::GetIE7Login.
- PendingRequestFormMap::iterator it(pending_request_forms_.find(
- request->handle));
- PasswordForm* ie7_form = GetIE7Result(result, it->second);
+ std::vector<PasswordForm*> forms;
+ if (ie7_form)
+ forms.push_back(ie7_form);
- std::vector<PasswordForm*> forms;
- if (ie7_form)
- forms.push_back(ie7_form);
-
- CompleteRequest(request.get(), forms);
- break;
- }
+ pending_request_forms_.erase(it);
+ PasswordStore::NotifyConsumer(request.release(), forms);
+ } else {
+ NOTREACHED();
}
}
-void PasswordStoreWin::DeleteFormForRequest(int handle) {
- PendingRequestFormMap::iterator it(pending_request_forms_.find(handle));
- if (it != pending_request_forms_.end()) {
- pending_request_forms_.erase(it);
- }
+void PasswordStoreWin::TrackRequest(WebDataService::Handle handle,
+ GetLoginsRequest* request) {
+ pending_requests_.insert(PendingRequestMap::value_type(handle, request));
}
-void PasswordStoreWin::CompleteRequest(
- GetLoginsRequest* request,
- const std::vector<webkit_glue::PasswordForm*>& forms) {
- DeleteFormForRequest(request->handle);
- request->consumer->OnPasswordStoreRequestDone(request->handle, forms);
+PasswordStoreDefault::GetLoginsRequest*
+ PasswordStoreWin::TakeRequestWithHandle(WebDataService::Handle handle) {
+ PendingRequestMap::iterator it(pending_requests_.find(handle));
+ if (it == pending_requests_.end())
+ return NULL;
+
+ GetLoginsRequest* request = it->second;
+ pending_requests_.erase(it);
+ return request;
}
PasswordForm* PasswordStoreWin::GetIE7Result(const WDTypedResult *result,
const PasswordForm& form) {
const WDResult<IE7PasswordInfo>* r =
- static_cast<const WDResult<IE7PasswordInfo>*>(result);
+ static_cast<const WDResult<IE7PasswordInfo>*>(result);
IE7PasswordInfo info = r->GetValue();
if (!info.encrypted_data.empty()) {
diff --git a/chrome/browser/password_manager/password_store_win.h b/chrome/browser/password_manager/password_store_win.h
index 924fc07..6eea056 100644
--- a/chrome/browser/password_manager/password_store_win.h
+++ b/chrome/browser/password_manager/password_store_win.h
@@ -20,27 +20,33 @@
class PasswordStoreWin : public PasswordStoreDefault {
public:
// FilePath specifies path to WebDatabase.
- explicit PasswordStoreWin(WebDataService* web_data_service);
+ PasswordStoreWin(LoginDatabase* login_database,
+ Profile* profile,
+ WebDataService* web_data_service);
// Overridden so that we can save the form for later use.
virtual int GetLogins(const webkit_glue::PasswordForm& form,
PasswordStoreConsumer* consumer);
- virtual void CancelLoginsQuery(int handle);
private:
- virtual ~PasswordStoreWin() {}
+ virtual ~PasswordStoreWin();
// See PasswordStoreDefault.
void OnWebDataServiceRequestDone(WebDataService::Handle h,
const WDTypedResult* result);
- // Removes the form for |handle| from pending_request_forms_ (if any).
- void DeleteFormForRequest(int handle);
+ virtual void NotifyConsumer(
+ GetLoginsRequest* request,
+ const std::vector<webkit_glue::PasswordForm*> forms);
- // Cleans up internal state related to |request|, and sends its results to
- // the request's consumer.
- void CompleteRequest(GetLoginsRequest* request,
- const std::vector<webkit_glue::PasswordForm*>& forms);
+ // Takes ownership of |request| and tracks it under |handle|.
+ void TrackRequest(WebDataService::Handle handle, GetLoginsRequest* request);
+
+ // Finds the GetLoginsRequest associated with the in-flight WebDataService
+ // request identified by |handle|, removes it from the tracking list, and
+ // returns it. Ownership of the GetLoginsRequest passes to the caller.
+ // Returns NULL if the request has been cancelled.
+ GetLoginsRequest* TakeRequestWithHandle(WebDataService::Handle handle);
// Gets logins from IE7 if no others are found. Also copies them into
// Chrome's WebDatabase so we don't need to look next time.
@@ -48,6 +54,10 @@ class PasswordStoreWin : public PasswordStoreDefault {
const WDTypedResult* result,
const webkit_glue::PasswordForm& form);
+ // Holds requests associated with in-flight GetLogin queries.
+ typedef std::map<int, GetLoginsRequest*> PendingRequestMap;
+ PendingRequestMap pending_requests_;
+
// Holds forms associated with in-flight GetLogin queries.
typedef std::map<int, webkit_glue::PasswordForm> PendingRequestFormMap;
PendingRequestFormMap pending_request_forms_;
diff --git a/chrome/browser/password_manager/password_store_win_unittest.cc b/chrome/browser/password_manager/password_store_win_unittest.cc
new file mode 100644
index 0000000..ed78289
--- /dev/null
+++ b/chrome/browser/password_manager/password_store_win_unittest.cc
@@ -0,0 +1,327 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <windows.h>
+#include <wincrypt.h>
+#include <string>
+#include <vector>
+
+#include "base/message_loop.h"
+#include "base/scoped_ptr.h"
+#include "base/scoped_temp_dir.h"
+#include "base/time.h"
+#include "base/waitable_event.h"
+#include "chrome/browser/chrome_thread.h"
+#include "chrome/browser/password_manager/password_form_data.h"
+#include "chrome/browser/password_manager/password_store_win.h"
+#include "chrome/browser/password_manager/ie7_password.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/test/testing_profile.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::WaitableEvent;
+using testing::_;
+using webkit_glue::PasswordForm;
+
+namespace {
+
+class MockPasswordStoreConsumer : public PasswordStoreConsumer {
+ public:
+ MOCK_METHOD2(OnPasswordStoreRequestDone,
+ void(int, const std::vector<webkit_glue::PasswordForm*>&));
+};
+
+class MockWebDataServiceConsumer : public WebDataServiceConsumer {
+public:
+ MOCK_METHOD2(OnWebDataServiceRequestDone,
+ void(WebDataService::Handle, const WDTypedResult*));
+};
+
+class SignalingTask : public Task {
+ public:
+ explicit SignalingTask(WaitableEvent* event) : event_(event) {
+ }
+ virtual void Run() {
+ event_->Signal();
+ }
+ private:
+ WaitableEvent* event_;
+};
+
+} // anonymous namespace
+
+class PasswordStoreWinTest : public testing::Test {
+ protected:
+ PasswordStoreWinTest()
+ : ui_thread_(ChromeThread::UI, &message_loop_),
+ db_thread_(ChromeThread::DB) {
+ }
+
+ bool CreateIE7PasswordInfo(const std::wstring& url, const base::Time& created,
+ IE7PasswordInfo* info) {
+ // Copied from chrome/browser/importer/importer_unittest.cc
+ // The username is "abcdefgh" and the password "abcdefghijkl".
+ unsigned char data[] = "\x0c\x00\x00\x00\x38\x00\x00\x00\x2c\x00\x00\x00"
+ "\x57\x49\x43\x4b\x18\x00\x00\x00\x02\x00\x00\x00"
+ "\x67\x00\x72\x00\x01\x00\x00\x00\x00\x00\x00\x00"
+ "\x00\x00\x00\x00\x4e\xfa\x67\x76\x22\x94\xc8\x01"
+ "\x08\x00\x00\x00\x12\x00\x00\x00\x4e\xfa\x67\x76"
+ "\x22\x94\xc8\x01\x0c\x00\x00\x00\x61\x00\x62\x00"
+ "\x63\x00\x64\x00\x65\x00\x66\x00\x67\x00\x68\x00"
+ "\x00\x00\x61\x00\x62\x00\x63\x00\x64\x00\x65\x00"
+ "\x66\x00\x67\x00\x68\x00\x69\x00\x6a\x00\x6b\x00"
+ "\x6c\x00\x00\x00";
+ DATA_BLOB input = {0};
+ DATA_BLOB url_key = {0};
+ DATA_BLOB output = {0};
+
+ input.pbData = data;
+ input.cbData = sizeof(data);
+
+ url_key.pbData = reinterpret_cast<unsigned char*>(
+ const_cast<wchar_t*>(url.data()));
+ url_key.cbData = static_cast<DWORD>((url.size() + 1) *
+ sizeof(std::wstring::value_type));
+
+ if (!CryptProtectData(&input, NULL, &url_key, NULL, NULL,
+ CRYPTPROTECT_UI_FORBIDDEN, &output))
+ return false;
+
+ std::vector<unsigned char> encrypted_data;
+ encrypted_data.resize(output.cbData);
+ memcpy(&encrypted_data.front(), output.pbData, output.cbData);
+
+ LocalFree(output.pbData);
+
+ info->url_hash = ie7_password::GetUrlHash(url);
+ info->encrypted_data = encrypted_data;
+ info->date_created = created;
+
+ return true;
+ }
+
+ virtual void SetUp() {
+ ASSERT_TRUE(db_thread_.Start());
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+
+ profile_.reset(new TestingProfile());
+
+ login_db_.reset(new LoginDatabase());
+ ASSERT_TRUE(login_db_->Init(temp_dir_.path().Append(
+ FILE_PATH_LITERAL("login_test"))));
+
+ wds_ = new WebDataService();
+ ASSERT_TRUE(wds_->Init(temp_dir_.path()));
+ }
+
+ virtual void TearDown() {
+ if (wds_.get())
+ wds_->Shutdown();
+ MessageLoop::current()->PostTask(FROM_HERE, new MessageLoop::QuitTask);
+ MessageLoop::current()->Run();
+ db_thread_.Stop();
+ }
+
+ MessageLoopForUI message_loop_;
+ ChromeThread ui_thread_;
+ ChromeThread db_thread_; // PasswordStore, WDS schedule work on this thread.
+
+ scoped_ptr<LoginDatabase> login_db_;
+ scoped_ptr<TestingProfile> profile_;
+ scoped_refptr<WebDataService> wds_;
+ ScopedTempDir temp_dir_;
+};
+
+ACTION(QuitUIMessageLoop) {
+ DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
+ MessageLoop::current()->Quit();
+}
+
+TEST_F(PasswordStoreWinTest, ConvertIE7Login) {
+ IE7PasswordInfo password_info;
+ ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
+ base::Time::FromDoubleT(1),
+ &password_info));
+
+ // This IE7 password will be retrieved by the GetLogins call.
+ wds_->AddIE7Login(password_info);
+
+ // The WDS schedules tasks to run on the DB thread so we schedule yet another
+ // task to notify us that it's safe to carry on with the test.
+ WaitableEvent done(false, false);
+ ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done));
+ done.Wait();
+
+ // Prentend that the migration has already taken place.
+ profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated,
+ true);
+
+ // Initializing the PasswordStore shouldn't trigger a migration.
+ scoped_refptr<PasswordStoreWin> store(
+ new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get()));
+ EXPECT_TRUE(store->Init());
+
+ MockPasswordStoreConsumer consumer;
+
+ // Make sure we quit the MessageLoop even if the test fails.
+ ON_CALL(consumer, OnPasswordStoreRequestDone(_, _))
+ .WillByDefault(QuitUIMessageLoop());
+
+ PasswordFormData form_data = {
+ PasswordForm::SCHEME_HTML,
+ "http://example.com/",
+ "http://example.com/origin",
+ "http://example.com/action",
+ L"submit_element",
+ L"username_element",
+ L"password_element",
+ L"",
+ L"",
+ true, false, 1,
+ };
+ scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
+
+ PasswordFormData expected_form_data = {
+ PasswordForm::SCHEME_HTML,
+ "http://example.com/",
+ "http://example.com/origin",
+ "http://example.com/action",
+ L"submit_element",
+ L"username_element",
+ L"password_element",
+ L"abcdefgh",
+ L"abcdefghijkl",
+ true, false, 1,
+ };
+ std::vector<PasswordForm*> forms;
+ forms.push_back(CreatePasswordFormFromData(expected_form_data));
+
+ // The IE7 password should be returned.
+ EXPECT_CALL(consumer,
+ OnPasswordStoreRequestDone(_,
+ ContainsAllPasswordForms(forms)))
+ .WillOnce(QuitUIMessageLoop());
+
+ store->GetLogins(*form, &consumer);
+ MessageLoop::current()->Run();
+
+ STLDeleteElements(&forms);
+}
+
+TEST_F(PasswordStoreWinTest, OutstandingWDSQueries) {
+ // Prentend that the migration has already taken place.
+ profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated,
+ true);
+
+ // Initializing the PasswordStore shouldn't trigger a migration.
+ scoped_refptr<PasswordStoreWin> store(
+ new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get()));
+ EXPECT_TRUE(store->Init());
+
+ PasswordFormData form_data = {
+ PasswordForm::SCHEME_HTML,
+ "http://example.com/",
+ "http://example.com/origin",
+ "http://example.com/action",
+ L"submit_element",
+ L"username_element",
+ L"password_element",
+ L"",
+ L"",
+ true, false, 1,
+ };
+ scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
+
+ MockPasswordStoreConsumer consumer;
+ store->GetLogins(*form, &consumer);
+
+ // Release the PSW and the WDS before the query can return.
+ store = NULL;
+ wds_->Shutdown();
+ wds_ = NULL;
+
+ MessageLoop::current()->RunAllPending();
+}
+
+TEST_F(PasswordStoreWinTest, MultipleWDSQueriesOnDifferentThreads) {
+ IE7PasswordInfo password_info;
+ ASSERT_TRUE(CreateIE7PasswordInfo(L"http://example.com/origin",
+ base::Time::FromDoubleT(1),
+ &password_info));
+ wds_->AddIE7Login(password_info);
+
+ // The WDS schedules tasks to run on the DB thread so we schedule yet another
+ // task to notify us that it's safe to carry on with the test.
+ WaitableEvent done(false, false);
+ ChromeThread::PostTask(ChromeThread::DB, FROM_HERE, new SignalingTask(&done));
+ done.Wait();
+
+ // Prentend that the migration has already taken place.
+ profile_->GetPrefs()->RegisterBooleanPref(prefs::kLoginDatabaseMigrated,
+ true);
+
+ // Initializing the PasswordStore shouldn't trigger a migration.
+ scoped_refptr<PasswordStoreWin> store(
+ new PasswordStoreWin(login_db_.release(), profile_.get(), wds_.get()));
+ EXPECT_TRUE(store->Init());
+
+ MockPasswordStoreConsumer password_consumer;
+ // Make sure we quit the MessageLoop even if the test fails.
+ ON_CALL(password_consumer, OnPasswordStoreRequestDone(_, _))
+ .WillByDefault(QuitUIMessageLoop());
+
+ PasswordFormData form_data = {
+ PasswordForm::SCHEME_HTML,
+ "http://example.com/",
+ "http://example.com/origin",
+ "http://example.com/action",
+ L"submit_element",
+ L"username_element",
+ L"password_element",
+ L"",
+ L"",
+ true, false, 1,
+ };
+ scoped_ptr<PasswordForm> form(CreatePasswordFormFromData(form_data));
+
+ PasswordFormData expected_form_data = {
+ PasswordForm::SCHEME_HTML,
+ "http://example.com/",
+ "http://example.com/origin",
+ "http://example.com/action",
+ L"submit_element",
+ L"username_element",
+ L"password_element",
+ L"abcdefgh",
+ L"abcdefghijkl",
+ true, false, 1,
+ };
+ std::vector<PasswordForm*> forms;
+ forms.push_back(CreatePasswordFormFromData(expected_form_data));
+
+ // The IE7 password should be returned.
+ EXPECT_CALL(password_consumer,
+ OnPasswordStoreRequestDone(_,
+ ContainsAllPasswordForms(forms)))
+ .WillOnce(QuitUIMessageLoop());
+
+ store->GetLogins(*form, &password_consumer);
+
+ MockWebDataServiceConsumer wds_consumer;
+
+ EXPECT_CALL(wds_consumer,
+ OnWebDataServiceRequestDone(_, _))
+ .WillOnce(QuitUIMessageLoop());
+
+ wds_->GetIE7Login(password_info, &wds_consumer);
+
+ // Run the MessageLoop twice: once for the GetIE7Login that PasswordStoreWin
+ // schedules on the DB thread and once for the one we just scheduled on the UI
+ // thread.
+ MessageLoop::current()->Run();
+ MessageLoop::current()->Run();
+
+ STLDeleteElements(&forms);
+} \ No newline at end of file
diff --git a/chrome/browser/profile.cc b/chrome/browser/profile.cc
index 4332a35..98bae1d 100644
--- a/chrome/browser/profile.cc
+++ b/chrome/browser/profile.cc
@@ -44,7 +44,6 @@
#include "chrome/browser/net/ssl_config_service_manager.h"
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/password_manager/password_store_default.h"
-#include "chrome/browser/password_manager/password_store_linux.h"
#include "chrome/browser/privacy_blacklist/blacklist.h"
#include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
#include "chrome/browser/profile_manager.h"
@@ -1196,9 +1195,6 @@ void ProfileImpl::CreatePasswordStore() {
DCHECK(!created_password_store_ && password_store_.get() == NULL);
created_password_store_ = true;
scoped_refptr<PasswordStore> ps;
-#if defined(OS_WIN)
- ps = new PasswordStoreWin(GetWebDataService(Profile::IMPLICIT_ACCESS));
-#elif defined(OS_MACOSX)
FilePath login_db_file_path = GetPath();
login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName);
LoginDatabase* login_db = new LoginDatabase();
@@ -1207,31 +1203,26 @@ void ProfileImpl::CreatePasswordStore() {
delete login_db;
return;
}
+#if defined(OS_WIN)
+ ps = new PasswordStoreWin(login_db, this,
+ GetWebDataService(Profile::IMPLICIT_ACCESS));
+#elif defined(OS_MACOSX)
ps = new PasswordStoreMac(new MacKeychain(), login_db);
#elif defined(OS_POSIX)
// TODO(evanm): implement "native" password management.
// This bug describes the issues.
// http://code.google.com/p/chromium/issues/detail?id=12351
- FilePath login_db_file_path = GetPath();
- login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName);
- LoginDatabase* login_db = new LoginDatabase();
- if (!login_db->Init(login_db_file_path)) {
- LOG(ERROR) << "Could not initialize login database.";
- delete login_db;
- return;
- }
- ps = new PasswordStoreLinux(login_db, this,
- GetWebDataService(Profile::IMPLICIT_ACCESS));
+ ps = new PasswordStoreDefault(login_db, this,
+ GetWebDataService(Profile::IMPLICIT_ACCESS));
#else
NOTIMPLEMENTED();
#endif
+ if (!ps)
+ delete login_db;
+
if (!ps || !ps->Init()) {
- // Try falling back to the default password manager
- NOTREACHED() << "Could not initialise native password manager - "
- "falling back to default";
- ps = new PasswordStoreDefault(GetWebDataService(Profile::IMPLICIT_ACCESS));
- if (!ps->Init())
- return;
+ NOTREACHED() << "Could not initialise password manager";
+ return;
}
password_store_.swap(ps);
}
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index dc046fe..900725d 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1701,8 +1701,6 @@
'browser/password_manager/password_store.h',
'browser/password_manager/password_store_default.cc',
'browser/password_manager/password_store_default.h',
- 'browser/password_manager/password_store_linux.cc',
- 'browser/password_manager/password_store_linux.h',
# Temporarily disabled while we figure some stuff out.
# http://code.google.com/p/chromium/issues/detail?id=12351
# 'browser/password_manager/password_store_gnome.h',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 68bbca1..85497a3 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -859,8 +859,9 @@
'browser/password_manager/password_form_manager_unittest.cc',
'browser/password_manager/password_manager_unittest.cc',
'browser/password_manager/password_form_data.cc',
- 'browser/password_manager/password_store_linux_unittest.cc',
+ 'browser/password_manager/password_store_default_unittest.cc',
'browser/password_manager/password_store_mac_unittest.cc',
+ 'browser/password_manager/password_store_win_unittest.cc',
'browser/pref_member_unittest.cc',
'browser/pref_service_unittest.cc',
'browser/printing/print_job_unittest.cc',
@@ -1101,6 +1102,7 @@
# Blocked on bookmark manager.
'browser/bookmarks/bookmark_context_menu_controller_unittest.cc',
'browser/views/accessibility_event_router_views_unittest.cc',
+ 'browser/password_manager/password_store_default_unittest.cc',
'browser/views/bookmark_context_menu_test.cc',
'browser/gtk/go_button_gtk_unittest.cc',
'browser/gtk/tabs/tab_renderer_gtk_unittest.cc',