1 // Copyright (c) 2012 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/webdata/web_data_service_factory.h" 6 7 #include "base/bind.h" 8 #include "base/files/file_path.h" 9 #include "chrome/browser/browser_process.h" 10 #include "chrome/browser/profiles/incognito_helpers.h" 11 #include "chrome/browser/sync/glue/sync_start_util.h" 12 #include "chrome/browser/ui/profile_error_dialog.h" 13 #include "chrome/browser/webdata/autocomplete_syncable_service.h" 14 #include "chrome/grit/chromium_strings.h" 15 #include "chrome/grit/generated_resources.h" 16 #include "components/autofill/core/browser/autofill_country.h" 17 #include "components/autofill/core/browser/webdata/autofill_profile_syncable_service.h" 18 #include "components/autofill/core/browser/webdata/autofill_table.h" 19 #include "components/autofill/core/browser/webdata/autofill_webdata_service.h" 20 #include "components/keyed_service/content/browser_context_dependency_manager.h" 21 #include "components/password_manager/core/browser/webdata/logins_table.h" 22 #include "components/search_engines/keyword_table.h" 23 #include "components/search_engines/keyword_web_data_service.h" 24 #include "components/signin/core/browser/webdata/token_service_table.h" 25 #include "components/signin/core/browser/webdata/token_web_data.h" 26 #include "components/webdata/common/webdata_constants.h" 27 #include "content/public/browser/browser_thread.h" 28 29 #if defined(OS_WIN) 30 #include "components/password_manager/core/browser/webdata/password_web_data_service_win.h" 31 #endif 32 33 using autofill::AutofillWebDataService; 34 using autofill::AutofillProfileSyncableService; 35 using content::BrowserThread; 36 37 namespace { 38 39 // Callback to show error dialog on profile load error. 40 void ProfileErrorCallback(ProfileErrorType type, sql::InitStatus status) { 41 ShowProfileErrorDialog( 42 type, 43 (status == sql::INIT_FAILURE) ? 44 IDS_COULDNT_OPEN_PROFILE_ERROR : IDS_PROFILE_TOO_NEW_ERROR); 45 } 46 47 void InitSyncableServicesOnDBThread( 48 scoped_refptr<AutofillWebDataService> autofill_web_data, 49 const base::FilePath& profile_path, 50 const std::string& app_locale, 51 autofill::AutofillWebDataBackend* autofill_backend) { 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); 53 54 // Currently only Autocomplete and Autofill profiles use the new Sync API, but 55 // all the database data should migrate to this API over time. 56 AutocompleteSyncableService::CreateForWebDataServiceAndBackend( 57 autofill_web_data.get(), autofill_backend); 58 AutocompleteSyncableService::FromWebDataService(autofill_web_data.get()) 59 ->InjectStartSyncFlare( 60 sync_start_util::GetFlareForSyncableService(profile_path)); 61 AutofillProfileSyncableService::CreateForWebDataServiceAndBackend( 62 autofill_web_data.get(), autofill_backend, app_locale); 63 AutofillProfileSyncableService::FromWebDataService(autofill_web_data.get()) 64 ->InjectStartSyncFlare( 65 sync_start_util::GetFlareForSyncableService(profile_path)); 66 } 67 68 } // namespace 69 70 WebDataServiceWrapper::WebDataServiceWrapper() { 71 } 72 73 WebDataServiceWrapper::WebDataServiceWrapper(Profile* profile) { 74 base::FilePath profile_path = profile->GetPath(); 75 base::FilePath path = profile_path.Append(kWebDataFilename); 76 77 scoped_refptr<base::MessageLoopProxy> ui_thread = 78 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI); 79 scoped_refptr<base::MessageLoopProxy> db_thread = 80 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::DB); 81 web_database_ = new WebDatabaseService(path, ui_thread, db_thread); 82 83 // All tables objects that participate in managing the database must 84 // be added here. 85 web_database_->AddTable(scoped_ptr<WebDatabaseTable>( 86 new autofill::AutofillTable(g_browser_process->GetApplicationLocale()))); 87 web_database_->AddTable(scoped_ptr<WebDatabaseTable>(new KeywordTable())); 88 // TODO(mdm): We only really need the LoginsTable on Windows for IE7 password 89 // access, but for now, we still create it on all platforms since it deletes 90 // the old logins table. We can remove this after a while, e.g. in M22 or so. 91 web_database_->AddTable(scoped_ptr<WebDatabaseTable>(new LoginsTable())); 92 web_database_->AddTable( 93 scoped_ptr<WebDatabaseTable>(new TokenServiceTable())); 94 95 web_database_->LoadDatabase(); 96 97 autofill_web_data_ = new AutofillWebDataService( 98 web_database_, 99 ui_thread, 100 db_thread, 101 base::Bind(&ProfileErrorCallback, PROFILE_ERROR_DB_AUTOFILL_WEB_DATA)); 102 autofill_web_data_->Init(); 103 104 keyword_web_data_ = new KeywordWebDataService( 105 web_database_, 106 ui_thread, 107 base::Bind(&ProfileErrorCallback, PROFILE_ERROR_DB_KEYWORD_WEB_DATA)); 108 keyword_web_data_->Init(); 109 110 token_web_data_ = new TokenWebData( 111 web_database_, 112 ui_thread, 113 db_thread, 114 base::Bind(&ProfileErrorCallback, PROFILE_ERROR_DB_TOKEN_WEB_DATA)); 115 token_web_data_->Init(); 116 117 #if defined(OS_WIN) 118 password_web_data_ = new PasswordWebDataService( 119 web_database_, 120 ui_thread, 121 base::Bind(&ProfileErrorCallback, PROFILE_ERROR_DB_WEB_DATA)); 122 password_web_data_->Init(); 123 #endif 124 125 autofill_web_data_->GetAutofillBackend( 126 base::Bind(&InitSyncableServicesOnDBThread, 127 autofill_web_data_, 128 profile_path, 129 g_browser_process->GetApplicationLocale())); 130 } 131 132 WebDataServiceWrapper::~WebDataServiceWrapper() { 133 } 134 135 void WebDataServiceWrapper::Shutdown() { 136 autofill_web_data_->ShutdownOnUIThread(); 137 keyword_web_data_->ShutdownOnUIThread(); 138 token_web_data_->ShutdownOnUIThread(); 139 140 #if defined(OS_WIN) 141 password_web_data_->ShutdownOnUIThread(); 142 #endif 143 web_database_->ShutdownDatabase(); 144 } 145 146 scoped_refptr<AutofillWebDataService> 147 WebDataServiceWrapper::GetAutofillWebData() { 148 return autofill_web_data_.get(); 149 } 150 151 scoped_refptr<KeywordWebDataService> 152 WebDataServiceWrapper::GetKeywordWebData() { 153 return keyword_web_data_.get(); 154 } 155 156 scoped_refptr<TokenWebData> WebDataServiceWrapper::GetTokenWebData() { 157 return token_web_data_.get(); 158 } 159 160 #if defined(OS_WIN) 161 scoped_refptr<PasswordWebDataService> 162 WebDataServiceWrapper::GetPasswordWebData() { 163 return password_web_data_.get(); 164 } 165 #endif 166 167 WebDataServiceFactory::WebDataServiceFactory() 168 : BrowserContextKeyedServiceFactory( 169 "WebDataService", 170 BrowserContextDependencyManager::GetInstance()) { 171 // WebDataServiceFactory has no dependecies. 172 } 173 174 WebDataServiceFactory::~WebDataServiceFactory() { 175 } 176 177 // static 178 WebDataServiceWrapper* WebDataServiceFactory::GetForProfile( 179 Profile* profile, 180 Profile::ServiceAccessType access_type) { 181 // If |access_type| starts being used for anything other than this 182 // DCHECK, we need to start taking it as a parameter to 183 // the *WebDataService::FromBrowserContext() functions (see above). 184 DCHECK(access_type != Profile::IMPLICIT_ACCESS || !profile->IsOffTheRecord()); 185 return static_cast<WebDataServiceWrapper*>( 186 GetInstance()->GetServiceForBrowserContext(profile, true)); 187 } 188 189 // static 190 WebDataServiceWrapper* WebDataServiceFactory::GetForProfileIfExists( 191 Profile* profile, 192 Profile::ServiceAccessType access_type) { 193 // If |access_type| starts being used for anything other than this 194 // DCHECK, we need to start taking it as a parameter to 195 // the *WebDataService::FromBrowserContext() functions (see above). 196 DCHECK(access_type != Profile::IMPLICIT_ACCESS || !profile->IsOffTheRecord()); 197 return static_cast<WebDataServiceWrapper*>( 198 GetInstance()->GetServiceForBrowserContext(profile, false)); 199 } 200 201 // static 202 scoped_refptr<AutofillWebDataService> 203 WebDataServiceFactory::GetAutofillWebDataForProfile( 204 Profile* profile, 205 Profile::ServiceAccessType access_type) { 206 WebDataServiceWrapper* wrapper = 207 WebDataServiceFactory::GetForProfile(profile, access_type); 208 // |wrapper| can be NULL in Incognito mode. 209 return wrapper ? 210 wrapper->GetAutofillWebData() : 211 scoped_refptr<AutofillWebDataService>(NULL); 212 } 213 214 // static 215 scoped_refptr<KeywordWebDataService> 216 WebDataServiceFactory::GetKeywordWebDataForProfile( 217 Profile* profile, 218 Profile::ServiceAccessType access_type) { 219 WebDataServiceWrapper* wrapper = 220 WebDataServiceFactory::GetForProfile(profile, access_type); 221 // |wrapper| can be NULL in Incognito mode. 222 return wrapper ? 223 wrapper->GetKeywordWebData() : scoped_refptr<KeywordWebDataService>(NULL); 224 } 225 226 // static 227 scoped_refptr<TokenWebData> WebDataServiceFactory::GetTokenWebDataForProfile( 228 Profile* profile, 229 Profile::ServiceAccessType access_type) { 230 WebDataServiceWrapper* wrapper = 231 WebDataServiceFactory::GetForProfile(profile, access_type); 232 // |wrapper| can be NULL in Incognito mode. 233 return wrapper ? 234 wrapper->GetTokenWebData() : scoped_refptr<TokenWebData>(NULL); 235 } 236 237 #if defined(OS_WIN) 238 // static 239 scoped_refptr<PasswordWebDataService> 240 WebDataServiceFactory::GetPasswordWebDataForProfile( 241 Profile* profile, 242 Profile::ServiceAccessType access_type) { 243 WebDataServiceWrapper* wrapper = 244 WebDataServiceFactory::GetForProfile(profile, access_type); 245 // |wrapper| can be NULL in Incognito mode. 246 return wrapper ? 247 wrapper->GetPasswordWebData() : 248 scoped_refptr<PasswordWebDataService>(NULL); 249 } 250 #endif 251 252 // static 253 WebDataServiceFactory* WebDataServiceFactory::GetInstance() { 254 return Singleton<WebDataServiceFactory>::get(); 255 } 256 257 content::BrowserContext* WebDataServiceFactory::GetBrowserContextToUse( 258 content::BrowserContext* context) const { 259 return chrome::GetBrowserContextRedirectedInIncognito(context); 260 } 261 262 KeyedService* WebDataServiceFactory::BuildServiceInstanceFor( 263 content::BrowserContext* profile) const { 264 return new WebDataServiceWrapper(static_cast<Profile*>(profile)); 265 } 266 267 bool WebDataServiceFactory::ServiceIsNULLWhileTesting() const { 268 return true; 269 } 270