Commit a6bf1b23 authored by engedy's avatar engedy Committed by Commit bot

Integrate serving affiliation-based matches into the PasswordStore.

BUG=437865

Review URL: https://codereview.chromium.org/999073002

Cr-Commit-Position: refs/heads/master@{#320959}
parent 4d83add3
......@@ -18,6 +18,9 @@
#include "chrome/common/chrome_switches.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/os_crypt/os_crypt_switches.h"
#include "components/password_manager/core/browser/affiliated_match_helper.h"
#include "components/password_manager/core/browser/affiliation_service.h"
#include "components/password_manager/core/browser/affiliation_utils.h"
#include "components/password_manager/core/browser/login_database.h"
#include "components/password_manager/core/browser/password_store.h"
#include "components/password_manager/core/browser/password_store_default.h"
......@@ -274,6 +277,24 @@ KeyedService* PasswordStoreFactory::BuildServiceInstanceFor(
return nullptr;
}
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (password_manager::IsAffiliationBasedMatchingEnabled(*command_line)) {
// The PasswordStore is so far the only consumer of the AffiliationService,
// therefore the service is owned by the AffiliatedMatchHelper, which in
// turn is owned by the PasswordStore.
// TODO(engedy): Double-check which request context we want.
scoped_ptr<password_manager::AffiliationService> affiliation_service(
new password_manager::AffiliationService(db_thread_runner));
affiliation_service->Initialize(
profile->GetRequestContext(),
profile->GetPath().Append(chrome::kAffiliationDatabaseFileName));
scoped_ptr<password_manager::AffiliatedMatchHelper> affiliated_match_helper(
new password_manager::AffiliatedMatchHelper(
ps.get(), affiliation_service.Pass()));
affiliated_match_helper->Initialize();
ps->SetAffiliatedMatchHelper(affiliated_match_helper.Pass());
}
return new PasswordStoreService(ps);
}
......
......@@ -137,6 +137,8 @@ const base::FilePath::CharType kSystemProfileDir[] = FPL("System Profile");
const wchar_t kBrowserResourcesDll[] = L"chrome.dll";
// filenames
const base::FilePath::CharType kAffiliationDatabaseFileName[] =
FPL("Affiliation Database");
const base::FilePath::CharType kCacheDirname[] = FPL("Cache");
const base::FilePath::CharType kChannelIDFilename[] = FPL("Origin Bound Certs");
const base::FilePath::CharType kCookieFilename[] = FPL("Cookies");
......
......@@ -63,6 +63,7 @@ extern const base::FilePath::CharType kSystemProfileDir[];
extern const wchar_t kBrowserResourcesDll[];
// filenames
extern const base::FilePath::CharType kAffiliationDatabaseFileName[];
extern const base::FilePath::CharType kCacheDirname[];
extern const base::FilePath::CharType kChannelIDFilename[];
extern const base::FilePath::CharType kCookieFilename[];
......
......@@ -39,15 +39,16 @@ AffiliatedMatchHelper::AffiliatedMatchHelper(
task_runner_for_waiting_(base::ThreadTaskRunnerHandle::Get()),
affiliation_service_(affiliation_service.Pass()),
weak_ptr_factory_(this) {
DCHECK(affiliation_service_);
DCHECK(password_store_);
}
AffiliatedMatchHelper::~AffiliatedMatchHelper() {
password_store_->RemoveObserver(this);
if (password_store_)
password_store_->RemoveObserver(this);
}
void AffiliatedMatchHelper::Initialize() {
DCHECK(password_store_);
DCHECK(affiliation_service_);
task_runner_for_waiting_->PostDelayedTask(
FROM_HERE, base::Bind(&AffiliatedMatchHelper::DoDeferredInitialization,
weak_ptr_factory_.GetWeakPtr()),
......
......@@ -52,7 +52,8 @@ class AffiliatedMatchHelper : public PasswordStore::Observer,
typedef base::Callback<void(const std::vector<std::string>&)>
AffiliatedRealmsCallback;
// The |password_store| must outlive |this|.
// The |password_store| must outlive |this|. Both arguments must be non-NULL,
// except in tests which do not Initialize() the object.
AffiliatedMatchHelper(PasswordStore* password_store,
scoped_ptr<AffiliationService> affiliation_service);
~AffiliatedMatchHelper() override;
......@@ -63,7 +64,7 @@ class AffiliatedMatchHelper : public PasswordStore::Observer,
// Retrieves realms of Android applications affiliated with the realm of the
// |observed_form| if it is web-based. Otherwise, yields the empty list. The
// |result_callback| will be invoked in both cases, on the same thread.
void GetAffiliatedAndroidRealms(
virtual void GetAffiliatedAndroidRealms(
const autofill::PasswordForm& observed_form,
const AffiliatedRealmsCallback& result_callback);
......@@ -106,7 +107,7 @@ class AffiliatedMatchHelper : public PasswordStore::Observer,
void OnGetPasswordStoreResults(
ScopedVector<autofill::PasswordForm> results) override;
PasswordStore* password_store_;
PasswordStore* const password_store_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_for_waiting_;
// Being the sole consumer of AffiliationService, |this| owns the service.
......
......@@ -11,6 +11,7 @@
#include "base/metrics/histogram.h"
#include "base/stl_util.h"
#include "components/autofill/core/common/password_form.h"
#include "components/password_manager/core/browser/affiliated_match_helper.h"
#include "components/password_manager/core/browser/password_store_consumer.h"
#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
......@@ -77,6 +78,13 @@ bool PasswordStore::Init(const syncer::SyncableService::StartSyncFlare& flare) {
return true;
}
void PasswordStore::SetAffiliatedMatchHelper(
scoped_ptr<AffiliatedMatchHelper> helper) {
DCHECK(helper);
DCHECK(!affiliated_match_helper_);
affiliated_match_helper_ = helper.Pass();
}
void PasswordStore::AddLogin(const PasswordForm& form) {
CheckForEmptyUsernameAndPassword(form);
ScheduleTask(base::Bind(&PasswordStore::AddLoginInternal, this, form));
......@@ -125,8 +133,15 @@ void PasswordStore::GetLogins(const PasswordForm& form,
}
scoped_ptr<GetLoginsRequest> request(new GetLoginsRequest(consumer));
request->set_ignore_logins_cutoff(ignore_logins_cutoff);
ScheduleTask(base::Bind(&PasswordStore::GetLoginsImpl, this, form,
prompt_policy, base::Passed(&request)));
if (affiliated_match_helper_) {
affiliated_match_helper_->GetAffiliatedAndroidRealms(
form, base::Bind(&PasswordStore::ScheduleGetLoginsWithAffiliations,
this, form, prompt_policy, base::Passed(&request)));
} else {
ScheduleTask(base::Bind(&PasswordStore::GetLoginsImpl, this, form,
prompt_policy, base::Passed(&request)));
}
}
void PasswordStore::GetAutofillableLogins(PasswordStoreConsumer* consumer) {
......@@ -170,6 +185,8 @@ void PasswordStore::Shutdown() {
#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
ScheduleTask(base::Bind(&PasswordStore::DestroySyncableService, this));
#endif
// The AffiliationService must be destroyed from the main thread.
affiliated_match_helper_.reset();
shutdown_called_ = true;
}
......@@ -263,6 +280,36 @@ void PasswordStore::RemoveLoginsSyncedBetweenInternal(base::Time delete_begin,
NotifyLoginsChanged(changes);
}
void PasswordStore::GetLoginsWithAffiliationsImpl(
const PasswordForm& form,
AuthorizationPromptPolicy prompt_policy,
scoped_ptr<GetLoginsRequest> request,
const std::vector<std::string>& additional_android_realms) {
DCHECK(GetBackgroundTaskRunner()->BelongsToCurrentThread());
ScopedVector<PasswordForm> results(FillMatchingLogins(form, prompt_policy));
for (const std::string& realm : additional_android_realms) {
PasswordForm android_form;
android_form.scheme = PasswordForm::SCHEME_HTML;
android_form.signon_realm = realm;
ScopedVector<PasswordForm> more_results(
AffiliatedMatchHelper::TransformAffiliatedAndroidCredentials(
form, FillMatchingLogins(android_form, DISALLOW_PROMPT)));
results.insert(results.end(), more_results.begin(), more_results.end());
more_results.weak_clear();
}
request->NotifyConsumerWithResults(results.Pass());
}
void PasswordStore::ScheduleGetLoginsWithAffiliations(
const PasswordForm& form,
AuthorizationPromptPolicy prompt_policy,
scoped_ptr<GetLoginsRequest> request,
const std::vector<std::string>& additional_android_realms) {
ScheduleTask(base::Bind(&PasswordStore::GetLoginsWithAffiliationsImpl, this,
form, prompt_policy, base::Passed(&request),
additional_android_realms));
}
#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
void PasswordStore::InitSyncableService(
const syncer::SyncableService::StartSyncFlare& flare) {
......
......@@ -26,6 +26,7 @@ class SyncableService;
namespace password_manager {
class AffiliatedMatchHelper;
class PasswordStoreConsumer;
class PasswordSyncableService;
......@@ -65,6 +66,13 @@ class PasswordStore : protected PasswordStoreSync,
// Reimplement this to add custom initialization. Always call this too.
virtual bool Init(const syncer::SyncableService::StartSyncFlare& flare);
// Sets the affiliation-based match |helper| that will be used by subsequent
// GetLogins() calls to return credentials stored not only for the requested
// sign-on realm, but also for affiliated Android applications. The helper
// must already be initialized. Unless a |helper| is set, affiliation-based
// matching is disabled.
void SetAffiliatedMatchHelper(scoped_ptr<AffiliatedMatchHelper> helper);
// Adds the given PasswordForm to the secure password store asynchronously.
virtual void AddLogin(const autofill::PasswordForm& form);
......@@ -194,8 +202,9 @@ class PasswordStore : protected PasswordStoreSync,
// Finds all PasswordForms with a signon_realm that is equal to, or is a
// PSL-match to that of |form|, and takes care of notifying the consumer with
// the results when done.
// Note: subclasses should implement FillMatchingLogins() instead, which will
// later be used by additional flavors of this method.
// Note: subclasses should implement FillMatchingLogins() instead. This needs
// to be virtual only because asynchronous behavior in PasswordStoreWin.
// TODO(engedy): Make this non-virtual once https://crbug.com/78830 is fixed.
virtual void GetLoginsImpl(const autofill::PasswordForm& form,
AuthorizationPromptPolicy prompt_policy,
scoped_ptr<GetLoginsRequest> request);
......@@ -255,6 +264,26 @@ class PasswordStore : protected PasswordStoreSync,
void RemoveLoginsSyncedBetweenInternal(base::Time delete_begin,
base::Time delete_end);
// Extended version of GetLoginsImpl that also returns credentials stored for
// the specified affiliated Android applications. That is, it finds all
// PasswordForms with a signon_realm that is either:
// * equal to that of |form|,
// * is a PSL-match to the realm of |form|,
// * is one of those in |additional_android_realms|,
// and takes care of notifying the consumer with the results when done.
void GetLoginsWithAffiliationsImpl(
const autofill::PasswordForm& form,
AuthorizationPromptPolicy prompt_policy,
scoped_ptr<GetLoginsRequest> request,
const std::vector<std::string>& additional_android_realms);
// Schedules GetLoginsWithAffiliationsImpl() to be run on the DB thread.
void ScheduleGetLoginsWithAffiliations(
const autofill::PasswordForm& form,
AuthorizationPromptPolicy prompt_policy,
scoped_ptr<GetLoginsRequest> request,
const std::vector<std::string>& additional_android_realms);
#if defined(PASSWORD_MANAGER_ENABLE_SYNC)
// Creates PasswordSyncableService instance on the background thread.
void InitSyncableService(
......@@ -268,6 +297,7 @@ class PasswordStore : protected PasswordStoreSync,
scoped_refptr<ObserverListThreadSafe<Observer>> observers_;
scoped_ptr<PasswordSyncableService> syncable_service_;
scoped_ptr<AffiliatedMatchHelper> affiliated_match_helper_;
bool shutdown_called_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment