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