1// Copyright 2020 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#import "ios/web_view/internal/passwords/web_view_account_password_store_factory.h" 6 7#include <memory> 8#include <utility> 9 10#include "base/bind.h" 11#include "base/callback_helpers.h" 12#include "base/task/post_task.h" 13#include "components/keyed_service/ios/browser_state_dependency_manager.h" 14#include "components/password_manager/core/browser/login_database.h" 15#include "components/password_manager/core/browser/password_manager_constants.h" 16#include "components/password_manager/core/browser/password_manager_util.h" 17#include "components/password_manager/core/browser/password_store_default.h" 18#include "components/password_manager/core/browser/password_store_factory_util.h" 19#include "components/password_manager/core/common/password_manager_features.h" 20#include "components/prefs/pref_service.h" 21#include "ios/web/public/thread/web_task_traits.h" 22#include "ios/web/public/thread/web_thread.h" 23#include "ios/web_view/internal/webdata_services/web_view_web_data_service_wrapper_factory.h" 24 25#if !defined(__has_feature) || !__has_feature(objc_arc) 26#error "This file requires ARC support." 27#endif 28 29NSNotificationName const CWVPasswordStoreSyncToggledNotification = 30 @"CWVPasswordStoreSyncToggledNotification"; 31NSString* const CWVPasswordStoreNotificationBrowserStateKey = 32 @"CWVPasswordStoreNotificationBrowserStateKey"; 33 34namespace ios_web_view { 35 36namespace { 37 38void UpdateFormManager(WebViewBrowserState* browser_state) { 39 NSValue* wrapped_browser_state = [NSValue valueWithPointer:browser_state]; 40 [NSNotificationCenter.defaultCenter 41 postNotificationName:CWVPasswordStoreSyncToggledNotification 42 object:nil 43 userInfo:@{ 44 CWVPasswordStoreNotificationBrowserStateKey : 45 wrapped_browser_state 46 }]; 47} 48 49void SyncEnabledOrDisabled(WebViewBrowserState* browser_state) { 50 base::PostTask(FROM_HERE, {web::WebThread::UI}, 51 base::BindOnce(&UpdateFormManager, browser_state)); 52} 53 54} // namespace 55 56// static 57scoped_refptr<password_manager::PasswordStore> 58WebViewAccountPasswordStoreFactory::GetForBrowserState( 59 WebViewBrowserState* browser_state, 60 ServiceAccessType access_type) { 61 if (!base::FeatureList::IsEnabled( 62 password_manager::features::kEnablePasswordsAccountStorage)) { 63 return nullptr; 64 } 65 66 // |browser_state| always gets redirected to a the recording version in 67 // |GetBrowserStateToUse|. 68 if (access_type == ServiceAccessType::IMPLICIT_ACCESS && 69 browser_state->IsOffTheRecord()) { 70 return nullptr; 71 } 72 73 return base::WrapRefCounted(static_cast<password_manager::PasswordStore*>( 74 GetInstance()->GetServiceForBrowserState(browser_state, true).get())); 75} 76 77// static 78WebViewAccountPasswordStoreFactory* 79WebViewAccountPasswordStoreFactory::GetInstance() { 80 static base::NoDestructor<WebViewAccountPasswordStoreFactory> instance; 81 return instance.get(); 82} 83 84WebViewAccountPasswordStoreFactory::WebViewAccountPasswordStoreFactory() 85 : RefcountedBrowserStateKeyedServiceFactory( 86 "AccountPasswordStore", 87 BrowserStateDependencyManager::GetInstance()) { 88 DependsOn(WebViewWebDataServiceWrapperFactory::GetInstance()); 89} 90 91WebViewAccountPasswordStoreFactory::~WebViewAccountPasswordStoreFactory() {} 92 93scoped_refptr<RefcountedKeyedService> 94WebViewAccountPasswordStoreFactory::BuildServiceInstanceFor( 95 web::BrowserState* context) const { 96 DCHECK(base::FeatureList::IsEnabled( 97 password_manager::features::kEnablePasswordsAccountStorage)); 98 99 WebViewBrowserState* browser_state = 100 WebViewBrowserState::FromBrowserState(context); 101 102 std::unique_ptr<password_manager::LoginDatabase> login_db( 103 password_manager::CreateLoginDatabaseForAccountStorage( 104 browser_state->GetStatePath())); 105 106 scoped_refptr<password_manager::PasswordStore> ps = 107 new password_manager::PasswordStoreDefault(std::move(login_db)); 108 if (!ps->Init(browser_state->GetPrefs(), 109 base::BindRepeating(&SyncEnabledOrDisabled, browser_state))) { 110 // TODO(crbug.com/479725): Remove the LOG once this error is visible in the 111 // UI. 112 LOG(WARNING) << "Could not initialize password store."; 113 return nullptr; 114 } 115 116 return ps; 117} 118 119web::BrowserState* WebViewAccountPasswordStoreFactory::GetBrowserStateToUse( 120 web::BrowserState* context) const { 121 WebViewBrowserState* browser_state = 122 WebViewBrowserState::FromBrowserState(context); 123 return browser_state->GetRecordingBrowserState(); 124} 125 126bool WebViewAccountPasswordStoreFactory::ServiceIsNULLWhileTesting() const { 127 return true; 128} 129 130} // namespace ios_web_view 131