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