• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
ProfileErrorCallback(ProfileErrorType type,sql::InitStatus status)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 
InitSyncableServicesOnDBThread(scoped_refptr<AutofillWebDataService> autofill_web_data,const base::FilePath & profile_path,const std::string & app_locale,autofill::AutofillWebDataBackend * autofill_backend)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 
WebDataServiceWrapper()68 WebDataServiceWrapper::WebDataServiceWrapper() {}
69 
WebDataServiceWrapper(Profile * profile)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 
~WebDataServiceWrapper()125 WebDataServiceWrapper::~WebDataServiceWrapper() {
126 }
127 
Shutdown()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>
GetAutofillWebData()136 WebDataServiceWrapper::GetAutofillWebData() {
137   return autofill_web_data_.get();
138 }
139 
GetWebData()140 scoped_refptr<WebDataService> WebDataServiceWrapper::GetWebData() {
141   return web_data_.get();
142 }
143 
GetTokenWebData()144 scoped_refptr<TokenWebData> WebDataServiceWrapper::GetTokenWebData() {
145   return token_web_data_.get();
146 }
147 
148 // static
FromBrowserContext(content::BrowserContext * context)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 
WebDataServiceFactory()163 WebDataServiceFactory::WebDataServiceFactory()
164     : BrowserContextKeyedServiceFactory(
165         "WebDataService",
166         BrowserContextDependencyManager::GetInstance()) {
167   // WebDataServiceFactory has no dependecies.
168 }
169 
~WebDataServiceFactory()170 WebDataServiceFactory::~WebDataServiceFactory() {}
171 
172 // static
GetForProfile(Profile * profile,Profile::ServiceAccessType access_type)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
GetForProfileIfExists(Profile * profile,Profile::ServiceAccessType access_type)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>
GetAutofillWebDataForProfile(Profile * profile,Profile::ServiceAccessType access_type)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>
GetTokenWebDataForProfile(Profile * profile,Profile::ServiceAccessType access_type)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
GetInstance()222 WebDataServiceFactory* WebDataServiceFactory::GetInstance() {
223   return Singleton<WebDataServiceFactory>::get();
224 }
225 
GetBrowserContextToUse(content::BrowserContext * context) const226 content::BrowserContext* WebDataServiceFactory::GetBrowserContextToUse(
227     content::BrowserContext* context) const {
228   return chrome::GetBrowserContextRedirectedInIncognito(context);
229 }
230 
BuildServiceInstanceFor(content::BrowserContext * profile) const231 KeyedService* WebDataServiceFactory::BuildServiceInstanceFor(
232     content::BrowserContext* profile) const {
233   return new WebDataServiceWrapper(static_cast<Profile*>(profile));
234 }
235 
ServiceIsNULLWhileTesting() const236 bool WebDataServiceFactory::ServiceIsNULLWhileTesting() const {
237   return true;
238 }
239