• 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/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.
ProfileErrorCallback(ProfileErrorType type,sql::InitStatus status)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 
InitSyncableServicesOnDBThread(scoped_refptr<AutofillWebDataService> autofill_web_data,const base::FilePath & profile_path,const std::string & app_locale,autofill::AutofillWebDataBackend * autofill_backend)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 
WebDataServiceWrapper()67 WebDataServiceWrapper::WebDataServiceWrapper() {}
68 
WebDataServiceWrapper(Profile * profile)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 
~WebDataServiceWrapper()124 WebDataServiceWrapper::~WebDataServiceWrapper() {
125 }
126 
Shutdown()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>
GetAutofillWebData()135 WebDataServiceWrapper::GetAutofillWebData() {
136   return autofill_web_data_.get();
137 }
138 
GetWebData()139 scoped_refptr<WebDataService> WebDataServiceWrapper::GetWebData() {
140   return web_data_.get();
141 }
142 
GetTokenWebData()143 scoped_refptr<TokenWebData> WebDataServiceWrapper::GetTokenWebData() {
144   return token_web_data_.get();
145 }
146 
147 // static
FromBrowserContext(content::BrowserContext * context)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
FromBrowserContext(content::BrowserContext * context)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 
WebDataServiceFactory()177 WebDataServiceFactory::WebDataServiceFactory()
178     : BrowserContextKeyedServiceFactory(
179         "WebDataService",
180         BrowserContextDependencyManager::GetInstance()) {
181   // WebDataServiceFactory has no dependecies.
182 }
183 
~WebDataServiceFactory()184 WebDataServiceFactory::~WebDataServiceFactory() {}
185 
186 // static
GetForProfile(Profile * profile,Profile::ServiceAccessType access_type)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
GetForProfileIfExists(Profile * profile,Profile::ServiceAccessType access_type)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>
GetAutofillWebDataForProfile(Profile * profile,Profile::ServiceAccessType access_type)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
GetInstance()224 WebDataServiceFactory* WebDataServiceFactory::GetInstance() {
225   return Singleton<WebDataServiceFactory>::get();
226 }
227 
GetBrowserContextToUse(content::BrowserContext * context) const228 content::BrowserContext* WebDataServiceFactory::GetBrowserContextToUse(
229     content::BrowserContext* context) const {
230   return chrome::GetBrowserContextRedirectedInIncognito(context);
231 }
232 
BuildServiceInstanceFor(content::BrowserContext * profile) const233 BrowserContextKeyedService* WebDataServiceFactory::BuildServiceInstanceFor(
234     content::BrowserContext* profile) const {
235   return new WebDataServiceWrapper(static_cast<Profile*>(profile));
236 }
237 
ServiceIsNULLWhileTesting() const238 bool WebDataServiceFactory::ServiceIsNULLWhileTesting() const {
239   return true;
240 }
241