blob: 36517c4f88cb25feb2ffa7eb06b36451c8feac9c [file] [log] [blame]
license.botbf09a502008-08-24 00:55:551// Copyright (c) 2006-2008 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.
initial.commit09911bf2008-07-26 23:55:294
5#include "chrome/browser/profile.h"
6
7#include "base/command_line.h"
[email protected]04fba9a92008-10-28 17:25:258#include "base/file_path.h"
initial.commit09911bf2008-07-26 23:55:299#include "base/file_util.h"
initial.commit09911bf2008-07-26 23:55:2910#include "base/path_service.h"
11#include "base/scoped_ptr.h"
12#include "base/string_util.h"
[email protected]a9afddb2009-02-12 17:49:4213#include "chrome/browser/bookmarks/bookmark_model.h"
initial.commit09911bf2008-07-26 23:55:2914#include "chrome/browser/browser_list.h"
15#include "chrome/browser/browser_process.h"
[email protected]67a46b7f2009-06-16 21:41:0216#include "chrome/browser/browser_theme_provider.h"
[email protected]b7f05882009-02-22 01:21:5617#include "chrome/browser/download/download_manager.h"
[email protected]481e1a42009-05-06 20:56:0518#include "chrome/browser/extensions/extension_process_manager.h"
[email protected]6014d672008-12-05 00:38:2519#include "chrome/browser/extensions/extensions_service.h"
[email protected]0938d3c2009-01-09 20:37:3520#include "chrome/browser/extensions/user_script_master.h"
[email protected]a9afddb2009-02-12 17:49:4221#include "chrome/browser/history/history.h"
[email protected]3bf335a2009-06-26 20:46:0622#include "chrome/browser/in_process_webkit/webkit_context.h"
[email protected]6ab9b202008-12-23 22:34:5023#include "chrome/browser/net/chrome_url_request_context.h"
[email protected]e69d33952009-06-03 22:00:4124#include "chrome/browser/password_manager/password_store_default.h"
[email protected]eaadd9052009-06-23 18:02:2325#include "chrome/browser/privacy_blacklist/blacklist.h"
initial.commit09911bf2008-07-26 23:55:2926#include "chrome/browser/profile_manager.h"
[email protected]8c8657d62009-01-16 18:31:2627#include "chrome/browser/renderer_host/render_process_host.h"
[email protected]1132436e2009-04-08 20:06:3328#include "chrome/browser/search_engines/template_url_fetcher.h"
[email protected]f63ae312009-02-04 17:58:4629#include "chrome/browser/search_engines/template_url_model.h"
[email protected]85e921fb82009-02-11 23:19:4430#include "chrome/browser/sessions/session_service.h"
[email protected]bd580a252009-02-12 01:16:3031#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]f0a644292009-02-25 23:32:4732#include "chrome/browser/spellchecker.h"
[email protected]1132436e2009-04-08 20:06:3333#include "chrome/browser/ssl/ssl_host_state.h"
[email protected]449478302009-06-09 20:04:2834#include "chrome/browser/thumbnail_store.h"
initial.commit09911bf2008-07-26 23:55:2935#include "chrome/browser/visitedlink_master.h"
[email protected]3e90d4a2009-07-03 17:38:3936#include "chrome/browser/visitedlink_event_listener.h"
initial.commit09911bf2008-07-26 23:55:2937#include "chrome/browser/webdata/web_data_service.h"
38#include "chrome/common/chrome_constants.h"
39#include "chrome/common/chrome_paths.h"
40#include "chrome/common/chrome_switches.h"
[email protected]5b1a0e22009-05-26 19:00:5841#include "chrome/common/extensions/extension_error_reporter.h"
[email protected]47accfd62009-05-14 18:46:2142#include "chrome/common/net/cookie_monster_sqlite.h"
initial.commit09911bf2008-07-26 23:55:2943#include "chrome/common/notification_service.h"
44#include "chrome/common/pref_names.h"
[email protected]f7011fcb2009-01-28 21:54:3245#include "chrome/common/render_messages.h"
[email protected]f90f5c512009-02-18 19:10:5846#include "grit/locale_settings.h"
[email protected]a9cea7542009-05-20 04:30:2347#include "net/base/force_tls_state.h"
initial.commit09911bf2008-07-26 23:55:2948
[email protected]a5166af62009-07-03 00:42:2949#if defined(OS_LINUX)
50#include "chrome/browser/gtk/gtk_theme_provider.h"
51#endif
52
[email protected]e1acf6f2008-10-27 20:43:3353using base::Time;
54using base::TimeDelta;
55
[email protected]e5642992009-06-26 23:06:3156namespace {
57
initial.commit09911bf2008-07-26 23:55:2958// Delay, in milliseconds, before we explicitly create the SessionService.
59static const int kCreateSessionServiceDelayMS = 500;
60
[email protected]e5642992009-06-26 23:06:3161enum ContextType {
62 kNormalContext,
63 kMediaContext
64};
65
66// Gets the cache parameters from the command line. |type| is the type of
67// request context that we need, |cache_path| will be set to the user provided
68// path, or will not be touched if there is not an argument. |max_size| will
69// be the user provided value or zero by default.
70void GetCacheParameters(ContextType type, FilePath* cache_path,
71 int* max_size) {
72 DCHECK(cache_path);
73 DCHECK(max_size);
74
75 // Override the cache location if specified by the user.
76 std::wstring user_path(CommandLine::ForCurrentProcess()->GetSwitchValue(
77 switches::kDiskCacheDir));
78
79 if (!user_path.empty()) {
80 *cache_path = FilePath::FromWStringHack(user_path);
81 }
82
83 const wchar_t* arg = kNormalContext == type ? switches::kDiskCacheSize :
84 switches::kMediaCacheSize;
85 std::string value =
86 WideToASCII(CommandLine::ForCurrentProcess()->GetSwitchValue(arg));
87
88 // By default we let the cache determine the right size.
89 *max_size = 0;
90 if (!StringToInt(value, max_size)) {
91 *max_size = 0;
92 } else if (max_size < 0) {
93 *max_size = 0;
94 }
95}
96
97} // namespace
98
initial.commit09911bf2008-07-26 23:55:2999// A pointer to the request context for the default profile. See comments on
100// Profile::GetDefaultRequestContext.
101URLRequestContext* Profile::default_request_context_;
102
[email protected]47accfd62009-05-14 18:46:21103static void CleanupRequestContext(ChromeURLRequestContext* context) {
104 if (context) {
105 context->CleanupOnUIThread();
106
107 // Clean up request context on IO thread.
108 g_browser_process->io_thread()->message_loop()->ReleaseSoon(FROM_HERE,
109 context);
110 }
111}
112
[email protected]34cc84f2009-02-13 10:04:35113// static
initial.commit09911bf2008-07-26 23:55:29114void Profile::RegisterUserPrefs(PrefService* prefs) {
[email protected]430d3f72008-10-27 17:56:55115 prefs->RegisterBooleanPref(prefs::kSearchSuggestEnabled, true);
initial.commit09911bf2008-07-26 23:55:29116 prefs->RegisterBooleanPref(prefs::kSessionExitedCleanly, true);
117 prefs->RegisterBooleanPref(prefs::kSafeBrowsingEnabled, true);
[email protected]74c8b422009-03-11 00:34:12118 // TODO(estade): IDS_SPELLCHECK_DICTIONARY should be an ASCII string.
[email protected]e7244d82008-10-29 18:13:26119 prefs->RegisterLocalizedStringPref(prefs::kSpellCheckDictionary,
120 IDS_SPELLCHECK_DICTIONARY);
121 prefs->RegisterBooleanPref(prefs::kEnableSpellCheck, true);
[email protected]154a4332009-06-03 20:20:58122 prefs->RegisterBooleanPref(prefs::kEnableAutoSpellCorrect, true);
[email protected]f93fe782009-02-19 01:26:13123 prefs->RegisterBooleanPref(prefs::kEnableUserScripts, false);
[email protected]a5166af62009-07-03 00:42:29124#if defined(OS_LINUX)
125 prefs->RegisterBooleanPref(prefs::kUsesSystemTheme, false);
126#endif
[email protected]4a190632009-05-09 01:07:42127 prefs->RegisterStringPref(prefs::kCurrentThemeID, L"");
128 prefs->RegisterDictionaryPref(prefs::kCurrentThemeImages);
129 prefs->RegisterDictionaryPref(prefs::kCurrentThemeColors);
130 prefs->RegisterDictionaryPref(prefs::kCurrentThemeTints);
[email protected]7895ea22009-06-02 20:53:50131 prefs->RegisterDictionaryPref(prefs::kCurrentThemeDisplayProperties);
[email protected]f93fe782009-02-19 01:26:13132 prefs->RegisterBooleanPref(prefs::kEnableExtensions, false);
initial.commit09911bf2008-07-26 23:55:29133}
134
[email protected]34cc84f2009-02-13 10:04:35135// static
[email protected]f7011fcb2009-01-28 21:54:32136Profile* Profile::CreateProfile(const FilePath& path) {
initial.commit09911bf2008-07-26 23:55:29137 return new ProfileImpl(path);
138}
139
[email protected]34cc84f2009-02-13 10:04:35140// static
initial.commit09911bf2008-07-26 23:55:29141URLRequestContext* Profile::GetDefaultRequestContext() {
142 return default_request_context_;
143}
144
[email protected]e69d33952009-06-03 22:00:41145#if defined(OS_LINUX)
146// Temporarily disabled while we figure some stuff out.
147// http://code.google.com/p/chromium/issues/detail?id=12351
148// #include "chrome/browser/password_manager/password_store_gnome.h"
149// #include "chrome/browser/password_manager/password_store_kwallet.h"
150#elif defined(OS_WIN)
151#include "chrome/browser/password_manager/password_store_win.h"
[email protected]034eba52009-06-03 22:50:56152#elif defined(OS_MACOSX)
153#include "chrome/browser/keychain_mac.h"
[email protected]e0411ae52009-06-30 23:59:17154#include "chrome/browser/password_manager/login_database_mac.h"
[email protected]034eba52009-06-03 22:50:56155#include "chrome/browser/password_manager/password_store_mac.h"
[email protected]e69d33952009-06-03 22:00:41156#endif
initial.commit09911bf2008-07-26 23:55:29157
initial.commit09911bf2008-07-26 23:55:29158////////////////////////////////////////////////////////////////////////////////
159//
160// OffTheRecordProfileImpl is a profile subclass that wraps an existing profile
[email protected]4a190632009-05-09 01:07:42161// to make it suitable for the off the record mode.
initial.commit09911bf2008-07-26 23:55:29162//
163////////////////////////////////////////////////////////////////////////////////
164class OffTheRecordProfileImpl : public Profile,
165 public NotificationObserver {
166 public:
167 explicit OffTheRecordProfileImpl(Profile* real_profile)
168 : profile_(real_profile),
[email protected]47accfd62009-05-14 18:46:21169 extensions_request_context_(NULL),
initial.commit09911bf2008-07-26 23:55:29170 start_time_(Time::Now()) {
[email protected]6ab9b202008-12-23 22:34:50171 request_context_ = ChromeURLRequestContext::CreateOffTheRecord(this);
initial.commit09911bf2008-07-26 23:55:29172 request_context_->AddRef();
[email protected]481e1a42009-05-06 20:56:05173
initial.commit09911bf2008-07-26 23:55:29174 // Register for browser close notifications so we can detect when the last
175 // off-the-record window is closed, in which case we can clean our states
176 // (cookies, downloads...).
[email protected]88cf3292009-05-22 01:48:43177 registrar_.Add(this, NotificationType::BROWSER_CLOSED,
178 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29179 }
180
181 virtual ~OffTheRecordProfileImpl() {
[email protected]47accfd62009-05-14 18:46:21182 CleanupRequestContext(request_context_);
[email protected]47accfd62009-05-14 18:46:21183 CleanupRequestContext(extensions_request_context_);
initial.commit09911bf2008-07-26 23:55:29184 }
185
[email protected]f7011fcb2009-01-28 21:54:32186 virtual FilePath GetPath() { return profile_->GetPath(); }
initial.commit09911bf2008-07-26 23:55:29187
188 virtual bool IsOffTheRecord() {
189 return true;
190 }
191
192 virtual Profile* GetOffTheRecordProfile() {
193 return this;
194 }
195
[email protected]860f55492009-03-27 19:50:59196 virtual void DestroyOffTheRecordProfile() {
197 // Suicide is bad!
198 NOTREACHED();
199 }
200
initial.commit09911bf2008-07-26 23:55:29201 virtual Profile* GetOriginalProfile() {
202 return profile_;
203 }
204
205 virtual VisitedLinkMaster* GetVisitedLinkMaster() {
[email protected]7fb6c862009-03-13 02:51:49206 // We don't provide access to the VisitedLinkMaster when we're OffTheRecord
207 // because we don't want to leak the sites that the user has visited before.
208 return NULL;
initial.commit09911bf2008-07-26 23:55:29209 }
210
[email protected]6014d672008-12-05 00:38:25211 virtual ExtensionsService* GetExtensionsService() {
[email protected]1bd54132009-06-11 00:05:34212 return NULL;
[email protected]6014d672008-12-05 00:38:25213 }
214
[email protected]0938d3c2009-01-09 20:37:35215 virtual UserScriptMaster* GetUserScriptMaster() {
216 return profile_->GetUserScriptMaster();
[email protected]04fba9a92008-10-28 17:25:25217 }
218
[email protected]481e1a42009-05-06 20:56:05219 virtual ExtensionProcessManager* GetExtensionProcessManager() {
[email protected]1bd54132009-06-11 00:05:34220 return NULL;
[email protected]481e1a42009-05-06 20:56:05221 }
222
[email protected]34cc84f2009-02-13 10:04:35223 virtual SSLHostState* GetSSLHostState() {
224 if (!ssl_host_state_.get())
225 ssl_host_state_.reset(new SSLHostState());
226
227 DCHECK(ssl_host_state_->CalledOnValidThread());
228 return ssl_host_state_.get();
229 }
230
[email protected]a9cea7542009-05-20 04:30:23231 virtual net::ForceTLSState* GetForceTLSState() {
232 if (!force_tls_state_.get())
233 force_tls_state_.reset(new net::ForceTLSState());
234
235 return force_tls_state_.get();
236 }
237
initial.commit09911bf2008-07-26 23:55:29238 virtual HistoryService* GetHistoryService(ServiceAccessType sat) {
239 if (sat == EXPLICIT_ACCESS) {
240 return profile_->GetHistoryService(sat);
241 } else {
242 NOTREACHED() << "This profile is OffTheRecord";
243 return NULL;
244 }
245 }
246
initial.commit09911bf2008-07-26 23:55:29247 virtual WebDataService* GetWebDataService(ServiceAccessType sat) {
248 if (sat == EXPLICIT_ACCESS) {
249 return profile_->GetWebDataService(sat);
250 } else {
251 NOTREACHED() << "This profile is OffTheRecord";
252 return NULL;
253 }
254 }
255
[email protected]e69d33952009-06-03 22:00:41256 virtual PasswordStore* GetPasswordStore(ServiceAccessType sat) {
257 if (sat == EXPLICIT_ACCESS) {
258 return profile_->GetPasswordStore(sat);
259 } else {
260 NOTREACHED() << "This profile is OffTheRecord";
261 return NULL;
262 }
263 }
264
initial.commit09911bf2008-07-26 23:55:29265 virtual PrefService* GetPrefs() {
266 return profile_->GetPrefs();
267 }
268
269 virtual TemplateURLModel* GetTemplateURLModel() {
270 return profile_->GetTemplateURLModel();
271 }
272
273 virtual TemplateURLFetcher* GetTemplateURLFetcher() {
274 return profile_->GetTemplateURLFetcher();
275 }
276
277 virtual DownloadManager* GetDownloadManager() {
278 if (!download_manager_.get()) {
279 scoped_refptr<DownloadManager> dlm(new DownloadManager);
280 dlm->Init(this);
281 download_manager_.swap(dlm);
282 }
283 return download_manager_.get();
284 }
285
286 virtual bool HasCreatedDownloadManager() const {
287 return (download_manager_.get() != NULL);
288 }
289
[email protected]4a190632009-05-09 01:07:42290 virtual void InitThemes() {
291 GetOriginalProfile()->InitThemes();
292 }
293
294 virtual void SetTheme(Extension* extension) {
295 GetOriginalProfile()->SetTheme(extension);
296 }
297
[email protected]a5166af62009-07-03 00:42:29298 virtual void SetNativeTheme() {
299 GetOriginalProfile()->SetNativeTheme();
300 }
301
[email protected]4a190632009-05-09 01:07:42302 virtual void ClearTheme() {
303 GetOriginalProfile()->ClearTheme();
304 }
305
306 virtual ThemeProvider* GetThemeProvider() {
307 return GetOriginalProfile()->GetThemeProvider();
308 }
309
initial.commit09911bf2008-07-26 23:55:29310 virtual URLRequestContext* GetRequestContext() {
311 return request_context_;
312 }
313
[email protected]e7f29642009-03-02 22:53:18314 virtual URLRequestContext* GetRequestContextForMedia() {
[email protected]d14c7ac2009-05-29 20:38:11315 // In OTR mode, media request context is the same as the original one.
316 return request_context_;
[email protected]e7f29642009-03-02 22:53:18317 }
318
[email protected]47accfd62009-05-14 18:46:21319 URLRequestContext* GetRequestContextForExtensions() {
320 if (!extensions_request_context_) {
321 extensions_request_context_ =
322 ChromeURLRequestContext::CreateOffTheRecordForExtensions(this);
323 extensions_request_context_->AddRef();
324
325 DCHECK(extensions_request_context_->cookie_store());
326 }
327
328 return extensions_request_context_;
329 }
330
[email protected]eaadd9052009-06-23 18:02:23331 virtual Blacklist* GetBlacklist() {
332 return GetOriginalProfile()->GetBlacklist();
333 }
334
initial.commit09911bf2008-07-26 23:55:29335 virtual SessionService* GetSessionService() {
336 // Don't save any sessions when off the record.
337 return NULL;
338 }
339
340 virtual void ShutdownSessionService() {
341 // We don't allow a session service, nothing to do.
342 }
343
344 virtual bool HasSessionService() const {
345 // We never have a session service.
346 return false;
347 }
348
349 virtual std::wstring GetName() {
350 return profile_->GetName();
351 }
352
353 virtual void SetName(const std::wstring& name) {
354 profile_->SetName(name);
355 }
356
357 virtual std::wstring GetID() {
358 return profile_->GetID();
359 }
360
361 virtual void SetID(const std::wstring& id) {
362 profile_->SetID(id);
363 }
364
initial.commit09911bf2008-07-26 23:55:29365 virtual bool DidLastSessionExitCleanly() {
366 return profile_->DidLastSessionExitCleanly();
367 }
368
[email protected]d8e41ed2008-09-11 15:22:32369 virtual BookmarkModel* GetBookmarkModel() {
370 return profile_->GetBookmarkModel();
initial.commit09911bf2008-07-26 23:55:29371 }
372
[email protected]3a453fa2008-08-15 18:46:34373#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:07374 virtual ProfilePersonalization* GetProfilePersonalization() {
[email protected]3a453fa2008-08-15 18:46:34375 return profile_->GetProfilePersonalization();
376 }
377#endif
378
initial.commit09911bf2008-07-26 23:55:29379 virtual bool IsSameProfile(Profile* profile) {
380 if (profile == static_cast<Profile*>(this))
381 return true;
382 return profile == profile_;
383 }
384
385 virtual Time GetStartTime() const {
386 return start_time_;
387 }
388
389 virtual TabRestoreService* GetTabRestoreService() {
390 return NULL;
391 }
392
[email protected]e7244d82008-10-29 18:13:26393 virtual void ResetTabRestoreService() {
[email protected]20930852008-10-15 19:30:41394 }
395
[email protected]e7244d82008-10-29 18:13:26396 virtual void ReinitializeSpellChecker() {
397 profile_->ReinitializeSpellChecker();
initial.commit09911bf2008-07-26 23:55:29398 }
399
400 virtual SpellChecker* GetSpellChecker() {
401 return profile_->GetSpellChecker();
402 }
403
[email protected]3bf335a2009-06-26 20:46:06404 virtual WebKitContext* GetWebKitContext() {
405 if (!webkit_context_.get())
406 webkit_context_ = new WebKitContext(GetPath(), true);
407 DCHECK(webkit_context_.get());
408 return webkit_context_.get();
409}
410
[email protected]449478302009-06-09 20:04:28411 virtual ThumbnailStore* GetThumbnailStore() {
412 return NULL;
413 }
414
initial.commit09911bf2008-07-26 23:55:29415 virtual void MarkAsCleanShutdown() {
416 }
417
[email protected]bdbc87c2009-01-25 05:08:54418 virtual void InitExtensions() {
419 NOTREACHED();
420 }
421
[email protected]ea0c98cf2009-06-18 23:02:54422 virtual void InitWebResources() {
423 NOTREACHED();
424 }
425
initial.commit09911bf2008-07-26 23:55:29426 virtual void ExitedOffTheRecordMode() {
427 // Drop our download manager so we forget about all the downloads made
428 // in off-the-record mode.
429 download_manager_ = NULL;
430 }
431
432 virtual void Observe(NotificationType type,
433 const NotificationSource& source,
434 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:56435 DCHECK_EQ(NotificationType::BROWSER_CLOSED, type.value);
initial.commit09911bf2008-07-26 23:55:29436 // We are only interested in OTR browser closing.
437 if (Source<Browser>(source)->profile() != this)
438 return;
439
440 // Let's check if we still have an Off The Record window opened.
441 // Note that we check against 1 as this notification is sent before the
442 // browser window is actually removed from the list.
443 if (BrowserList::GetBrowserCount(this) <= 1)
444 ExitedOffTheRecordMode();
445 }
446
447 private:
[email protected]88cf3292009-05-22 01:48:43448 NotificationRegistrar registrar_;
449
initial.commit09911bf2008-07-26 23:55:29450 // The real underlying profile.
451 Profile* profile_;
452
[email protected]6ab9b202008-12-23 22:34:50453 // The context to use for requests made from this OTR session.
454 ChromeURLRequestContext* request_context_;
initial.commit09911bf2008-07-26 23:55:29455
[email protected]47accfd62009-05-14 18:46:21456 ChromeURLRequestContext* extensions_request_context_;
457
initial.commit09911bf2008-07-26 23:55:29458 // The download manager that only stores downloaded items in memory.
459 scoped_refptr<DownloadManager> download_manager_;
460
[email protected]4a190632009-05-09 01:07:42461 scoped_refptr<BrowserThemeProvider> theme_provider_;
462
[email protected]3bf335a2009-06-26 20:46:06463 // Use a special WebKit context for OTR browsing.
464 scoped_refptr<WebKitContext> webkit_context_;
465
[email protected]34cc84f2009-02-13 10:04:35466 // We don't want SSLHostState from the OTR profile to leak back to the main
467 // profile because then the main profile would learn some of the host names
468 // the user visited while OTR.
469 scoped_ptr<SSLHostState> ssl_host_state_;
470
[email protected]a9cea7542009-05-20 04:30:23471 // The ForceTLSState that only stores enabled sites in memory.
472 scoped_ptr<net::ForceTLSState> force_tls_state_;
473
initial.commit09911bf2008-07-26 23:55:29474 // Time we were started.
475 Time start_time_;
476
477 DISALLOW_EVIL_CONSTRUCTORS(OffTheRecordProfileImpl);
478};
479
[email protected]f7011fcb2009-01-28 21:54:32480ProfileImpl::ProfileImpl(const FilePath& path)
initial.commit09911bf2008-07-26 23:55:29481 : path_(path),
[email protected]3e90d4a2009-07-03 17:38:39482 visited_link_event_listener_(new VisitedLinkEventListener()),
[email protected]f7011fcb2009-01-28 21:54:32483 request_context_(NULL),
[email protected]363347b2009-03-13 20:06:57484 media_request_context_(NULL),
[email protected]47accfd62009-05-14 18:46:21485 extensions_request_context_(NULL),
[email protected]eaadd9052009-06-23 18:02:23486 blacklist_(NULL),
[email protected]f7011fcb2009-01-28 21:54:32487 history_service_created_(false),
488 created_web_data_service_(false),
[email protected]e69d33952009-06-03 22:00:41489 created_password_store_(false),
[email protected]f7011fcb2009-01-28 21:54:32490 created_download_manager_(false),
[email protected]4a190632009-05-09 01:07:42491 created_theme_provider_(false),
[email protected]f7011fcb2009-01-28 21:54:32492 start_time_(Time::Now()),
493 spellchecker_(NULL),
initial.commit09911bf2008-07-26 23:55:29494 shutdown_session_service_(false) {
495 DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<
496 "profile files to the root directory!";
[email protected]2d316662008-09-03 18:18:14497 create_session_service_timer_.Start(
498 TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,
499 &ProfileImpl::EnsureSessionServiceCreated);
[email protected]bdbc87c2009-01-25 05:08:54500
[email protected]382a0702009-06-26 17:12:27501 extension_process_manager_.reset(new ExtensionProcessManager(this));
502
[email protected]e7244d82008-10-29 18:13:26503 PrefService* prefs = GetPrefs();
504 prefs->AddPrefObserver(prefs::kSpellCheckDictionary, this);
505 prefs->AddPrefObserver(prefs::kEnableSpellCheck, this);
[email protected]154a4332009-06-03 20:20:58506 prefs->AddPrefObserver(prefs::kEnableAutoSpellCorrect, this);
[email protected]380ab462009-04-24 01:23:58507
508#ifdef CHROME_PERSONALIZATION
509 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableP13n))
510 personalization_.reset(Personalization::CreateProfilePersonalization(this));
511#endif
512
[email protected]eaadd9052009-06-23 18:02:23513 if (CommandLine::ForCurrentProcess()->
514 HasSwitch(switches::kPrivacyBlacklist)) {
515 std::wstring option = CommandLine::ForCurrentProcess()->GetSwitchValue(
516 switches::kPrivacyBlacklist);
517#if defined(OS_POSIX)
518 FilePath path(WideToUTF8(option));
519#else
520 FilePath path(option);
521#endif
522 blacklist_ = new Blacklist(path);
523 }
524
[email protected]4a190632009-05-09 01:07:42525 // Listen for theme installation.
[email protected]88cf3292009-05-22 01:48:43526 registrar_.Add(this, NotificationType::THEME_INSTALLED,
527 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29528}
529
[email protected]bdbc87c2009-01-25 05:08:54530void ProfileImpl::InitExtensions() {
[email protected]8c756ac2009-01-30 23:36:41531 if (user_script_master_ || extensions_service_)
532 return; // Already initialized.
533
[email protected]bdbc87c2009-01-25 05:08:54534 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]f93fe782009-02-19 01:26:13535 PrefService* prefs = GetPrefs();
[email protected]bdbc87c2009-01-25 05:08:54536 bool user_scripts_enabled =
[email protected]f0a51fb52009-03-05 12:46:38537 command_line->HasSwitch(switches::kEnableUserScripts) ||
[email protected]f93fe782009-02-19 01:26:13538 prefs->GetBoolean(prefs::kEnableUserScripts);
[email protected]bdbc87c2009-01-25 05:08:54539
[email protected]f7011fcb2009-01-28 21:54:32540 FilePath script_dir;
[email protected]bdbc87c2009-01-25 05:08:54541 if (user_scripts_enabled) {
[email protected]0cd957b2009-03-06 20:13:23542 if (command_line->HasSwitch(switches::kUserScriptsDir)) {
543 std::wstring path_string =
544 command_line->GetSwitchValue(switches::kUserScriptsDir);
545 script_dir = FilePath::FromWStringHack(path_string);
546 } else {
547 script_dir = GetPath();
548 script_dir = script_dir.Append(chrome::kUserScriptsDirname);
549 }
[email protected]bdbc87c2009-01-25 05:08:54550 }
551
[email protected]bb28e062009-02-27 17:19:18552 ExtensionErrorReporter::Init(true); // allow noisy errors.
[email protected]bdbc87c2009-01-25 05:08:54553 user_script_master_ = new UserScriptMaster(
[email protected]9197f3b2009-06-02 00:49:27554 g_browser_process->file_thread()->message_loop(),
555 script_dir);
[email protected]894bb502009-05-21 22:39:57556 extensions_service_ = new ExtensionsService(
[email protected]a9b00ac2009-06-25 21:03:23557 this,
558 CommandLine::ForCurrentProcess(),
559 GetPrefs(),
560 GetPath().AppendASCII(ExtensionsService::kInstallDirectoryName),
561 MessageLoop::current(),
[email protected]93fd78f42009-07-10 16:43:17562 g_browser_process->file_thread()->message_loop(),
[email protected]b40cd872009-07-10 22:58:19563 false);
[email protected]bdbc87c2009-01-25 05:08:54564
[email protected]9197f3b2009-06-02 00:49:27565 extensions_service_->Init();
[email protected]919ddc82009-07-15 04:30:12566
567 // Load any extensions specified with --load-extension.
568 if (command_line->HasSwitch(switches::kLoadExtension)) {
569 std::wstring path_string =
570 command_line->GetSwitchValue(switches::kLoadExtension);
571 FilePath path = FilePath::FromWStringHack(path_string);
572 extensions_service_->LoadExtension(path);
573
574 // Tell UserScriptMaser to watch this extension's directory for changes so
575 // you can live edit content scripts during development.
576 user_script_master_->AddWatchedPath(path);
577 }
[email protected]bdbc87c2009-01-25 05:08:54578}
579
[email protected]ea0c98cf2009-06-18 23:02:54580void ProfileImpl::InitWebResources() {
[email protected]0c274c202009-07-12 02:59:07581 if (web_resource_service_)
582 return; // Already initialized.
583
[email protected]ea0c98cf2009-06-18 23:02:54584 web_resource_service_ = new WebResourceService(
585 this,
586 g_browser_process->file_thread()->message_loop());
587
588 web_resource_service_->StartAfterDelay();
589}
590
initial.commit09911bf2008-07-26 23:55:29591ProfileImpl::~ProfileImpl() {
[email protected]169627b2008-12-06 19:30:19592 tab_restore_service_ = NULL;
initial.commit09911bf2008-07-26 23:55:29593
594 StopCreateSessionServiceTimer();
595 // TemplateURLModel schedules a task on the WebDataService from its
596 // destructor. Delete it first to ensure the task gets scheduled before we
597 // shut down the database.
598 template_url_model_.reset();
599
600 // The download manager queries the history system and should be deleted
601 // before the history is shutdown so it can properly cancel all requests.
602 download_manager_ = NULL;
603
[email protected]4a190632009-05-09 01:07:42604 // The theme provider provides bitmaps to whoever wants them.
605 theme_provider_ = NULL;
606
[email protected]44961292009-07-20 20:03:09607 // The ThumbnailStore saves thumbnails used by the NTP. Call Shutdown to
608 // save any new thumbnails to disk and release its reference to the
609 // HistoryService.
610 if (thumbnail_store_.get())
611 thumbnail_store_->Shutdown();
612
[email protected]e7244d82008-10-29 18:13:26613 // Remove pref observers.
614 PrefService* prefs = GetPrefs();
615 prefs->RemovePrefObserver(prefs::kSpellCheckDictionary, this);
616 prefs->RemovePrefObserver(prefs::kEnableSpellCheck, this);
[email protected]154a4332009-06-03 20:20:58617 prefs->RemovePrefObserver(prefs::kEnableAutoSpellCorrect, this);
[email protected]e7244d82008-10-29 18:13:26618
[email protected]3a453fa2008-08-15 18:46:34619#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:07620 personalization_.reset();
[email protected]3a453fa2008-08-15 18:46:34621#endif
622
initial.commit09911bf2008-07-26 23:55:29623 // Both HistoryService and WebDataService maintain threads for background
624 // processing. Its possible each thread still has tasks on it that have
625 // increased the ref count of the service. In such a situation, when we
626 // decrement the refcount, it won't be 0, and the threads/databases aren't
627 // properly shut down. By explicitly calling Cleanup/Shutdown we ensure the
628 // databases are properly closed.
629 if (web_data_service_.get())
630 web_data_service_->Shutdown();
631
632 if (history_service_.get())
633 history_service_->Cleanup();
634
635 // The I/O thread may be NULL during testing.
[email protected]ab820df2008-08-26 05:55:10636 base::Thread* io_thread = g_browser_process->io_thread();
initial.commit09911bf2008-07-26 23:55:29637
638 if (spellchecker_) {
639 // The spellchecker must be deleted on the I/O thread. During testing, we
640 // don't have an I/O thread.
641 if (io_thread)
642 io_thread->message_loop()->ReleaseSoon(FROM_HERE, spellchecker_);
643 else
644 spellchecker_->Release();
645 }
646
[email protected]47accfd62009-05-14 18:46:21647 if (default_request_context_ == request_context_)
648 default_request_context_ = NULL;
[email protected]6ab9b202008-12-23 22:34:50649
[email protected]47accfd62009-05-14 18:46:21650 CleanupRequestContext(request_context_);
651 CleanupRequestContext(media_request_context_);
652 CleanupRequestContext(extensions_request_context_);
[email protected]1e744f22009-04-08 01:00:17653
[email protected]eaadd9052009-06-23 18:02:23654 // When the request contexts are gone, the blacklist wont be needed anymore.
655 delete blacklist_;
656 blacklist_ = 0;
657
[email protected]d8e41ed2008-09-11 15:22:32658 // HistoryService may call into the BookmarkModel, as such we need to
659 // delete HistoryService before the BookmarkModel. The destructor for
[email protected]90ef13132008-08-27 03:27:46660 // HistoryService will join with HistoryService's backend thread so that
661 // by the time the destructor has finished we're sure it will no longer call
[email protected]d8e41ed2008-09-11 15:22:32662 // into the BookmarkModel.
[email protected]90ef13132008-08-27 03:27:46663 history_service_ = NULL;
664 bookmark_bar_model_.reset();
665
initial.commit09911bf2008-07-26 23:55:29666 MarkAsCleanShutdown();
667}
668
[email protected]f7011fcb2009-01-28 21:54:32669FilePath ProfileImpl::GetPath() {
initial.commit09911bf2008-07-26 23:55:29670 return path_;
671}
672
673bool ProfileImpl::IsOffTheRecord() {
674 return false;
675}
676
677Profile* ProfileImpl::GetOffTheRecordProfile() {
678 if (!off_the_record_profile_.get()) {
679 scoped_ptr<OffTheRecordProfileImpl> p(new OffTheRecordProfileImpl(this));
680 off_the_record_profile_.swap(p);
681 }
682 return off_the_record_profile_.get();
683}
684
[email protected]860f55492009-03-27 19:50:59685void ProfileImpl::DestroyOffTheRecordProfile() {
686 off_the_record_profile_.reset();
687}
688
initial.commit09911bf2008-07-26 23:55:29689Profile* ProfileImpl::GetOriginalProfile() {
690 return this;
691}
692
initial.commit09911bf2008-07-26 23:55:29693VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() {
694 if (!visited_link_master_.get()) {
695 scoped_ptr<VisitedLinkMaster> visited_links(
696 new VisitedLinkMaster(g_browser_process->file_thread(),
[email protected]3e90d4a2009-07-03 17:38:39697 visited_link_event_listener_.get(), this));
initial.commit09911bf2008-07-26 23:55:29698 if (!visited_links->Init())
699 return NULL;
700 visited_link_master_.swap(visited_links);
701 }
702
703 return visited_link_master_.get();
704}
705
[email protected]6014d672008-12-05 00:38:25706ExtensionsService* ProfileImpl::GetExtensionsService() {
707 return extensions_service_.get();
708}
709
[email protected]0938d3c2009-01-09 20:37:35710UserScriptMaster* ProfileImpl::GetUserScriptMaster() {
[email protected]0938d3c2009-01-09 20:37:35711 return user_script_master_.get();
[email protected]04fba9a92008-10-28 17:25:25712}
713
[email protected]481e1a42009-05-06 20:56:05714ExtensionProcessManager* ProfileImpl::GetExtensionProcessManager() {
[email protected]382a0702009-06-26 17:12:27715 return extension_process_manager_.get();
[email protected]481e1a42009-05-06 20:56:05716}
717
[email protected]34cc84f2009-02-13 10:04:35718SSLHostState* ProfileImpl::GetSSLHostState() {
719 if (!ssl_host_state_.get())
720 ssl_host_state_.reset(new SSLHostState());
721
722 DCHECK(ssl_host_state_->CalledOnValidThread());
723 return ssl_host_state_.get();
724}
725
[email protected]a9cea7542009-05-20 04:30:23726net::ForceTLSState* ProfileImpl::GetForceTLSState() {
727 if (!force_tls_state_.get())
728 force_tls_state_.reset(new net::ForceTLSState());
729
730 return force_tls_state_.get();
731}
732
initial.commit09911bf2008-07-26 23:55:29733PrefService* ProfileImpl::GetPrefs() {
734 if (!prefs_.get()) {
[email protected]6faa0e0d2009-04-28 06:50:36735 prefs_.reset(new PrefService(GetPrefFilePath(),
736 g_browser_process->file_thread()));
initial.commit09911bf2008-07-26 23:55:29737
738 // The Profile class and ProfileManager class may read some prefs so
739 // register known prefs as soon as possible.
740 Profile::RegisterUserPrefs(prefs_.get());
741 ProfileManager::RegisterUserPrefs(prefs_.get());
742
743 // The last session exited cleanly if there is no pref for
744 // kSessionExitedCleanly or the value for kSessionExitedCleanly is true.
745 last_session_exited_cleanly_ =
746 prefs_->GetBoolean(prefs::kSessionExitedCleanly);
747 // Mark the session as open.
748 prefs_->SetBoolean(prefs::kSessionExitedCleanly, false);
749 // Make sure we save to disk that the session has opened.
[email protected]6faa0e0d2009-04-28 06:50:36750 prefs_->ScheduleSavePersistentPrefs();
initial.commit09911bf2008-07-26 23:55:29751 }
752
753 return prefs_.get();
754}
755
[email protected]f7011fcb2009-01-28 21:54:32756FilePath ProfileImpl::GetPrefFilePath() {
757 FilePath pref_file_path = path_;
758 pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename);
initial.commit09911bf2008-07-26 23:55:29759 return pref_file_path;
760}
761
762URLRequestContext* ProfileImpl::GetRequestContext() {
763 if (!request_context_) {
[email protected]f7011fcb2009-01-28 21:54:32764 FilePath cookie_path = GetPath();
765 cookie_path = cookie_path.Append(chrome::kCookieFilename);
766 FilePath cache_path = GetPath();
[email protected]e5642992009-06-26 23:06:31767 int max_size;
768 GetCacheParameters(kNormalContext, &cache_path, &max_size);
[email protected]2b2830a2009-02-07 01:58:42769
[email protected]f7011fcb2009-01-28 21:54:32770 cache_path = cache_path.Append(chrome::kCacheDirname);
[email protected]6ab9b202008-12-23 22:34:50771 request_context_ = ChromeURLRequestContext::CreateOriginal(
[email protected]e5642992009-06-26 23:06:31772 this, cookie_path, cache_path, max_size);
initial.commit09911bf2008-07-26 23:55:29773 request_context_->AddRef();
774
[email protected]6ab9b202008-12-23 22:34:50775 // The first request context is always a normal (non-OTR) request context.
776 // Even when Chromium is started in OTR mode, a normal profile is always
777 // created first.
778 if (!default_request_context_) {
779 default_request_context_ = request_context_;
780 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:56781 NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
[email protected]6ab9b202008-12-23 22:34:50782 NotificationService::AllSources(), NotificationService::NoDetails());
783 }
784
initial.commit09911bf2008-07-26 23:55:29785 DCHECK(request_context_->cookie_store());
786 }
787
788 return request_context_;
789}
790
[email protected]e7f29642009-03-02 22:53:18791URLRequestContext* ProfileImpl::GetRequestContextForMedia() {
792 if (!media_request_context_) {
793 FilePath cache_path = GetPath();
[email protected]e5642992009-06-26 23:06:31794 int max_size;
795 GetCacheParameters(kMediaContext, &cache_path, &max_size);
[email protected]e3edeba2009-03-23 18:57:14796
[email protected]4e7b5dbb2009-03-25 00:09:23797 cache_path = cache_path.Append(chrome::kMediaCacheDirname);
[email protected]e7f29642009-03-02 22:53:18798 media_request_context_ = ChromeURLRequestContext::CreateOriginalForMedia(
[email protected]e5642992009-06-26 23:06:31799 this, cache_path, max_size);
[email protected]e7f29642009-03-02 22:53:18800 media_request_context_->AddRef();
801
802 DCHECK(media_request_context_->cookie_store());
803 }
804
805 return media_request_context_;
806}
807
[email protected]47accfd62009-05-14 18:46:21808URLRequestContext* ProfileImpl::GetRequestContextForExtensions() {
809 if (!extensions_request_context_) {
810 FilePath cookie_path = GetPath();
811 cookie_path = cookie_path.Append(chrome::kExtensionsCookieFilename);
812
813 extensions_request_context_ =
814 ChromeURLRequestContext::CreateOriginalForExtensions(this, cookie_path);
815 extensions_request_context_->AddRef();
816
817 DCHECK(extensions_request_context_->cookie_store());
818 }
819
820 return extensions_request_context_;
821}
822
[email protected]eaadd9052009-06-23 18:02:23823Blacklist* ProfileImpl::GetBlacklist() {
824 return blacklist_;
825}
826
initial.commit09911bf2008-07-26 23:55:29827HistoryService* ProfileImpl::GetHistoryService(ServiceAccessType sat) {
828 if (!history_service_created_) {
[email protected]90ef13132008-08-27 03:27:46829 history_service_created_ = true;
initial.commit09911bf2008-07-26 23:55:29830 scoped_refptr<HistoryService> history(new HistoryService(this));
[email protected]d8e41ed2008-09-11 15:22:32831 if (!history->Init(GetPath(), GetBookmarkModel()))
initial.commit09911bf2008-07-26 23:55:29832 return NULL;
833 history_service_.swap(history);
initial.commit09911bf2008-07-26 23:55:29834
835 // Send out the notification that the history service was created.
836 NotificationService::current()->
[email protected]bfd04a62009-02-01 18:16:56837 Notify(NotificationType::HISTORY_CREATED, Source<Profile>(this),
initial.commit09911bf2008-07-26 23:55:29838 Details<HistoryService>(history_service_.get()));
839 }
840 return history_service_.get();
841}
842
initial.commit09911bf2008-07-26 23:55:29843TemplateURLModel* ProfileImpl::GetTemplateURLModel() {
844 if (!template_url_model_.get())
845 template_url_model_.reset(new TemplateURLModel(this));
846 return template_url_model_.get();
847}
848
849TemplateURLFetcher* ProfileImpl::GetTemplateURLFetcher() {
850 if (!template_url_fetcher_.get())
851 template_url_fetcher_.reset(new TemplateURLFetcher(this));
852 return template_url_fetcher_.get();
853}
854
855WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) {
856 if (!created_web_data_service_)
857 CreateWebDataService();
858 return web_data_service_.get();
859}
860
861void ProfileImpl::CreateWebDataService() {
862 DCHECK(!created_web_data_service_ && web_data_service_.get() == NULL);
863 created_web_data_service_ = true;
864 scoped_refptr<WebDataService> wds(new WebDataService());
865 if (!wds->Init(GetPath()))
866 return;
867 web_data_service_.swap(wds);
868}
869
[email protected]e69d33952009-06-03 22:00:41870PasswordStore* ProfileImpl::GetPasswordStore(ServiceAccessType sat) {
871 if (!created_password_store_)
872 CreatePasswordStore();
873 return password_store_.get();
874}
875
876void ProfileImpl::CreatePasswordStore() {
877 DCHECK(!created_password_store_ && password_store_.get() == NULL);
878 created_password_store_ = true;
879 scoped_refptr<PasswordStore> ps;
880#if defined(OS_LINUX)
881// Temporarily disabled while we figure some stuff out.
882// http://code.google.com/p/chromium/issues/detail?id=12351
883// if (getenv("KDE_FULL_SESSION")) {
884// ps = new PasswordStoreKWallet();
885// } else {
886// ps = new PasswordStoreGnome();
887// }
888 NOTIMPLEMENTED();
889#elif defined(OS_WIN)
890 ps = new PasswordStoreWin(GetWebDataService(Profile::IMPLICIT_ACCESS));
[email protected]034eba52009-06-03 22:50:56891#elif defined(OS_MACOSX)
[email protected]e0411ae52009-06-30 23:59:17892 FilePath login_db_file_path = GetPath();
893 login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName);
894 LoginDatabaseMac* login_db = new LoginDatabaseMac();
895 if (!login_db->Init(login_db_file_path)) {
896 LOG(ERROR) << "Could not initialize login database.";
897 delete login_db;
898 return;
899 }
900 ps = new PasswordStoreMac(new MacKeychain(), login_db);
[email protected]e69d33952009-06-03 22:00:41901#else
902 NOTIMPLEMENTED();
903#endif
904 if (!ps || !ps->Init()) {
905 // Try falling back to the default password manager
906 LOG(WARNING) << "Could not initialise native password manager - "
907 "falling back to default";
908 ps = new PasswordStoreDefault(GetWebDataService(Profile::IMPLICIT_ACCESS));
909 if (!ps->Init())
910 return;
911 }
912 password_store_.swap(ps);
913}
914
initial.commit09911bf2008-07-26 23:55:29915DownloadManager* ProfileImpl::GetDownloadManager() {
916 if (!created_download_manager_) {
917 scoped_refptr<DownloadManager> dlm(new DownloadManager);
918 dlm->Init(this);
919 created_download_manager_ = true;
920 download_manager_.swap(dlm);
921 }
922 return download_manager_.get();
923}
924
925bool ProfileImpl::HasCreatedDownloadManager() const {
926 return created_download_manager_;
927}
928
[email protected]4a190632009-05-09 01:07:42929void ProfileImpl::InitThemes() {
930 if (!created_theme_provider_) {
[email protected]0ef42ff92009-07-06 20:17:35931#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
[email protected]a5166af62009-07-03 00:42:29932 scoped_refptr<BrowserThemeProvider> themes(new GtkThemeProvider);
933#else
[email protected]4a190632009-05-09 01:07:42934 scoped_refptr<BrowserThemeProvider> themes(new BrowserThemeProvider);
[email protected]a5166af62009-07-03 00:42:29935#endif
[email protected]4a190632009-05-09 01:07:42936 themes->Init(this);
937 created_theme_provider_ = true;
938 theme_provider_.swap(themes);
939 }
940}
941
942void ProfileImpl::SetTheme(Extension* extension) {
943 InitThemes();
944 theme_provider_.get()->SetTheme(extension);
945}
946
[email protected]a5166af62009-07-03 00:42:29947void ProfileImpl::SetNativeTheme() {
948 InitThemes();
949 theme_provider_.get()->SetNativeTheme();
950}
951
[email protected]4a190632009-05-09 01:07:42952void ProfileImpl::ClearTheme() {
953 InitThemes();
954 theme_provider_.get()->UseDefaultTheme();
955}
956
957ThemeProvider* ProfileImpl::GetThemeProvider() {
958 InitThemes();
959 return theme_provider_.get();
960}
961
initial.commit09911bf2008-07-26 23:55:29962SessionService* ProfileImpl::GetSessionService() {
963 if (!session_service_.get() && !shutdown_session_service_) {
964 session_service_ = new SessionService(this);
965 session_service_->ResetFromCurrentBrowsers();
966 }
967 return session_service_.get();
968}
969
970void ProfileImpl::ShutdownSessionService() {
971 if (shutdown_session_service_)
972 return;
973
974 // We're about to exit, force creation of the session service if it hasn't
975 // been created yet. We do this to ensure session state matches the point in
976 // time the user exited.
977 GetSessionService();
978 shutdown_session_service_ = true;
979 session_service_ = NULL;
980}
981
982bool ProfileImpl::HasSessionService() const {
983 return (session_service_.get() != NULL);
984}
985
986std::wstring ProfileImpl::GetName() {
987 return GetPrefs()->GetString(prefs::kProfileName);
988}
989void ProfileImpl::SetName(const std::wstring& name) {
990 GetPrefs()->SetString(prefs::kProfileName, name);
991}
992
993std::wstring ProfileImpl::GetID() {
994 return GetPrefs()->GetString(prefs::kProfileID);
995}
996void ProfileImpl::SetID(const std::wstring& id) {
997 GetPrefs()->SetString(prefs::kProfileID, id);
998}
999
initial.commit09911bf2008-07-26 23:55:291000bool ProfileImpl::DidLastSessionExitCleanly() {
1001 // last_session_exited_cleanly_ is set when the preferences are loaded. Force
1002 // it to be set by asking for the prefs.
1003 GetPrefs();
1004 return last_session_exited_cleanly_;
1005}
1006
[email protected]d8e41ed2008-09-11 15:22:321007BookmarkModel* ProfileImpl::GetBookmarkModel() {
[email protected]90ef13132008-08-27 03:27:461008 if (!bookmark_bar_model_.get()) {
[email protected]d8e41ed2008-09-11 15:22:321009 bookmark_bar_model_.reset(new BookmarkModel(this));
[email protected]90ef13132008-08-27 03:27:461010 bookmark_bar_model_->Load();
1011 }
initial.commit09911bf2008-07-26 23:55:291012 return bookmark_bar_model_.get();
1013}
1014
1015bool ProfileImpl::IsSameProfile(Profile* profile) {
1016 if (profile == static_cast<Profile*>(this))
1017 return true;
1018 OffTheRecordProfileImpl* otr_profile = off_the_record_profile_.get();
1019 return otr_profile && profile == static_cast<Profile*>(otr_profile);
1020}
1021
1022Time ProfileImpl::GetStartTime() const {
1023 return start_time_;
1024}
1025
1026TabRestoreService* ProfileImpl::GetTabRestoreService() {
1027 if (!tab_restore_service_.get())
[email protected]169627b2008-12-06 19:30:191028 tab_restore_service_ = new TabRestoreService(this);
initial.commit09911bf2008-07-26 23:55:291029 return tab_restore_service_.get();
1030}
1031
[email protected]449478302009-06-09 20:04:281032ThumbnailStore* ProfileImpl::GetThumbnailStore() {
1033 if (!thumbnail_store_.get()) {
1034 thumbnail_store_ = new ThumbnailStore;
[email protected]72d0fc72009-07-09 17:30:491035 thumbnail_store_->Init(GetPath().AppendASCII("Top Thumbnails"), this);
[email protected]449478302009-06-09 20:04:281036 }
1037 return thumbnail_store_.get();
1038}
1039
initial.commit09911bf2008-07-26 23:55:291040void ProfileImpl::ResetTabRestoreService() {
[email protected]169627b2008-12-06 19:30:191041 tab_restore_service_ = NULL;
initial.commit09911bf2008-07-26 23:55:291042}
1043
[email protected]a9afddb2009-02-12 17:49:421044// To be run in the IO thread to notify all resource message filters that the
[email protected]20930852008-10-15 19:30:411045// spellchecker has changed.
1046class NotifySpellcheckerChangeTask : public Task {
1047 public:
1048 NotifySpellcheckerChangeTask(
[email protected]e7244d82008-10-29 18:13:261049 Profile* profile,
1050 const SpellcheckerReinitializedDetails& spellchecker)
[email protected]20930852008-10-15 19:30:411051 : profile_(profile),
1052 spellchecker_(spellchecker) {
1053 }
1054
1055 private:
1056 void Run(void) {
1057 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:561058 NotificationType::SPELLCHECKER_REINITIALIZED,
[email protected]20930852008-10-15 19:30:411059 Source<Profile>(profile_),
1060 Details<SpellcheckerReinitializedDetails>(&spellchecker_));
1061 }
1062
1063 Profile* profile_;
1064 SpellcheckerReinitializedDetails spellchecker_;
1065};
1066
[email protected]e7244d82008-10-29 18:13:261067void ProfileImpl::InitializeSpellChecker(bool need_to_broadcast) {
[email protected]20930852008-10-15 19:30:411068 // The I/O thread may be NULL during testing.
1069 base::Thread* io_thread = g_browser_process->io_thread();
1070 if (spellchecker_) {
1071 // The spellchecker must be deleted on the I/O thread.
1072 // A dummy variable to aid in logical clarity.
1073 SpellChecker* last_spellchecker = spellchecker_;
1074
1075 if (io_thread)
1076 io_thread->message_loop()->ReleaseSoon(FROM_HERE, last_spellchecker);
1077 else // during testing, we don't have an I/O thread
1078 last_spellchecker->Release();
[email protected]20930852008-10-15 19:30:411079 }
1080
[email protected]20930852008-10-15 19:30:411081 // Retrieve the (perhaps updated recently) dictionary name from preferences.
1082 PrefService* prefs = GetPrefs();
[email protected]e7244d82008-10-29 18:13:261083 bool enable_spellcheck = prefs->GetBoolean(prefs::kEnableSpellCheck);
[email protected]20930852008-10-15 19:30:411084
[email protected]e7244d82008-10-29 18:13:261085 if (enable_spellcheck) {
[email protected]bd17b702009-02-25 20:44:081086 FilePath dict_dir;
[email protected]e7244d82008-10-29 18:13:261087 PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir);
[email protected]a9afddb2009-02-12 17:49:421088 // Note that, as the object pointed to by previously by spellchecker_
[email protected]e7244d82008-10-29 18:13:261089 // is being deleted in the io thread, the spellchecker_ can be made to point
1090 // to a new object (RE-initialized) in parallel in this UI thread.
[email protected]4b4d1adc2008-12-10 22:28:581091 spellchecker_ = new SpellChecker(dict_dir,
[email protected]74c8b422009-03-11 00:34:121092 WideToASCII(prefs->GetString(prefs::kSpellCheckDictionary)),
1093 GetRequestContext(),
[email protected]bd17b702009-02-25 20:44:081094 FilePath());
[email protected]e7244d82008-10-29 18:13:261095 spellchecker_->AddRef(); // Manual refcounting.
1096 } else {
1097 spellchecker_ = NULL;
1098 }
[email protected]20930852008-10-15 19:30:411099
[email protected]154a4332009-06-03 20:20:581100 // Set auto spell correct status for spellchecker.
1101 if (spellchecker_) {
1102 spellchecker_->EnableAutoSpellCorrect(
1103 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
1104 }
1105
[email protected]20930852008-10-15 19:30:411106 if (need_to_broadcast && io_thread) { // Notify resource message filters.
1107 SpellcheckerReinitializedDetails scoped_spellchecker;
1108 scoped_spellchecker.spellchecker = spellchecker_;
[email protected]e7244d82008-10-29 18:13:261109 if (io_thread) {
1110 io_thread->message_loop()->PostTask(
[email protected]a9afddb2009-02-12 17:49:421111 FROM_HERE,
[email protected]e7244d82008-10-29 18:13:261112 new NotifySpellcheckerChangeTask(this, scoped_spellchecker));
1113 }
[email protected]20930852008-10-15 19:30:411114 }
1115}
1116
[email protected]e7244d82008-10-29 18:13:261117void ProfileImpl::ReinitializeSpellChecker() {
1118 InitializeSpellChecker(true);
1119}
1120
initial.commit09911bf2008-07-26 23:55:291121SpellChecker* ProfileImpl::GetSpellChecker() {
1122 if (!spellchecker_) {
[email protected]20930852008-10-15 19:30:411123 // This is where spellchecker gets initialized. Note that this is being
1124 // initialized in the ui_thread. However, this is not a problem as long as
1125 // it is *used* in the io thread.
[email protected]34cc84f2009-02-13 10:04:351126 // TODO(sidchat): One day, change everything so that spellchecker gets
[email protected]20930852008-10-15 19:30:411127 // initialized in the IO thread itself.
[email protected]e7244d82008-10-29 18:13:261128 InitializeSpellChecker(false);
initial.commit09911bf2008-07-26 23:55:291129 }
[email protected]20930852008-10-15 19:30:411130
initial.commit09911bf2008-07-26 23:55:291131 return spellchecker_;
1132}
1133
[email protected]3bf335a2009-06-26 20:46:061134WebKitContext* ProfileImpl::GetWebKitContext() {
1135 if (!webkit_context_.get())
1136 webkit_context_ = new WebKitContext(path_, false);
1137 DCHECK(webkit_context_.get());
1138 return webkit_context_.get();
1139}
1140
initial.commit09911bf2008-07-26 23:55:291141void ProfileImpl::MarkAsCleanShutdown() {
1142 if (prefs_.get()) {
1143 // The session cleanly exited, set kSessionExitedCleanly appropriately.
1144 prefs_->SetBoolean(prefs::kSessionExitedCleanly, true);
1145
1146 // NOTE: If you change what thread this writes on, be sure and update
1147 // ChromeFrame::EndSession().
[email protected]6faa0e0d2009-04-28 06:50:361148 prefs_->SavePersistentPrefs();
initial.commit09911bf2008-07-26 23:55:291149 }
1150}
1151
[email protected]e7244d82008-10-29 18:13:261152void ProfileImpl::Observe(NotificationType type,
1153 const NotificationSource& source,
1154 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:561155 if (NotificationType::PREF_CHANGED == type) {
[email protected]e7244d82008-10-29 18:13:261156 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
1157 PrefService* prefs = Source<PrefService>(source).ptr();
1158 DCHECK(pref_name_in && prefs);
1159 if (*pref_name_in == prefs::kSpellCheckDictionary ||
[email protected]154a4332009-06-03 20:20:581160 *pref_name_in == prefs::kEnableSpellCheck ||
1161 *pref_name_in == prefs::kEnableAutoSpellCorrect) {
[email protected]e7244d82008-10-29 18:13:261162 InitializeSpellChecker(true);
1163 }
[email protected]4a190632009-05-09 01:07:421164 } else if (NotificationType::THEME_INSTALLED == type) {
1165 Extension* extension = Details<Extension>(details).ptr();
1166 SetTheme(extension);
[email protected]e7244d82008-10-29 18:13:261167 }
1168}
1169
initial.commit09911bf2008-07-26 23:55:291170void ProfileImpl::StopCreateSessionServiceTimer() {
[email protected]2d316662008-09-03 18:18:141171 create_session_service_timer_.Stop();
initial.commit09911bf2008-07-26 23:55:291172}
[email protected]3a453fa2008-08-15 18:46:341173
1174#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:071175ProfilePersonalization* ProfileImpl::GetProfilePersonalization() {
[email protected]57d3d0a2008-09-24 00:50:071176 return personalization_.get();
[email protected]3a453fa2008-08-15 18:46:341177}
license.botbf09a502008-08-24 00:55:551178#endif