1 // Copyright 2019 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.
4
5 #include "chrome/browser/password_manager/account_password_store_factory.h"
6
7 #include <memory>
8 #include <utility>
9 #include <vector>
10
11 #include "base/bind.h"
12 #include "base/callback_helpers.h"
13 #include "base/memory/weak_ptr.h"
14 #include "build/build_config.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/password_manager/credentials_cleaner_runner_factory.h"
17 #include "chrome/browser/password_manager/password_store_utils.h"
18 #include "chrome/browser/profiles/incognito_helpers.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/web_data_service_factory.h"
22 #include "components/keyed_service/content/browser_context_dependency_manager.h"
23 #include "components/password_manager/core/browser/login_database.h"
24 #include "components/password_manager/core/browser/password_manager_constants.h"
25 #include "components/password_manager/core/browser/password_manager_util.h"
26 #include "components/password_manager/core/browser/password_store.h"
27 #include "components/password_manager/core/browser/password_store_default.h"
28 #include "components/password_manager/core/browser/password_store_factory_util.h"
29 #include "components/password_manager/core/common/password_manager_features.h"
30 #include "components/password_manager/core/common/password_manager_pref_names.h"
31 #include "components/pref_registry/pref_registry_syncable.h"
32 #include "components/prefs/pref_service.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/browser/network_service_instance.h"
36 #include "content/public/browser/storage_partition.h"
37 #include "content/public/browser/web_contents.h"
38
39 #if !defined(OS_ANDROID)
40 #include "base/task/task_traits.h"
41 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
42 #include "chrome/browser/ui/browser.h"
43 #include "chrome/browser/ui/browser_finder.h"
44 #include "chrome/browser/ui/browser_list.h"
45 #include "chrome/browser/ui/passwords/manage_passwords_ui_controller.h"
46 #include "chrome/browser/ui/tabs/tab_strip_model.h"
47 #include "content/public/browser/browser_task_traits.h"
48 #endif // !defined(OS_ANDROID)
49
50 using password_manager::PasswordStore;
51
52 #if !defined(OS_ANDROID)
53
54 namespace {
55
UpdateAllFormManagers(Profile * profile)56 void UpdateAllFormManagers(Profile* profile) {
57 for (Browser* browser : *BrowserList::GetInstance()) {
58 if (browser->profile() != profile)
59 continue;
60 TabStripModel* tabs = browser->tab_strip_model();
61 for (int index = 0; index < tabs->count(); index++) {
62 content::WebContents* web_contents = tabs->GetWebContentsAt(index);
63 ChromePasswordManagerClient::FromWebContents(web_contents)
64 ->UpdateFormManagers();
65 }
66 }
67 }
68
69 class UnsyncedCredentialsDeletionNotifierImpl
70 : public PasswordStore::UnsyncedCredentialsDeletionNotifier {
71 public:
72 explicit UnsyncedCredentialsDeletionNotifierImpl(Profile* profile);
73 ~UnsyncedCredentialsDeletionNotifierImpl() override = default;
74
75 // Finds the last active tab and notifies their ManagePasswordsUIController.
76 void Notify(std::vector<password_manager::PasswordForm> credentials) override;
77 base::WeakPtr<UnsyncedCredentialsDeletionNotifier> GetWeakPtr() override;
78
79 private:
80 Profile* const profile_;
81 base::WeakPtrFactory<UnsyncedCredentialsDeletionNotifier> weak_ptr_factory_{
82 this};
83 };
84
85 UnsyncedCredentialsDeletionNotifierImpl::
UnsyncedCredentialsDeletionNotifierImpl(Profile * profile)86 UnsyncedCredentialsDeletionNotifierImpl(Profile* profile)
87 : profile_(profile) {}
88
Notify(std::vector<password_manager::PasswordForm> credentials)89 void UnsyncedCredentialsDeletionNotifierImpl::Notify(
90 std::vector<password_manager::PasswordForm> credentials) {
91 Browser* browser = chrome::FindBrowserWithProfile(profile_);
92 if (!browser)
93 return;
94 content::WebContents* web_contents =
95 browser->tab_strip_model()->GetActiveWebContents();
96 if (!web_contents)
97 return;
98 auto* ui_controller =
99 ManagePasswordsUIController::FromWebContents(web_contents);
100 if (!ui_controller)
101 return;
102 ui_controller->NotifyUnsyncedCredentialsWillBeDeleted(std::move(credentials));
103 }
104
105 base::WeakPtr<PasswordStore::UnsyncedCredentialsDeletionNotifier>
GetWeakPtr()106 UnsyncedCredentialsDeletionNotifierImpl::GetWeakPtr() {
107 return weak_ptr_factory_.GetWeakPtr();
108 }
109
110 } // namespace
111
112 #endif // !defined(OS_ANDROID)
113
SyncEnabledOrDisabled(Profile * profile)114 void SyncEnabledOrDisabled(Profile* profile) {
115 #if defined(OS_ANDROID)
116 NOTREACHED();
117 #else
118 content::GetUIThreadTaskRunner({})->PostTask(
119 FROM_HERE, base::BindOnce(&UpdateAllFormManagers, profile));
120 #endif // defined(OS_ANDROID)
121 }
122
123 // static
GetForProfile(Profile * profile,ServiceAccessType access_type)124 scoped_refptr<PasswordStore> AccountPasswordStoreFactory::GetForProfile(
125 Profile* profile,
126 ServiceAccessType access_type) {
127 if (!base::FeatureList::IsEnabled(
128 password_manager::features::kEnablePasswordsAccountStorage)) {
129 if (profile->GetPrefs()->GetBoolean(
130 password_manager::prefs::kAccountStorageExists)) {
131 // TODO(crbug.com/1108738): Remove this logic once
132 // kEnablePasswordsAccountStorage is launched.
133 profile->GetPrefs()->ClearPref(
134 password_manager::prefs::kAccountStorageExists);
135 password_manager::DeleteLoginDatabaseForAccountStorageFiles(
136 profile->GetPath());
137 }
138 return nullptr;
139 }
140
141 // |profile| gets always redirected to a non-Incognito profile below, so
142 // Incognito & IMPLICIT_ACCESS means that incognito browsing session would
143 // result in traces in the normal profile without the user knowing it.
144 if (access_type == ServiceAccessType::IMPLICIT_ACCESS &&
145 profile->IsOffTheRecord()) {
146 return nullptr;
147 }
148
149 // Either the store exists already, or it'll be created now.
150 profile->GetPrefs()->SetBoolean(
151 password_manager::prefs::kAccountStorageExists, true);
152
153 return base::WrapRefCounted(static_cast<password_manager::PasswordStore*>(
154 GetInstance()->GetServiceForBrowserContext(profile, true).get()));
155 }
156
157 // static
GetInstance()158 AccountPasswordStoreFactory* AccountPasswordStoreFactory::GetInstance() {
159 return base::Singleton<AccountPasswordStoreFactory>::get();
160 }
161
AccountPasswordStoreFactory()162 AccountPasswordStoreFactory::AccountPasswordStoreFactory()
163 : RefcountedBrowserContextKeyedServiceFactory(
164 "AccountPasswordStore",
165 BrowserContextDependencyManager::GetInstance()) {
166 DependsOn(WebDataServiceFactory::GetInstance());
167 }
168
169 AccountPasswordStoreFactory::~AccountPasswordStoreFactory() = default;
170
RegisterProfilePrefs(user_prefs::PrefRegistrySyncable * registry)171 void AccountPasswordStoreFactory::RegisterProfilePrefs(
172 user_prefs::PrefRegistrySyncable* registry) {
173 registry->RegisterBooleanPref(password_manager::prefs::kAccountStorageExists,
174 false);
175 }
176
177 scoped_refptr<RefcountedKeyedService>
BuildServiceInstanceFor(content::BrowserContext * context) const178 AccountPasswordStoreFactory::BuildServiceInstanceFor(
179 content::BrowserContext* context) const {
180 DCHECK(base::FeatureList::IsEnabled(
181 password_manager::features::kEnablePasswordsAccountStorage));
182
183 Profile* profile = Profile::FromBrowserContext(context);
184
185 std::unique_ptr<password_manager::LoginDatabase> login_db(
186 password_manager::CreateLoginDatabaseForAccountStorage(
187 profile->GetPath()));
188
189 scoped_refptr<PasswordStore> ps =
190 new password_manager::PasswordStoreDefault(std::move(login_db));
191 if (!ps->Init(profile->GetPrefs(),
192 base::BindRepeating(&SyncEnabledOrDisabled, profile))) {
193 // TODO(crbug.com/479725): Remove the LOG once this error is visible in the
194 // UI.
195 LOG(WARNING) << "Could not initialize password store.";
196 return nullptr;
197 }
198
199 auto network_context_getter = base::BindRepeating(
200 [](Profile* profile) -> network::mojom::NetworkContext* {
201 if (!g_browser_process->profile_manager()->IsValidProfile(profile))
202 return nullptr;
203 return content::BrowserContext::GetDefaultStoragePartition(profile)
204 ->GetNetworkContext();
205 },
206 profile);
207 password_manager_util::RemoveUselessCredentials(
208 CredentialsCleanerRunnerFactory::GetForProfile(profile), ps,
209 profile->GetPrefs(), base::TimeDelta::FromSeconds(60),
210 network_context_getter);
211
212 #if !defined(OS_ANDROID)
213 ps->SetUnsyncedCredentialsDeletionNotifier(
214 std::make_unique<UnsyncedCredentialsDeletionNotifierImpl>(profile));
215 #endif // !defined(OS_ANDROID)
216
217 return ps;
218 }
219
GetBrowserContextToUse(content::BrowserContext * context) const220 content::BrowserContext* AccountPasswordStoreFactory::GetBrowserContextToUse(
221 content::BrowserContext* context) const {
222 return chrome::GetBrowserContextRedirectedInIncognito(context);
223 }
224
ServiceIsNULLWhileTesting() const225 bool AccountPasswordStoreFactory::ServiceIsNULLWhileTesting() const {
226 return true;
227 }
228