blob: 085f8146e3bd0108c53ebdb0cbc0f053f875c0a7 [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]1351b6a2009-04-09 20:13:22525#if defined(OS_LINUX)
526 // TODO(port): Remove ifdef when the Linux splash page is not needed.
527 prefs->transient()->SetString(prefs::kHomePage, "about:linux-splash");
528 prefs->transient()->SetBoolean(prefs::kHomePageIsNewTabPage, false);
529#endif
[email protected]4a190632009-05-09 01:07:42530
531 // Listen for theme installation.
[email protected]88cf3292009-05-22 01:48:43532 registrar_.Add(this, NotificationType::THEME_INSTALLED,
533 NotificationService::AllSources());
initial.commit09911bf2008-07-26 23:55:29534}
535
[email protected]bdbc87c2009-01-25 05:08:54536void ProfileImpl::InitExtensions() {
[email protected]8c756ac2009-01-30 23:36:41537 if (user_script_master_ || extensions_service_)
538 return; // Already initialized.
539
[email protected]bdbc87c2009-01-25 05:08:54540 const CommandLine* command_line = CommandLine::ForCurrentProcess();
[email protected]f93fe782009-02-19 01:26:13541 PrefService* prefs = GetPrefs();
[email protected]bdbc87c2009-01-25 05:08:54542 bool user_scripts_enabled =
[email protected]f0a51fb52009-03-05 12:46:38543 command_line->HasSwitch(switches::kEnableUserScripts) ||
[email protected]f93fe782009-02-19 01:26:13544 prefs->GetBoolean(prefs::kEnableUserScripts);
[email protected]bdbc87c2009-01-25 05:08:54545
[email protected]f7011fcb2009-01-28 21:54:32546 FilePath script_dir;
[email protected]bdbc87c2009-01-25 05:08:54547 if (user_scripts_enabled) {
[email protected]0cd957b2009-03-06 20:13:23548 if (command_line->HasSwitch(switches::kUserScriptsDir)) {
549 std::wstring path_string =
550 command_line->GetSwitchValue(switches::kUserScriptsDir);
551 script_dir = FilePath::FromWStringHack(path_string);
552 } else {
553 script_dir = GetPath();
554 script_dir = script_dir.Append(chrome::kUserScriptsDirname);
555 }
[email protected]bdbc87c2009-01-25 05:08:54556 }
557
[email protected]bb28e062009-02-27 17:19:18558 ExtensionErrorReporter::Init(true); // allow noisy errors.
[email protected]bdbc87c2009-01-25 05:08:54559 user_script_master_ = new UserScriptMaster(
[email protected]9197f3b2009-06-02 00:49:27560 g_browser_process->file_thread()->message_loop(),
561 script_dir);
[email protected]894bb502009-05-21 22:39:57562 extensions_service_ = new ExtensionsService(
[email protected]a9b00ac2009-06-25 21:03:23563 this,
564 CommandLine::ForCurrentProcess(),
565 GetPrefs(),
566 GetPath().AppendASCII(ExtensionsService::kInstallDirectoryName),
567 MessageLoop::current(),
[email protected]a1257b12009-06-12 02:51:34568 g_browser_process->file_thread()->message_loop());
[email protected]bdbc87c2009-01-25 05:08:54569
[email protected]9197f3b2009-06-02 00:49:27570 extensions_service_->Init();
[email protected]bdbc87c2009-01-25 05:08:54571}
572
[email protected]ea0c98cf2009-06-18 23:02:54573void ProfileImpl::InitWebResources() {
574 web_resource_service_ = new WebResourceService(
575 this,
576 g_browser_process->file_thread()->message_loop());
577
578 web_resource_service_->StartAfterDelay();
579}
580
initial.commit09911bf2008-07-26 23:55:29581ProfileImpl::~ProfileImpl() {
[email protected]169627b2008-12-06 19:30:19582 tab_restore_service_ = NULL;
initial.commit09911bf2008-07-26 23:55:29583
584 StopCreateSessionServiceTimer();
585 // TemplateURLModel schedules a task on the WebDataService from its
586 // destructor. Delete it first to ensure the task gets scheduled before we
587 // shut down the database.
588 template_url_model_.reset();
589
590 // The download manager queries the history system and should be deleted
591 // before the history is shutdown so it can properly cancel all requests.
592 download_manager_ = NULL;
593
[email protected]4a190632009-05-09 01:07:42594 // The theme provider provides bitmaps to whoever wants them.
595 theme_provider_ = NULL;
596
[email protected]e7244d82008-10-29 18:13:26597 // Remove pref observers.
598 PrefService* prefs = GetPrefs();
599 prefs->RemovePrefObserver(prefs::kSpellCheckDictionary, this);
600 prefs->RemovePrefObserver(prefs::kEnableSpellCheck, this);
[email protected]154a4332009-06-03 20:20:58601 prefs->RemovePrefObserver(prefs::kEnableAutoSpellCorrect, this);
[email protected]e7244d82008-10-29 18:13:26602
[email protected]3a453fa2008-08-15 18:46:34603#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:07604 personalization_.reset();
[email protected]3a453fa2008-08-15 18:46:34605#endif
606
initial.commit09911bf2008-07-26 23:55:29607 // Both HistoryService and WebDataService maintain threads for background
608 // processing. Its possible each thread still has tasks on it that have
609 // increased the ref count of the service. In such a situation, when we
610 // decrement the refcount, it won't be 0, and the threads/databases aren't
611 // properly shut down. By explicitly calling Cleanup/Shutdown we ensure the
612 // databases are properly closed.
613 if (web_data_service_.get())
614 web_data_service_->Shutdown();
615
616 if (history_service_.get())
617 history_service_->Cleanup();
618
619 // The I/O thread may be NULL during testing.
[email protected]ab820df2008-08-26 05:55:10620 base::Thread* io_thread = g_browser_process->io_thread();
initial.commit09911bf2008-07-26 23:55:29621
622 if (spellchecker_) {
623 // The spellchecker must be deleted on the I/O thread. During testing, we
624 // don't have an I/O thread.
625 if (io_thread)
626 io_thread->message_loop()->ReleaseSoon(FROM_HERE, spellchecker_);
627 else
628 spellchecker_->Release();
629 }
630
[email protected]47accfd62009-05-14 18:46:21631 if (default_request_context_ == request_context_)
632 default_request_context_ = NULL;
[email protected]6ab9b202008-12-23 22:34:50633
[email protected]47accfd62009-05-14 18:46:21634 CleanupRequestContext(request_context_);
635 CleanupRequestContext(media_request_context_);
636 CleanupRequestContext(extensions_request_context_);
[email protected]1e744f22009-04-08 01:00:17637
[email protected]eaadd9052009-06-23 18:02:23638 // When the request contexts are gone, the blacklist wont be needed anymore.
639 delete blacklist_;
640 blacklist_ = 0;
641
[email protected]d8e41ed2008-09-11 15:22:32642 // HistoryService may call into the BookmarkModel, as such we need to
643 // delete HistoryService before the BookmarkModel. The destructor for
[email protected]90ef13132008-08-27 03:27:46644 // HistoryService will join with HistoryService's backend thread so that
645 // by the time the destructor has finished we're sure it will no longer call
[email protected]d8e41ed2008-09-11 15:22:32646 // into the BookmarkModel.
[email protected]90ef13132008-08-27 03:27:46647 history_service_ = NULL;
648 bookmark_bar_model_.reset();
649
initial.commit09911bf2008-07-26 23:55:29650 MarkAsCleanShutdown();
651}
652
[email protected]f7011fcb2009-01-28 21:54:32653FilePath ProfileImpl::GetPath() {
initial.commit09911bf2008-07-26 23:55:29654 return path_;
655}
656
657bool ProfileImpl::IsOffTheRecord() {
658 return false;
659}
660
661Profile* ProfileImpl::GetOffTheRecordProfile() {
662 if (!off_the_record_profile_.get()) {
663 scoped_ptr<OffTheRecordProfileImpl> p(new OffTheRecordProfileImpl(this));
664 off_the_record_profile_.swap(p);
665 }
666 return off_the_record_profile_.get();
667}
668
[email protected]860f55492009-03-27 19:50:59669void ProfileImpl::DestroyOffTheRecordProfile() {
670 off_the_record_profile_.reset();
671}
672
initial.commit09911bf2008-07-26 23:55:29673Profile* ProfileImpl::GetOriginalProfile() {
674 return this;
675}
676
initial.commit09911bf2008-07-26 23:55:29677VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() {
678 if (!visited_link_master_.get()) {
679 scoped_ptr<VisitedLinkMaster> visited_links(
680 new VisitedLinkMaster(g_browser_process->file_thread(),
[email protected]3e90d4a2009-07-03 17:38:39681 visited_link_event_listener_.get(), this));
initial.commit09911bf2008-07-26 23:55:29682 if (!visited_links->Init())
683 return NULL;
684 visited_link_master_.swap(visited_links);
685 }
686
687 return visited_link_master_.get();
688}
689
[email protected]6014d672008-12-05 00:38:25690ExtensionsService* ProfileImpl::GetExtensionsService() {
691 return extensions_service_.get();
692}
693
[email protected]0938d3c2009-01-09 20:37:35694UserScriptMaster* ProfileImpl::GetUserScriptMaster() {
[email protected]0938d3c2009-01-09 20:37:35695 return user_script_master_.get();
[email protected]04fba9a92008-10-28 17:25:25696}
697
[email protected]481e1a42009-05-06 20:56:05698ExtensionProcessManager* ProfileImpl::GetExtensionProcessManager() {
[email protected]382a0702009-06-26 17:12:27699 return extension_process_manager_.get();
[email protected]481e1a42009-05-06 20:56:05700}
701
[email protected]34cc84f2009-02-13 10:04:35702SSLHostState* ProfileImpl::GetSSLHostState() {
703 if (!ssl_host_state_.get())
704 ssl_host_state_.reset(new SSLHostState());
705
706 DCHECK(ssl_host_state_->CalledOnValidThread());
707 return ssl_host_state_.get();
708}
709
[email protected]a9cea7542009-05-20 04:30:23710net::ForceTLSState* ProfileImpl::GetForceTLSState() {
711 if (!force_tls_state_.get())
712 force_tls_state_.reset(new net::ForceTLSState());
713
714 return force_tls_state_.get();
715}
716
initial.commit09911bf2008-07-26 23:55:29717PrefService* ProfileImpl::GetPrefs() {
718 if (!prefs_.get()) {
[email protected]6faa0e0d2009-04-28 06:50:36719 prefs_.reset(new PrefService(GetPrefFilePath(),
720 g_browser_process->file_thread()));
initial.commit09911bf2008-07-26 23:55:29721
722 // The Profile class and ProfileManager class may read some prefs so
723 // register known prefs as soon as possible.
724 Profile::RegisterUserPrefs(prefs_.get());
725 ProfileManager::RegisterUserPrefs(prefs_.get());
726
727 // The last session exited cleanly if there is no pref for
728 // kSessionExitedCleanly or the value for kSessionExitedCleanly is true.
729 last_session_exited_cleanly_ =
730 prefs_->GetBoolean(prefs::kSessionExitedCleanly);
731 // Mark the session as open.
732 prefs_->SetBoolean(prefs::kSessionExitedCleanly, false);
733 // Make sure we save to disk that the session has opened.
[email protected]6faa0e0d2009-04-28 06:50:36734 prefs_->ScheduleSavePersistentPrefs();
initial.commit09911bf2008-07-26 23:55:29735 }
736
737 return prefs_.get();
738}
739
[email protected]f7011fcb2009-01-28 21:54:32740FilePath ProfileImpl::GetPrefFilePath() {
741 FilePath pref_file_path = path_;
742 pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename);
initial.commit09911bf2008-07-26 23:55:29743 return pref_file_path;
744}
745
746URLRequestContext* ProfileImpl::GetRequestContext() {
747 if (!request_context_) {
[email protected]f7011fcb2009-01-28 21:54:32748 FilePath cookie_path = GetPath();
749 cookie_path = cookie_path.Append(chrome::kCookieFilename);
750 FilePath cache_path = GetPath();
[email protected]e5642992009-06-26 23:06:31751 int max_size;
752 GetCacheParameters(kNormalContext, &cache_path, &max_size);
[email protected]2b2830a2009-02-07 01:58:42753
[email protected]f7011fcb2009-01-28 21:54:32754 cache_path = cache_path.Append(chrome::kCacheDirname);
[email protected]6ab9b202008-12-23 22:34:50755 request_context_ = ChromeURLRequestContext::CreateOriginal(
[email protected]e5642992009-06-26 23:06:31756 this, cookie_path, cache_path, max_size);
initial.commit09911bf2008-07-26 23:55:29757 request_context_->AddRef();
758
[email protected]6ab9b202008-12-23 22:34:50759 // The first request context is always a normal (non-OTR) request context.
760 // Even when Chromium is started in OTR mode, a normal profile is always
761 // created first.
762 if (!default_request_context_) {
763 default_request_context_ = request_context_;
764 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:56765 NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
[email protected]6ab9b202008-12-23 22:34:50766 NotificationService::AllSources(), NotificationService::NoDetails());
767 }
768
initial.commit09911bf2008-07-26 23:55:29769 DCHECK(request_context_->cookie_store());
770 }
771
772 return request_context_;
773}
774
[email protected]e7f29642009-03-02 22:53:18775URLRequestContext* ProfileImpl::GetRequestContextForMedia() {
776 if (!media_request_context_) {
777 FilePath cache_path = GetPath();
[email protected]e5642992009-06-26 23:06:31778 int max_size;
779 GetCacheParameters(kMediaContext, &cache_path, &max_size);
[email protected]e3edeba2009-03-23 18:57:14780
[email protected]4e7b5dbb2009-03-25 00:09:23781 cache_path = cache_path.Append(chrome::kMediaCacheDirname);
[email protected]e7f29642009-03-02 22:53:18782 media_request_context_ = ChromeURLRequestContext::CreateOriginalForMedia(
[email protected]e5642992009-06-26 23:06:31783 this, cache_path, max_size);
[email protected]e7f29642009-03-02 22:53:18784 media_request_context_->AddRef();
785
786 DCHECK(media_request_context_->cookie_store());
787 }
788
789 return media_request_context_;
790}
791
[email protected]47accfd62009-05-14 18:46:21792URLRequestContext* ProfileImpl::GetRequestContextForExtensions() {
793 if (!extensions_request_context_) {
794 FilePath cookie_path = GetPath();
795 cookie_path = cookie_path.Append(chrome::kExtensionsCookieFilename);
796
797 extensions_request_context_ =
798 ChromeURLRequestContext::CreateOriginalForExtensions(this, cookie_path);
799 extensions_request_context_->AddRef();
800
801 DCHECK(extensions_request_context_->cookie_store());
802 }
803
804 return extensions_request_context_;
805}
806
[email protected]eaadd9052009-06-23 18:02:23807Blacklist* ProfileImpl::GetBlacklist() {
808 return blacklist_;
809}
810
initial.commit09911bf2008-07-26 23:55:29811HistoryService* ProfileImpl::GetHistoryService(ServiceAccessType sat) {
812 if (!history_service_created_) {
[email protected]90ef13132008-08-27 03:27:46813 history_service_created_ = true;
initial.commit09911bf2008-07-26 23:55:29814 scoped_refptr<HistoryService> history(new HistoryService(this));
[email protected]d8e41ed2008-09-11 15:22:32815 if (!history->Init(GetPath(), GetBookmarkModel()))
initial.commit09911bf2008-07-26 23:55:29816 return NULL;
817 history_service_.swap(history);
initial.commit09911bf2008-07-26 23:55:29818
819 // Send out the notification that the history service was created.
820 NotificationService::current()->
[email protected]bfd04a62009-02-01 18:16:56821 Notify(NotificationType::HISTORY_CREATED, Source<Profile>(this),
initial.commit09911bf2008-07-26 23:55:29822 Details<HistoryService>(history_service_.get()));
823 }
824 return history_service_.get();
825}
826
initial.commit09911bf2008-07-26 23:55:29827TemplateURLModel* ProfileImpl::GetTemplateURLModel() {
828 if (!template_url_model_.get())
829 template_url_model_.reset(new TemplateURLModel(this));
830 return template_url_model_.get();
831}
832
833TemplateURLFetcher* ProfileImpl::GetTemplateURLFetcher() {
834 if (!template_url_fetcher_.get())
835 template_url_fetcher_.reset(new TemplateURLFetcher(this));
836 return template_url_fetcher_.get();
837}
838
839WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) {
840 if (!created_web_data_service_)
841 CreateWebDataService();
842 return web_data_service_.get();
843}
844
845void ProfileImpl::CreateWebDataService() {
846 DCHECK(!created_web_data_service_ && web_data_service_.get() == NULL);
847 created_web_data_service_ = true;
848 scoped_refptr<WebDataService> wds(new WebDataService());
849 if (!wds->Init(GetPath()))
850 return;
851 web_data_service_.swap(wds);
852}
853
[email protected]e69d33952009-06-03 22:00:41854PasswordStore* ProfileImpl::GetPasswordStore(ServiceAccessType sat) {
855 if (!created_password_store_)
856 CreatePasswordStore();
857 return password_store_.get();
858}
859
860void ProfileImpl::CreatePasswordStore() {
861 DCHECK(!created_password_store_ && password_store_.get() == NULL);
862 created_password_store_ = true;
863 scoped_refptr<PasswordStore> ps;
864#if defined(OS_LINUX)
865// Temporarily disabled while we figure some stuff out.
866// http://code.google.com/p/chromium/issues/detail?id=12351
867// if (getenv("KDE_FULL_SESSION")) {
868// ps = new PasswordStoreKWallet();
869// } else {
870// ps = new PasswordStoreGnome();
871// }
872 NOTIMPLEMENTED();
873#elif defined(OS_WIN)
874 ps = new PasswordStoreWin(GetWebDataService(Profile::IMPLICIT_ACCESS));
[email protected]034eba52009-06-03 22:50:56875#elif defined(OS_MACOSX)
[email protected]e0411ae52009-06-30 23:59:17876 FilePath login_db_file_path = GetPath();
877 login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName);
878 LoginDatabaseMac* login_db = new LoginDatabaseMac();
879 if (!login_db->Init(login_db_file_path)) {
880 LOG(ERROR) << "Could not initialize login database.";
881 delete login_db;
882 return;
883 }
884 ps = new PasswordStoreMac(new MacKeychain(), login_db);
[email protected]e69d33952009-06-03 22:00:41885#else
886 NOTIMPLEMENTED();
887#endif
888 if (!ps || !ps->Init()) {
889 // Try falling back to the default password manager
890 LOG(WARNING) << "Could not initialise native password manager - "
891 "falling back to default";
892 ps = new PasswordStoreDefault(GetWebDataService(Profile::IMPLICIT_ACCESS));
893 if (!ps->Init())
894 return;
895 }
896 password_store_.swap(ps);
897}
898
initial.commit09911bf2008-07-26 23:55:29899DownloadManager* ProfileImpl::GetDownloadManager() {
900 if (!created_download_manager_) {
901 scoped_refptr<DownloadManager> dlm(new DownloadManager);
902 dlm->Init(this);
903 created_download_manager_ = true;
904 download_manager_.swap(dlm);
905 }
906 return download_manager_.get();
907}
908
909bool ProfileImpl::HasCreatedDownloadManager() const {
910 return created_download_manager_;
911}
912
[email protected]4a190632009-05-09 01:07:42913void ProfileImpl::InitThemes() {
914 if (!created_theme_provider_) {
[email protected]0ef42ff92009-07-06 20:17:35915#if defined(OS_LINUX) && !defined(TOOLKIT_VIEWS)
[email protected]a5166af62009-07-03 00:42:29916 scoped_refptr<BrowserThemeProvider> themes(new GtkThemeProvider);
917#else
[email protected]4a190632009-05-09 01:07:42918 scoped_refptr<BrowserThemeProvider> themes(new BrowserThemeProvider);
[email protected]a5166af62009-07-03 00:42:29919#endif
[email protected]4a190632009-05-09 01:07:42920 themes->Init(this);
921 created_theme_provider_ = true;
922 theme_provider_.swap(themes);
923 }
924}
925
926void ProfileImpl::SetTheme(Extension* extension) {
927 InitThemes();
928 theme_provider_.get()->SetTheme(extension);
929}
930
[email protected]a5166af62009-07-03 00:42:29931void ProfileImpl::SetNativeTheme() {
932 InitThemes();
933 theme_provider_.get()->SetNativeTheme();
934}
935
[email protected]4a190632009-05-09 01:07:42936void ProfileImpl::ClearTheme() {
937 InitThemes();
938 theme_provider_.get()->UseDefaultTheme();
939}
940
941ThemeProvider* ProfileImpl::GetThemeProvider() {
942 InitThemes();
943 return theme_provider_.get();
944}
945
initial.commit09911bf2008-07-26 23:55:29946SessionService* ProfileImpl::GetSessionService() {
947 if (!session_service_.get() && !shutdown_session_service_) {
948 session_service_ = new SessionService(this);
949 session_service_->ResetFromCurrentBrowsers();
950 }
951 return session_service_.get();
952}
953
954void ProfileImpl::ShutdownSessionService() {
955 if (shutdown_session_service_)
956 return;
957
958 // We're about to exit, force creation of the session service if it hasn't
959 // been created yet. We do this to ensure session state matches the point in
960 // time the user exited.
961 GetSessionService();
962 shutdown_session_service_ = true;
963 session_service_ = NULL;
964}
965
966bool ProfileImpl::HasSessionService() const {
967 return (session_service_.get() != NULL);
968}
969
970std::wstring ProfileImpl::GetName() {
971 return GetPrefs()->GetString(prefs::kProfileName);
972}
973void ProfileImpl::SetName(const std::wstring& name) {
974 GetPrefs()->SetString(prefs::kProfileName, name);
975}
976
977std::wstring ProfileImpl::GetID() {
978 return GetPrefs()->GetString(prefs::kProfileID);
979}
980void ProfileImpl::SetID(const std::wstring& id) {
981 GetPrefs()->SetString(prefs::kProfileID, id);
982}
983
initial.commit09911bf2008-07-26 23:55:29984bool ProfileImpl::DidLastSessionExitCleanly() {
985 // last_session_exited_cleanly_ is set when the preferences are loaded. Force
986 // it to be set by asking for the prefs.
987 GetPrefs();
988 return last_session_exited_cleanly_;
989}
990
[email protected]d8e41ed2008-09-11 15:22:32991BookmarkModel* ProfileImpl::GetBookmarkModel() {
[email protected]90ef13132008-08-27 03:27:46992 if (!bookmark_bar_model_.get()) {
[email protected]d8e41ed2008-09-11 15:22:32993 bookmark_bar_model_.reset(new BookmarkModel(this));
[email protected]90ef13132008-08-27 03:27:46994 bookmark_bar_model_->Load();
995 }
initial.commit09911bf2008-07-26 23:55:29996 return bookmark_bar_model_.get();
997}
998
999bool ProfileImpl::IsSameProfile(Profile* profile) {
1000 if (profile == static_cast<Profile*>(this))
1001 return true;
1002 OffTheRecordProfileImpl* otr_profile = off_the_record_profile_.get();
1003 return otr_profile && profile == static_cast<Profile*>(otr_profile);
1004}
1005
1006Time ProfileImpl::GetStartTime() const {
1007 return start_time_;
1008}
1009
1010TabRestoreService* ProfileImpl::GetTabRestoreService() {
1011 if (!tab_restore_service_.get())
[email protected]169627b2008-12-06 19:30:191012 tab_restore_service_ = new TabRestoreService(this);
initial.commit09911bf2008-07-26 23:55:291013 return tab_restore_service_.get();
1014}
1015
[email protected]449478302009-06-09 20:04:281016ThumbnailStore* ProfileImpl::GetThumbnailStore() {
1017 if (!thumbnail_store_.get()) {
1018 thumbnail_store_ = new ThumbnailStore;
[email protected]72d0fc72009-07-09 17:30:491019 thumbnail_store_->Init(GetPath().AppendASCII("Top Thumbnails"), this);
[email protected]449478302009-06-09 20:04:281020 }
1021 return thumbnail_store_.get();
1022}
1023
initial.commit09911bf2008-07-26 23:55:291024void ProfileImpl::ResetTabRestoreService() {
[email protected]169627b2008-12-06 19:30:191025 tab_restore_service_ = NULL;
initial.commit09911bf2008-07-26 23:55:291026}
1027
[email protected]a9afddb2009-02-12 17:49:421028// To be run in the IO thread to notify all resource message filters that the
[email protected]20930852008-10-15 19:30:411029// spellchecker has changed.
1030class NotifySpellcheckerChangeTask : public Task {
1031 public:
1032 NotifySpellcheckerChangeTask(
[email protected]e7244d82008-10-29 18:13:261033 Profile* profile,
1034 const SpellcheckerReinitializedDetails& spellchecker)
[email protected]20930852008-10-15 19:30:411035 : profile_(profile),
1036 spellchecker_(spellchecker) {
1037 }
1038
1039 private:
1040 void Run(void) {
1041 NotificationService::current()->Notify(
[email protected]bfd04a62009-02-01 18:16:561042 NotificationType::SPELLCHECKER_REINITIALIZED,
[email protected]20930852008-10-15 19:30:411043 Source<Profile>(profile_),
1044 Details<SpellcheckerReinitializedDetails>(&spellchecker_));
1045 }
1046
1047 Profile* profile_;
1048 SpellcheckerReinitializedDetails spellchecker_;
1049};
1050
[email protected]e7244d82008-10-29 18:13:261051void ProfileImpl::InitializeSpellChecker(bool need_to_broadcast) {
[email protected]20930852008-10-15 19:30:411052 // The I/O thread may be NULL during testing.
1053 base::Thread* io_thread = g_browser_process->io_thread();
1054 if (spellchecker_) {
1055 // The spellchecker must be deleted on the I/O thread.
1056 // A dummy variable to aid in logical clarity.
1057 SpellChecker* last_spellchecker = spellchecker_;
1058
1059 if (io_thread)
1060 io_thread->message_loop()->ReleaseSoon(FROM_HERE, last_spellchecker);
1061 else // during testing, we don't have an I/O thread
1062 last_spellchecker->Release();
[email protected]20930852008-10-15 19:30:411063 }
1064
[email protected]20930852008-10-15 19:30:411065 // Retrieve the (perhaps updated recently) dictionary name from preferences.
1066 PrefService* prefs = GetPrefs();
[email protected]e7244d82008-10-29 18:13:261067 bool enable_spellcheck = prefs->GetBoolean(prefs::kEnableSpellCheck);
[email protected]20930852008-10-15 19:30:411068
[email protected]e7244d82008-10-29 18:13:261069 if (enable_spellcheck) {
[email protected]bd17b702009-02-25 20:44:081070 FilePath dict_dir;
[email protected]e7244d82008-10-29 18:13:261071 PathService::Get(chrome::DIR_APP_DICTIONARIES, &dict_dir);
[email protected]a9afddb2009-02-12 17:49:421072 // Note that, as the object pointed to by previously by spellchecker_
[email protected]e7244d82008-10-29 18:13:261073 // is being deleted in the io thread, the spellchecker_ can be made to point
1074 // to a new object (RE-initialized) in parallel in this UI thread.
[email protected]4b4d1adc2008-12-10 22:28:581075 spellchecker_ = new SpellChecker(dict_dir,
[email protected]74c8b422009-03-11 00:34:121076 WideToASCII(prefs->GetString(prefs::kSpellCheckDictionary)),
1077 GetRequestContext(),
[email protected]bd17b702009-02-25 20:44:081078 FilePath());
[email protected]e7244d82008-10-29 18:13:261079 spellchecker_->AddRef(); // Manual refcounting.
1080 } else {
1081 spellchecker_ = NULL;
1082 }
[email protected]20930852008-10-15 19:30:411083
[email protected]154a4332009-06-03 20:20:581084 // Set auto spell correct status for spellchecker.
1085 if (spellchecker_) {
1086 spellchecker_->EnableAutoSpellCorrect(
1087 prefs->GetBoolean(prefs::kEnableAutoSpellCorrect));
1088 }
1089
[email protected]20930852008-10-15 19:30:411090 if (need_to_broadcast && io_thread) { // Notify resource message filters.
1091 SpellcheckerReinitializedDetails scoped_spellchecker;
1092 scoped_spellchecker.spellchecker = spellchecker_;
[email protected]e7244d82008-10-29 18:13:261093 if (io_thread) {
1094 io_thread->message_loop()->PostTask(
[email protected]a9afddb2009-02-12 17:49:421095 FROM_HERE,
[email protected]e7244d82008-10-29 18:13:261096 new NotifySpellcheckerChangeTask(this, scoped_spellchecker));
1097 }
[email protected]20930852008-10-15 19:30:411098 }
1099}
1100
[email protected]e7244d82008-10-29 18:13:261101void ProfileImpl::ReinitializeSpellChecker() {
1102 InitializeSpellChecker(true);
1103}
1104
initial.commit09911bf2008-07-26 23:55:291105SpellChecker* ProfileImpl::GetSpellChecker() {
1106 if (!spellchecker_) {
[email protected]20930852008-10-15 19:30:411107 // This is where spellchecker gets initialized. Note that this is being
1108 // initialized in the ui_thread. However, this is not a problem as long as
1109 // it is *used* in the io thread.
[email protected]34cc84f2009-02-13 10:04:351110 // TODO(sidchat): One day, change everything so that spellchecker gets
[email protected]20930852008-10-15 19:30:411111 // initialized in the IO thread itself.
[email protected]e7244d82008-10-29 18:13:261112 InitializeSpellChecker(false);
initial.commit09911bf2008-07-26 23:55:291113 }
[email protected]20930852008-10-15 19:30:411114
initial.commit09911bf2008-07-26 23:55:291115 return spellchecker_;
1116}
1117
[email protected]3bf335a2009-06-26 20:46:061118WebKitContext* ProfileImpl::GetWebKitContext() {
1119 if (!webkit_context_.get())
1120 webkit_context_ = new WebKitContext(path_, false);
1121 DCHECK(webkit_context_.get());
1122 return webkit_context_.get();
1123}
1124
initial.commit09911bf2008-07-26 23:55:291125void ProfileImpl::MarkAsCleanShutdown() {
1126 if (prefs_.get()) {
1127 // The session cleanly exited, set kSessionExitedCleanly appropriately.
1128 prefs_->SetBoolean(prefs::kSessionExitedCleanly, true);
1129
1130 // NOTE: If you change what thread this writes on, be sure and update
1131 // ChromeFrame::EndSession().
[email protected]6faa0e0d2009-04-28 06:50:361132 prefs_->SavePersistentPrefs();
initial.commit09911bf2008-07-26 23:55:291133 }
1134}
1135
[email protected]e7244d82008-10-29 18:13:261136void ProfileImpl::Observe(NotificationType type,
1137 const NotificationSource& source,
1138 const NotificationDetails& details) {
[email protected]bfd04a62009-02-01 18:16:561139 if (NotificationType::PREF_CHANGED == type) {
[email protected]e7244d82008-10-29 18:13:261140 std::wstring* pref_name_in = Details<std::wstring>(details).ptr();
1141 PrefService* prefs = Source<PrefService>(source).ptr();
1142 DCHECK(pref_name_in && prefs);
1143 if (*pref_name_in == prefs::kSpellCheckDictionary ||
[email protected]154a4332009-06-03 20:20:581144 *pref_name_in == prefs::kEnableSpellCheck ||
1145 *pref_name_in == prefs::kEnableAutoSpellCorrect) {
[email protected]e7244d82008-10-29 18:13:261146 InitializeSpellChecker(true);
1147 }
[email protected]4a190632009-05-09 01:07:421148 } else if (NotificationType::THEME_INSTALLED == type) {
1149 Extension* extension = Details<Extension>(details).ptr();
1150 SetTheme(extension);
[email protected]e7244d82008-10-29 18:13:261151 }
1152}
1153
initial.commit09911bf2008-07-26 23:55:291154void ProfileImpl::StopCreateSessionServiceTimer() {
[email protected]2d316662008-09-03 18:18:141155 create_session_service_timer_.Stop();
initial.commit09911bf2008-07-26 23:55:291156}
[email protected]3a453fa2008-08-15 18:46:341157
1158#ifdef CHROME_PERSONALIZATION
[email protected]57d3d0a2008-09-24 00:50:071159ProfilePersonalization* ProfileImpl::GetProfilePersonalization() {
[email protected]57d3d0a2008-09-24 00:50:071160 return personalization_.get();
[email protected]3a453fa2008-08-15 18:46:341161}
license.botbf09a502008-08-24 00:55:551162#endif