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