blob: 72bf157140444f85b944765afb4d2fcbac5b89f1 [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]e7244d82008-10-29 18:13:26607 // Remove pref observers.
608 PrefService* prefs = GetPrefs();
609 prefs->RemovePrefObserver(prefs::kSpellCheckDictionary, this);
610 prefs->RemovePrefObserver(prefs::kEnableSpellCheck, this);
[email protected]154a4332009-06-03 20:20:58611 prefs->RemovePrefObserver(prefs::kEnableAutoSpellCorrect, this);
[email protected]e7244d82008-10-29 18:13:26612
[email protected]3a453fa2008-08-15 18:46:34613#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:07614 personalization_.reset();
[email protected]3a453fa2008-08-15 18:46:34615#endif
616
initial.commit09911bf2008-07-26 23:55:29617 // Both HistoryService and WebDataService maintain threads for background
618 // processing. Its possible each thread still has tasks on it that have
619 // increased the ref count of the service. In such a situation, when we
620 // decrement the refcount, it won't be 0, and the threads/databases aren't
621 // properly shut down. By explicitly calling Cleanup/Shutdown we ensure the
622 // databases are properly closed.
623 if (web_data_service_.get())
624 web_data_service_->Shutdown();
625
626 if (history_service_.get())
627 history_service_->Cleanup();
628
629 // The I/O thread may be NULL during testing.
[email protected]ab820df2008-08-26 05:55:10630 base::Thread* io_thread = g_browser_process->io_thread();
initial.commit09911bf2008-07-26 23:55:29631
632 if (spellchecker_) {
633 // The spellchecker must be deleted on the I/O thread. During testing, we
634 // don't have an I/O thread.
635 if (io_thread)
636 io_thread->message_loop()->ReleaseSoon(FROM_HERE, spellchecker_);
637 else
638 spellchecker_->Release();
639 }
640
[email protected]47accfd62009-05-14 18:46:21641 if (default_request_context_ == request_context_)
642 default_request_context_ = NULL;
[email protected]6ab9b202008-12-23 22:34:50643
[email protected]47accfd62009-05-14 18:46:21644 CleanupRequestContext(request_context_);
645 CleanupRequestContext(media_request_context_);
646 CleanupRequestContext(extensions_request_context_);
[email protected]1e744f22009-04-08 01:00:17647
[email protected]eaadd9052009-06-23 18:02:23648 // When the request contexts are gone, the blacklist wont be needed anymore.
649 delete blacklist_;
650 blacklist_ = 0;
651
[email protected]d8e41ed2008-09-11 15:22:32652 // HistoryService may call into the BookmarkModel, as such we need to
653 // delete HistoryService before the BookmarkModel. The destructor for
[email protected]90ef13132008-08-27 03:27:46654 // HistoryService will join with HistoryService's backend thread so that
655 // by the time the destructor has finished we're sure it will no longer call
[email protected]d8e41ed2008-09-11 15:22:32656 // into the BookmarkModel.
[email protected]90ef13132008-08-27 03:27:46657 history_service_ = NULL;
658 bookmark_bar_model_.reset();
659
initial.commit09911bf2008-07-26 23:55:29660 MarkAsCleanShutdown();
661}
662
[email protected]f7011fcb2009-01-28 21:54:32663FilePath ProfileImpl::GetPath() {
initial.commit09911bf2008-07-26 23:55:29664 return path_;
665}
666
667bool ProfileImpl::IsOffTheRecord() {
668 return false;
669}
670
671Profile* ProfileImpl::GetOffTheRecordProfile() {
672 if (!off_the_record_profile_.get()) {
673 scoped_ptr<OffTheRecordProfileImpl> p(new OffTheRecordProfileImpl(this));
674 off_the_record_profile_.swap(p);
675 }
676 return off_the_record_profile_.get();
677}
678
[email protected]860f55492009-03-27 19:50:59679void ProfileImpl::DestroyOffTheRecordProfile() {
680 off_the_record_profile_.reset();
681}
682
initial.commit09911bf2008-07-26 23:55:29683Profile* ProfileImpl::GetOriginalProfile() {
684 return this;
685}
686
initial.commit09911bf2008-07-26 23:55:29687VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() {
688 if (!visited_link_master_.get()) {
689 scoped_ptr<VisitedLinkMaster> visited_links(
690 new VisitedLinkMaster(g_browser_process->file_thread(),
[email protected]3e90d4a2009-07-03 17:38:39691 visited_link_event_listener_.get(), this));
initial.commit09911bf2008-07-26 23:55:29692 if (!visited_links->Init())
693 return NULL;
694 visited_link_master_.swap(visited_links);
695 }
696
697 return visited_link_master_.get();
698}
699
[email protected]6014d672008-12-05 00:38:25700ExtensionsService* ProfileImpl::GetExtensionsService() {
701 return extensions_service_.get();
702}
703
[email protected]0938d3c2009-01-09 20:37:35704UserScriptMaster* ProfileImpl::GetUserScriptMaster() {
[email protected]0938d3c2009-01-09 20:37:35705 return user_script_master_.get();
[email protected]04fba9a92008-10-28 17:25:25706}
707
[email protected]481e1a42009-05-06 20:56:05708ExtensionProcessManager* ProfileImpl::GetExtensionProcessManager() {
[email protected]382a0702009-06-26 17:12:27709 return extension_process_manager_.get();
[email protected]481e1a42009-05-06 20:56:05710}
711
[email protected]34cc84f2009-02-13 10:04:35712SSLHostState* ProfileImpl::GetSSLHostState() {
713 if (!ssl_host_state_.get())
714 ssl_host_state_.reset(new SSLHostState());
715
716 DCHECK(ssl_host_state_->CalledOnValidThread());
717 return ssl_host_state_.get();
718}
719
[email protected]a9cea7542009-05-20 04:30:23720net::ForceTLSState* ProfileImpl::GetForceTLSState() {
721 if (!force_tls_state_.get())
722 force_tls_state_.reset(new net::ForceTLSState());
723
724 return force_tls_state_.get();
725}
726
initial.commit09911bf2008-07-26 23:55:29727PrefService* ProfileImpl::GetPrefs() {
728 if (!prefs_.get()) {
[email protected]6faa0e0d2009-04-28 06:50:36729 prefs_.reset(new PrefService(GetPrefFilePath(),
730 g_browser_process->file_thread()));
initial.commit09911bf2008-07-26 23:55:29731
732 // The Profile class and ProfileManager class may read some prefs so
733 // register known prefs as soon as possible.
734 Profile::RegisterUserPrefs(prefs_.get());
735 ProfileManager::RegisterUserPrefs(prefs_.get());
736
737 // The last session exited cleanly if there is no pref for
738 // kSessionExitedCleanly or the value for kSessionExitedCleanly is true.
739 last_session_exited_cleanly_ =
740 prefs_->GetBoolean(prefs::kSessionExitedCleanly);
741 // Mark the session as open.
742 prefs_->SetBoolean(prefs::kSessionExitedCleanly, false);
743 // Make sure we save to disk that the session has opened.
[email protected]6faa0e0d2009-04-28 06:50:36744 prefs_->ScheduleSavePersistentPrefs();
initial.commit09911bf2008-07-26 23:55:29745 }
746
747 return prefs_.get();
748}
749
[email protected]f7011fcb2009-01-28 21:54:32750FilePath ProfileImpl::GetPrefFilePath() {
751 FilePath pref_file_path = path_;
752 pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename);
initial.commit09911bf2008-07-26 23:55:29753 return pref_file_path;
754}
755
756URLRequestContext* ProfileImpl::GetRequestContext() {
757 if (!request_context_) {
[email protected]f7011fcb2009-01-28 21:54:32758 FilePath cookie_path = GetPath();
759 cookie_path = cookie_path.Append(chrome::kCookieFilename);
760 FilePath cache_path = GetPath();
[email protected]e5642992009-06-26 23:06:31761 int max_size;
762 GetCacheParameters(kNormalContext, &cache_path, &max_size);
[email protected]2b2830a2009-02-07 01:58:42763
[email protected]f7011fcb2009-01-28 21:54:32764 cache_path = cache_path.Append(chrome::kCacheDirname);
[email protected]6ab9b202008-12-23 22:34:50765 request_context_ = ChromeURLRequestContext::CreateOriginal(
[email protected]e5642992009-06-26 23:06:31766 this, cookie_path, cache_path, max_size);
initial.commit09911bf2008-07-26 23:55:29767 request_context_->AddRef();
768
[email protected]6ab9b202008-12-23 22:34:50769 // The first request context is always a normal (non-OTR) request context.
770 // Even when Chromium is started in OTR mode, a normal profile is always
771 // created first.
772 if (!default_request_context_) {
773 default_request_context_ = request_context_;
774 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:56775 NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
[email protected]6ab9b202008-12-23 22:34:50776 NotificationService::AllSources(), NotificationService::NoDetails());
777 }
778
initial.commit09911bf2008-07-26 23:55:29779 DCHECK(request_context_->cookie_store());
780 }
781
782 return request_context_;
783}
784
[email protected]e7f29642009-03-02 22:53:18785URLRequestContext* ProfileImpl::GetRequestContextForMedia() {
786 if (!media_request_context_) {
787 FilePath cache_path = GetPath();
[email protected]e5642992009-06-26 23:06:31788 int max_size;
789 GetCacheParameters(kMediaContext, &cache_path, &max_size);
[email protected]e3edeba2009-03-23 18:57:14790
[email protected]4e7b5dbb2009-03-25 00:09:23791 cache_path = cache_path.Append(chrome::kMediaCacheDirname);
[email protected]e7f29642009-03-02 22:53:18792 media_request_context_ = ChromeURLRequestContext::CreateOriginalForMedia(
[email protected]e5642992009-06-26 23:06:31793 this, cache_path, max_size);
[email protected]e7f29642009-03-02 22:53:18794 media_request_context_->AddRef();
795
796 DCHECK(media_request_context_->cookie_store());
797 }
798
799 return media_request_context_;
800}
801
[email protected]47accfd62009-05-14 18:46:21802URLRequestContext* ProfileImpl::GetRequestContextForExtensions() {
803 if (!extensions_request_context_) {
804 FilePath cookie_path = GetPath();
805 cookie_path = cookie_path.Append(chrome::kExtensionsCookieFilename);
806
807 extensions_request_context_ =
808 ChromeURLRequestContext::CreateOriginalForExtensions(this, cookie_path);
809 extensions_request_context_->AddRef();
810
811 DCHECK(extensions_request_context_->cookie_store());
812 }
813
814 return extensions_request_context_;
815}
816
[email protected]eaadd9052009-06-23 18:02:23817Blacklist* ProfileImpl::GetBlacklist() {
818 return blacklist_;
819}
820
initial.commit09911bf2008-07-26 23:55:29821HistoryService* ProfileImpl::GetHistoryService(ServiceAccessType sat) {
822 if (!history_service_created_) {
[email protected]90ef13132008-08-27 03:27:46823 history_service_created_ = true;
initial.commit09911bf2008-07-26 23:55:29824 scoped_refptr<HistoryService> history(new HistoryService(this));
[email protected]d8e41ed2008-09-11 15:22:32825 if (!history->Init(GetPath(), GetBookmarkModel()))
initial.commit09911bf2008-07-26 23:55:29826 return NULL;
827 history_service_.swap(history);
initial.commit09911bf2008-07-26 23:55:29828
829 // Send out the notification that the history service was created.
830 NotificationService::current()->
[email protected]bfd04a62009-02-01 18:16:56831 Notify(NotificationType::HISTORY_CREATED, Source<Profile>(this),
initial.commit09911bf2008-07-26 23:55:29832 Details<HistoryService>(history_service_.get()));
833 }
834 return history_service_.get();
835}
836
initial.commit09911bf2008-07-26 23:55:29837TemplateURLModel* ProfileImpl::GetTemplateURLModel() {
838 if (!template_url_model_.get())
839 template_url_model_.reset(new TemplateURLModel(this));
840 return template_url_model_.get();
841}
842
843TemplateURLFetcher* ProfileImpl::GetTemplateURLFetcher() {
844 if (!template_url_fetcher_.get())
845 template_url_fetcher_.reset(new TemplateURLFetcher(this));
846 return template_url_fetcher_.get();
847}
848
849WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) {
850 if (!created_web_data_service_)
851 CreateWebDataService();
852 return web_data_service_.get();
853}
854
855void ProfileImpl::CreateWebDataService() {
856 DCHECK(!created_web_data_service_ && web_data_service_.get() == NULL);
857 created_web_data_service_ = true;
858 scoped_refptr<WebDataService> wds(new WebDataService());
859 if (!wds->Init(GetPath()))
860 return;
861 web_data_service_.swap(wds);
862}
863
[email protected]e69d33952009-06-03 22:00:41864PasswordStore* ProfileImpl::GetPasswordStore(ServiceAccessType sat) {
865 if (!created_password_store_)
866 CreatePasswordStore();
867 return password_store_.get();
868}
869
870void ProfileImpl::CreatePasswordStore() {
871 DCHECK(!created_password_store_ && password_store_.get() == NULL);
872 created_password_store_ = true;
873 scoped_refptr<PasswordStore> ps;
874#if defined(OS_LINUX)
875// Temporarily disabled while we figure some stuff out.
876// http://code.google.com/p/chromium/issues/detail?id=12351
877// if (getenv("KDE_FULL_SESSION")) {
878// ps = new PasswordStoreKWallet();
879// } else {
880// ps = new PasswordStoreGnome();
881// }
882 NOTIMPLEMENTED();
883#elif defined(OS_WIN)
884 ps = new PasswordStoreWin(GetWebDataService(Profile::IMPLICIT_ACCESS));
[email protected]034eba52009-06-03 22:50:56885#elif defined(OS_MACOSX)
[email protected]e0411ae52009-06-30 23:59:17886 FilePath login_db_file_path = GetPath();
887 login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName);
888 LoginDatabaseMac* login_db = new LoginDatabaseMac();
889 if (!login_db->Init(login_db_file_path)) {
890 LOG(ERROR) << "Could not initialize login database.";
891 delete login_db;
892 return;
893 }
894 ps = new PasswordStoreMac(new MacKeychain(), login_db);
[email protected]e69d33952009-06-03 22:00:41895#else
896 NOTIMPLEMENTED();
897#endif
898 if (!ps || !ps->Init()) {
899 // Try falling back to the default password manager
900 LOG(WARNING) << "Could not initialise native password manager - "
901 "falling back to default";
902 ps = new PasswordStoreDefault(GetWebDataService(Profile::IMPLICIT_ACCESS));
903 if (!ps->Init())
904 return;
905 }
906 password_store_.swap(ps);
907}
908
initial.commit09911bf2008-07-26 23:55:29909DownloadManager* ProfileImpl::GetDownloadManager() {
910 if (!created_download_manager_) {
911 scoped_refptr<DownloadManager> dlm(new DownloadManager);
912 dlm->Init(this);
913 created_download_manager_ = true;
914 download_manager_.swap(dlm);
915 }
916 return download_manager_.get();
917}
918
919bool ProfileImpl::HasCreatedDownloadManager() const {
920 return created_download_manager_;
921}
922
[email protected]4a190632009-05-09 01:07:42923void ProfileImpl::InitThemes() {
924 if (!created_theme_provider_) {
[email protected]0ef42ff92009-07-06 20:17:35925#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
[email protected]a5166af62009-07-03 00:42:29926 scoped_refptr<BrowserThemeProvider> themes(new GtkThemeProvider);
927#else
[email protected]4a190632009-05-09 01:07:42928 scoped_refptr<BrowserThemeProvider> themes(new BrowserThemeProvider);
[email protected]a5166af62009-07-03 00:42:29929#endif
[email protected]4a190632009-05-09 01:07:42930 themes->Init(this);
931 created_theme_provider_ = true;
932 theme_provider_.swap(themes);
933 }
934}
935
936void ProfileImpl::SetTheme(Extension* extension) {
937 InitThemes();
938 theme_provider_.get()->SetTheme(extension);
939}
940
[email protected]a5166af62009-07-03 00:42:29941void ProfileImpl::SetNativeTheme() {
942 InitThemes();
943 theme_provider_.get()->SetNativeTheme();
944}
945
[email protected]4a190632009-05-09 01:07:42946void ProfileImpl::ClearTheme() {
947 InitThemes();
948 theme_provider_.get()->UseDefaultTheme();
949}
950
951ThemeProvider* ProfileImpl::GetThemeProvider() {
952 InitThemes();
953 return theme_provider_.get();
954}
955
initial.commit09911bf2008-07-26 23:55:29956SessionService* ProfileImpl::GetSessionService() {
957 if (!session_service_.get() && !shutdown_session_service_) {
958 session_service_ = new SessionService(this);
959 session_service_->ResetFromCurrentBrowsers();
960 }
961 return session_service_.get();
962}
963
964void ProfileImpl::ShutdownSessionService() {
965 if (shutdown_session_service_)
966 return;
967
968 // We're about to exit, force creation of the session service if it hasn't
969 // been created yet. We do this to ensure session state matches the point in
970 // time the user exited.
971 GetSessionService();
972 shutdown_session_service_ = true;
973 session_service_ = NULL;
974}
975
976bool ProfileImpl::HasSessionService() const {
977 return (session_service_.get() != NULL);
978}
979
980std::wstring ProfileImpl::GetName() {
981 return GetPrefs()->GetString(prefs::kProfileName);
982}
983void ProfileImpl::SetName(const std::wstring& name) {
984 GetPrefs()->SetString(prefs::kProfileName, name);
985}
986
987std::wstring ProfileImpl::GetID() {
988 return GetPrefs()->GetString(prefs::kProfileID);
989}
990void ProfileImpl::SetID(const std::wstring& id) {
991 GetPrefs()->SetString(prefs::kProfileID, id);
992}
993
initial.commit09911bf2008-07-26 23:55:29994bool ProfileImpl::DidLastSessionExitCleanly() {
995 // last_session_exited_cleanly_ is set when the preferences are loaded. Force
996 // it to be set by asking for the prefs.
997 GetPrefs();
998 return last_session_exited_cleanly_;
999}
1000
[email protected]d8e41ed2008-09-11 15:22:321001BookmarkModel* ProfileImpl::GetBookmarkModel() {
[email protected]90ef13132008-08-27 03:27:461002 if (!bookmark_bar_model_.get()) {
[email protected]d8e41ed2008-09-11 15:22:321003 bookmark_bar_model_.reset(new BookmarkModel(this));
[email protected]90ef13132008-08-27 03:27:461004 bookmark_bar_model_->Load();
1005 }
initial.commit09911bf2008-07-26 23:55:291006 return bookmark_bar_model_.get();
1007}
1008
1009bool ProfileImpl::IsSameProfile(Profile* profile) {
1010 if (profile == static_cast<Profile*>(this))
1011 return true;
1012 OffTheRecordProfileImpl* otr_profile = off_the_record_profile_.get();
1013 return otr_profile && profile == static_cast<Profile*>(otr_profile);
1014}
1015
1016Time ProfileImpl::GetStartTime() const {
1017 return start_time_;
1018}
1019
1020TabRestoreService* ProfileImpl::GetTabRestoreService() {
1021 if (!tab_restore_service_.get())
[email protected]169627b2008-12-06 19:30:191022 tab_restore_service_ = new TabRestoreService(this);
initial.commit09911bf2008-07-26 23:55:291023 return tab_restore_service_.get();
1024}
1025
[email protected]449478302009-06-09 20:04:281026ThumbnailStore* ProfileImpl::GetThumbnailStore() {
1027 if (!thumbnail_store_.get()) {
1028 thumbnail_store_ = new ThumbnailStore;
[email protected]72d0fc72009-07-09 17:30:491029 thumbnail_store_->Init(GetPath().AppendASCII("Top Thumbnails"), this);
[email protected]449478302009-06-09 20:04:281030 }
1031 return thumbnail_store_.get();
1032}
1033
initial.commit09911bf2008-07-26 23:55:291034void ProfileImpl::ResetTabRestoreService() {
[email protected]169627b2008-12-06 19:30:191035 tab_restore_service_ = NULL;
initial.commit09911bf2008-07-26 23:55:291036}
1037
[email protected]a9afddb2009-02-12 17:49:421038// To be run in the IO thread to notify all resource message filters that the
[email protected]20930852008-10-15 19:30:411039// spellchecker has changed.
1040class NotifySpellcheckerChangeTask : public Task {
1041 public:
1042 NotifySpellcheckerChangeTask(
[email protected]e7244d82008-10-29 18:13:261043 Profile* profile,
1044 const SpellcheckerReinitializedDetails& spellchecker)
[email protected]20930852008-10-15 19:30:411045 : profile_(profile),
1046 spellchecker_(spellchecker) {
1047 }
1048
1049 private:
1050 void Run(void) {
1051 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:561052 NotificationType::SPELLCHECKER_REINITIALIZED,
[email protected]20930852008-10-15 19:30:411053 Source<Profile>(profile_),
1054 Details<SpellcheckerReinitializedDetails>(&spellchecker_));
1055 }
1056
1057 Profile* profile_;
1058 SpellcheckerReinitializedDetails spellchecker_;
1059};
1060
[email protected]e7244d82008-10-29 18:13:261061void ProfileImpl::InitializeSpellChecker(bool need_to_broadcast) {
[email protected]20930852008-10-15 19:30:411062 // The I/O thread may be NULL during testing.
1063 base::Thread* io_thread = g_browser_process->io_thread();
1064 if (spellchecker_) {
1065 // The spellchecker must be deleted on the I/O thread.
1066 // A dummy variable to aid in logical clarity.
1067 SpellChecker* last_spellchecker = spellchecker_;
1068
1069 if (io_thread)
1070 io_thread->message_loop()->ReleaseSoon(FROM_HERE, last_spellchecker);
1071 else // during testing, we don't have an I/O thread
1072 last_spellchecker->Release();
[email protected]20930852008-10-15 19:30:411073 }
1074
[email protected]20930852008-10-15 19:30:411075 // Retrieve the (perhaps updated recently) dictionary name from preferences.
1076 PrefService* prefs = GetPrefs();
[email protected]e7244d82008-10-29 18:13:261077 bool enable_spellcheck = prefs->GetBoolean(prefs::kEnableSpellCheck);
[email protected]20930852008-10-15 19:30:411078
[email protected]e7244d82008-10-29 18:13:261079 if (enable_spellcheck) {
[email protected]bd17b702009-02-25 20:44:081080 FilePath dict_dir;
[email protected]e7244d82008-10-29 18:13:261081 PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir);
[email protected]a9afddb2009-02-12 17:49:421082 // Note that, as the object pointed to by previously by spellchecker_
[email protected]e7244d82008-10-29 18:13:261083 // is being deleted in the io thread, the spellchecker_ can be made to point
1084 // to a new object (RE-initialized) in parallel in this UI thread.
[email protected]4b4d1adc2008-12-10 22:28:581085 spellchecker_ = new SpellChecker(dict_dir,
[email protected]74c8b422009-03-11 00:34:121086 WideToASCII(prefs->GetString(prefs::kSpellCheckDictionary)),
1087 GetRequestContext(),
[email protected]bd17b702009-02-25 20:44:081088 FilePath());
[email protected]e7244d82008-10-29 18:13:261089 spellchecker_->AddRef(); // Manual refcounting.
1090 } else {
1091 spellchecker_ = NULL;
1092 }
[email protected]20930852008-10-15 19:30:411093
[email protected]154a4332009-06-03 20:20:581094 // Set auto spell correct status for spellchecker.
1095 if (spellchecker_) {
1096 spellchecker_->EnableAutoSpellCorrect(
1097 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
1098 }
1099
[email protected]20930852008-10-15 19:30:411100 if (need_to_broadcast && io_thread) { // Notify resource message filters.
1101 SpellcheckerReinitializedDetails scoped_spellchecker;
1102 scoped_spellchecker.spellchecker = spellchecker_;
[email protected]e7244d82008-10-29 18:13:261103 if (io_thread) {
1104 io_thread->message_loop()->PostTask(
[email protected]a9afddb2009-02-12 17:49:421105 FROM_HERE,
[email protected]e7244d82008-10-29 18:13:261106 new NotifySpellcheckerChangeTask(this, scoped_spellchecker));
1107 }
[email protected]20930852008-10-15 19:30:411108 }
1109}
1110
[email protected]e7244d82008-10-29 18:13:261111void ProfileImpl::ReinitializeSpellChecker() {
1112 InitializeSpellChecker(true);
1113}
1114
initial.commit09911bf2008-07-26 23:55:291115SpellChecker* ProfileImpl::GetSpellChecker() {
1116 if (!spellchecker_) {
[email protected]20930852008-10-15 19:30:411117 // This is where spellchecker gets initialized. Note that this is being
1118 // initialized in the ui_thread. However, this is not a problem as long as
1119 // it is *used* in the io thread.
[email protected]34cc84f2009-02-13 10:04:351120 // TODO(sidchat): One day, change everything so that spellchecker gets
[email protected]20930852008-10-15 19:30:411121 // initialized in the IO thread itself.
[email protected]e7244d82008-10-29 18:13:261122 InitializeSpellChecker(false);
initial.commit09911bf2008-07-26 23:55:291123 }
[email protected]20930852008-10-15 19:30:411124
initial.commit09911bf2008-07-26 23:55:291125 return spellchecker_;
1126}
1127
[email protected]3bf335a2009-06-26 20:46:061128WebKitContext* ProfileImpl::GetWebKitContext() {
1129 if (!webkit_context_.get())
1130 webkit_context_ = new WebKitContext(path_, false);
1131 DCHECK(webkit_context_.get());
1132 return webkit_context_.get();
1133}
1134
initial.commit09911bf2008-07-26 23:55:291135void ProfileImpl::MarkAsCleanShutdown() {
1136 if (prefs_.get()) {
1137 // The session cleanly exited, set kSessionExitedCleanly appropriately.
1138 prefs_->SetBoolean(prefs::kSessionExitedCleanly, true);
1139
1140 // NOTE: If you change what thread this writes on, be sure and update
1141 // ChromeFrame::EndSession().
[email protected]6faa0e0d2009-04-28 06:50:361142 prefs_->SavePersistentPrefs();
initial.commit09911bf2008-07-26 23:55:291143 }
1144}
1145
[email protected]e7244d82008-10-29 18:13:261146void ProfileImpl::Observe(NotificationType type,
1147 const NotificationSource& source,
1148 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:561149 if (NotificationType::PREF_CHANGED == type) {
[email protected]e7244d82008-10-29 18:13:261150 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
1151 PrefService* prefs = Source<PrefService>(source).ptr();
1152 DCHECK(pref_name_in && prefs);
1153 if (*pref_name_in == prefs::kSpellCheckDictionary ||
[email protected]154a4332009-06-03 20:20:581154 *pref_name_in == prefs::kEnableSpellCheck ||
1155 *pref_name_in == prefs::kEnableAutoSpellCorrect) {
[email protected]e7244d82008-10-29 18:13:261156 InitializeSpellChecker(true);
1157 }
[email protected]4a190632009-05-09 01:07:421158 } else if (NotificationType::THEME_INSTALLED == type) {
1159 Extension* extension = Details<Extension>(details).ptr();
1160 SetTheme(extension);
[email protected]e7244d82008-10-29 18:13:261161 }
1162}
1163
initial.commit09911bf2008-07-26 23:55:291164void ProfileImpl::StopCreateSessionServiceTimer() {
[email protected]2d316662008-09-03 18:18:141165 create_session_service_timer_.Stop();
initial.commit09911bf2008-07-26 23:55:291166}
[email protected]3a453fa2008-08-15 18:46:341167
1168#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:071169ProfilePersonalization* ProfileImpl::GetProfilePersonalization() {
[email protected]57d3d0a2008-09-24 00:50:071170 return personalization_.get();
[email protected]3a453fa2008-08-15 18:46:341171}
license.botbf09a502008-08-24 00:55:551172#endif