1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/profiles/profile_impl.h"
6
7 #include "base/command_line.h"
8 #include "base/compiler_specific.h"
9 #include "base/environment.h"
10 #include "base/file_path.h"
11 #include "base/file_util.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/metrics/histogram.h"
14 #include "base/path_service.h"
15 #include "base/string_number_conversions.h"
16 #include "base/string_util.h"
17 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
18 #include "chrome/browser/autofill/personal_data_manager.h"
19 #include "chrome/browser/background_contents_service_factory.h"
20 #include "chrome/browser/background_mode_manager_factory.h"
21 #include "chrome/browser/bookmarks/bookmark_model.h"
22 #include "chrome/browser/browser_process.h"
23 #include "chrome/browser/browser_signin.h"
24 #include "chrome/browser/content_settings/host_content_settings_map.h"
25 #include "chrome/browser/custom_handlers/protocol_handler_registry.h"
26 #include "chrome/browser/defaults.h"
27 #include "chrome/browser/download/download_manager.h"
28 #include "chrome/browser/extensions/extension_devtools_manager.h"
29 #include "chrome/browser/extensions/extension_error_reporter.h"
30 #include "chrome/browser/extensions/extension_event_router.h"
31 #include "chrome/browser/extensions/extension_info_map.h"
32 #include "chrome/browser/extensions/extension_message_service.h"
33 #include "chrome/browser/extensions/extension_pref_store.h"
34 #include "chrome/browser/extensions/extension_process_manager.h"
35 #include "chrome/browser/extensions/extension_service.h"
36 #include "chrome/browser/extensions/extension_special_storage_policy.h"
37 #include "chrome/browser/extensions/user_script_master.h"
38 #include "chrome/browser/favicon_service.h"
39 #include "chrome/browser/geolocation/geolocation_content_settings_map.h"
40 #include "chrome/browser/history/history.h"
41 #include "chrome/browser/history/top_sites.h"
42 #include "chrome/browser/instant/instant_controller.h"
43 #include "chrome/browser/metrics/user_metrics.h"
44 #include "chrome/browser/net/chrome_url_request_context.h"
45 #include "chrome/browser/net/gaia/token_service.h"
46 #include "chrome/browser/net/net_pref_observer.h"
47 #include "chrome/browser/net/pref_proxy_config_service.h"
48 #include "chrome/browser/net/ssl_config_service_manager.h"
49 #include "chrome/browser/password_manager/password_store_default.h"
50 #include "chrome/browser/policy/configuration_policy_pref_store.h"
51 #include "chrome/browser/policy/configuration_policy_provider.h"
52 #include "chrome/browser/policy/profile_policy_connector.h"
53 #include "chrome/browser/prefs/browser_prefs.h"
54 #include "chrome/browser/prefs/pref_value_store.h"
55 #include "chrome/browser/prerender/prerender_manager.h"
56 #include "chrome/browser/printing/cloud_print/cloud_print_proxy_service.h"
57 #include "chrome/browser/profiles/profile_dependency_manager.h"
58 #include "chrome/browser/profiles/profile_manager.h"
59 #include "chrome/browser/search_engines/template_url_fetcher.h"
60 #include "chrome/browser/search_engines/template_url_model.h"
61 #include "chrome/browser/sessions/session_service.h"
62 #include "chrome/browser/sessions/tab_restore_service.h"
63 #include "chrome/browser/spellcheck_host.h"
64 #include "chrome/browser/ssl/ssl_host_state.h"
65 #include "chrome/browser/status_icons/status_tray.h"
66 #include "chrome/browser/sync/profile_sync_factory_impl.h"
67 #include "chrome/browser/sync/profile_sync_service.h"
68 #include "chrome/browser/tabs/pinned_tab_service_factory.h"
69 #include "chrome/browser/transport_security_persister.h"
70 #include "chrome/browser/ui/browser_list.h"
71 #include "chrome/browser/ui/find_bar/find_bar_state.h"
72 #include "chrome/browser/ui/webui/chrome_url_data_manager.h"
73 #include "chrome/browser/ui/webui/extension_icon_source.h"
74 #include "chrome/browser/ui/webui/ntp_resource_cache.h"
75 #include "chrome/browser/user_style_sheet_watcher.h"
76 #include "chrome/browser/visitedlink/visitedlink_event_listener.h"
77 #include "chrome/browser/visitedlink/visitedlink_master.h"
78 #include "chrome/browser/web_resource/promo_resource_service.h"
79 #include "chrome/browser/webdata/web_data_service.h"
80 #include "chrome/common/chrome_constants.h"
81 #include "chrome/common/chrome_paths.h"
82 #include "chrome/common/chrome_paths_internal.h"
83 #include "chrome/common/chrome_switches.h"
84 #include "chrome/common/json_pref_store.h"
85 #include "chrome/common/pref_names.h"
86 #include "chrome/common/render_messages.h"
87 #include "content/browser/appcache/chrome_appcache_service.h"
88 #include "content/browser/browser_thread.h"
89 #include "content/browser/chrome_blob_storage_context.h"
90 #include "content/browser/file_system/browser_file_system_helper.h"
91 #include "content/browser/geolocation/geolocation_permission_context.h"
92 #include "content/browser/host_zoom_map.h"
93 #include "content/browser/in_process_webkit/webkit_context.h"
94 #include "content/browser/renderer_host/render_process_host.h"
95 #include "content/common/notification_service.h"
96 #include "grit/browser_resources.h"
97 #include "grit/locale_settings.h"
98 #include "net/base/transport_security_state.h"
99 #include "ui/base/resource/resource_bundle.h"
100 #include "webkit/database/database_tracker.h"
101
102 #if defined(OS_WIN)
103 #include "chrome/browser/instant/promo_counter.h"
104 #include "chrome/browser/password_manager/password_store_win.h"
105 #include "chrome/installer/util/install_util.h"
106 #elif defined(OS_MACOSX)
107 #include "chrome/browser/keychain_mac.h"
108 #include "chrome/browser/password_manager/password_store_mac.h"
109 #elif defined(OS_CHROMEOS)
110 #include "chrome/browser/chromeos/enterprise_extension_observer.h"
111 #elif defined(OS_POSIX) && !defined(OS_CHROMEOS)
112 #include "base/nix/xdg_util.h"
113 #if defined(USE_GNOME_KEYRING)
114 #include "chrome/browser/password_manager/native_backend_gnome_x.h"
115 #endif
116 #include "chrome/browser/password_manager/native_backend_kwallet_x.h"
117 #include "chrome/browser/password_manager/password_store_x.h"
118 #endif
119
120 #if defined(OS_CHROMEOS)
121 #include "chrome/browser/chromeos/locale_change_guard.h"
122 #include "chrome/browser/chromeos/login/user_manager.h"
123 #include "chrome/browser/chromeos/preferences.h"
124 #endif
125
126 using base::Time;
127 using base::TimeDelta;
128
129 namespace {
130
131 // Delay, in milliseconds, before we explicitly create the SessionService.
132 static const int kCreateSessionServiceDelayMS = 500;
133
134 enum ContextType {
135 kNormalContext,
136 kMediaContext
137 };
138
139 // Gets the cache parameters from the command line. |type| is the type of
140 // request context that we need, |cache_path| will be set to the user provided
141 // path, or will not be touched if there is not an argument. |max_size| will
142 // be the user provided value or zero by default.
GetCacheParameters(ContextType type,FilePath * cache_path,int * max_size)143 void GetCacheParameters(ContextType type, FilePath* cache_path,
144 int* max_size) {
145 DCHECK(cache_path);
146 DCHECK(max_size);
147
148 // Override the cache location if specified by the user.
149 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDiskCacheDir)) {
150 *cache_path = CommandLine::ForCurrentProcess()->GetSwitchValuePath(
151 switches::kDiskCacheDir);
152 }
153
154 const char* arg = kNormalContext == type ? switches::kDiskCacheSize :
155 switches::kMediaCacheSize;
156 std::string value =
157 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(arg);
158
159 // By default we let the cache determine the right size.
160 *max_size = 0;
161 if (!base::StringToInt(value, max_size)) {
162 *max_size = 0;
163 } else if (max_size < 0) {
164 *max_size = 0;
165 }
166 }
167
GetCachePath(const FilePath & base)168 FilePath GetCachePath(const FilePath& base) {
169 return base.Append(chrome::kCacheDirname);
170 }
171
GetMediaCachePath(const FilePath & base)172 FilePath GetMediaCachePath(const FilePath& base) {
173 return base.Append(chrome::kMediaCacheDirname);
174 }
175
176 // Simple task to log the size of the current profile.
177 class ProfileSizeTask : public Task {
178 public:
ProfileSizeTask(const FilePath & path)179 explicit ProfileSizeTask(const FilePath& path) : path_(path) {}
~ProfileSizeTask()180 virtual ~ProfileSizeTask() {}
181
182 virtual void Run();
183 private:
184 FilePath path_;
185 };
186
Run()187 void ProfileSizeTask::Run() {
188 int64 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("*"));
189 int size_MB = static_cast<int>(size / (1024 * 1024));
190 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalSize", size_MB);
191
192 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("History"));
193 size_MB = static_cast<int>(size / (1024 * 1024));
194 UMA_HISTOGRAM_COUNTS_10000("Profile.HistorySize", size_MB);
195
196 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("History*"));
197 size_MB = static_cast<int>(size / (1024 * 1024));
198 UMA_HISTOGRAM_COUNTS_10000("Profile.TotalHistorySize", size_MB);
199
200 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Cookies"));
201 size_MB = static_cast<int>(size / (1024 * 1024));
202 UMA_HISTOGRAM_COUNTS_10000("Profile.CookiesSize", size_MB);
203
204 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Bookmarks"));
205 size_MB = static_cast<int>(size / (1024 * 1024));
206 UMA_HISTOGRAM_COUNTS_10000("Profile.BookmarksSize", size_MB);
207
208 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Favicons"));
209 size_MB = static_cast<int>(size / (1024 * 1024));
210 UMA_HISTOGRAM_COUNTS_10000("Profile.FaviconsSize", size_MB);
211
212 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Top Sites"));
213 size_MB = static_cast<int>(size / (1024 * 1024));
214 UMA_HISTOGRAM_COUNTS_10000("Profile.TopSitesSize", size_MB);
215
216 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Visited Links"));
217 size_MB = static_cast<int>(size / (1024 * 1024));
218 UMA_HISTOGRAM_COUNTS_10000("Profile.VisitedLinksSize", size_MB);
219
220 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Web Data"));
221 size_MB = static_cast<int>(size / (1024 * 1024));
222 UMA_HISTOGRAM_COUNTS_10000("Profile.WebDataSize", size_MB);
223
224 size = file_util::ComputeFilesSize(path_, FILE_PATH_LITERAL("Extension*"));
225 size_MB = static_cast<int>(size / (1024 * 1024));
226 UMA_HISTOGRAM_COUNTS_10000("Profile.ExtensionSize", size_MB);
227 }
228
229 } // namespace
230
231 // static
CreateProfile(const FilePath & path)232 Profile* Profile::CreateProfile(const FilePath& path) {
233 if (!file_util::PathExists(path)) {
234 // TODO(tc): http://b/1094718 Bad things happen if we can't write to the
235 // profile directory. We should eventually be able to run in this
236 // situation.
237 if (!file_util::CreateDirectory(path))
238 return NULL;
239 }
240 return new ProfileImpl(path, NULL);
241 }
242
243 // static
CreateProfileAsync(const FilePath & path,Profile::Delegate * delegate)244 Profile* Profile::CreateProfileAsync(const FilePath&path,
245 Profile::Delegate* delegate) {
246 DCHECK(delegate);
247 // This is safe while all file opeartions are done on the FILE thread.
248 BrowserThread::PostTask(BrowserThread::FILE,
249 FROM_HERE,
250 NewRunnableFunction(&file_util::CreateDirectory,
251 path));
252 // Async version.
253 return new ProfileImpl(path, delegate);
254 }
255
256 // static
RegisterUserPrefs(PrefService * prefs)257 void ProfileImpl::RegisterUserPrefs(PrefService* prefs) {
258 prefs->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled, false);
259 prefs->RegisterBooleanPref(prefs::kClearSiteDataOnExit, false);
260 }
261
ProfileImpl(const FilePath & path,Profile::Delegate * delegate)262 ProfileImpl::ProfileImpl(const FilePath& path,
263 Profile::Delegate* delegate)
264 : path_(path),
265 visited_link_event_listener_(new VisitedLinkEventListener()),
266 extension_devtools_manager_(NULL),
267 ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)),
268 host_content_settings_map_(NULL),
269 host_zoom_map_(NULL),
270 history_service_created_(false),
271 favicon_service_created_(false),
272 created_web_data_service_(false),
273 created_password_store_(false),
274 created_download_manager_(false),
275 start_time_(Time::Now()),
276 spellcheck_host_(NULL),
277 spellcheck_host_ready_(false),
278 #if defined(OS_WIN)
279 checked_instant_promo_(false),
280 #endif
281 shutdown_session_service_(false),
282 delegate_(delegate) {
283 DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<
284 "profile files to the root directory!";
285 create_session_service_timer_.Start(
286 TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,
287 &ProfileImpl::EnsureSessionServiceCreated);
288
289 if (delegate_) {
290 prefs_.reset(PrefService::CreatePrefServiceAsync(
291 GetPrefFilePath(),
292 new ExtensionPrefStore(GetExtensionPrefValueMap(), false),
293 GetOriginalProfile(),
294 this)); // Ask to notify us in the end.
295 } else {
296 // Load prefs synchronously.
297 prefs_.reset(PrefService::CreatePrefService(
298 GetPrefFilePath(),
299 new ExtensionPrefStore(GetExtensionPrefValueMap(), false),
300 GetOriginalProfile()));
301 OnPrefsLoaded(prefs_.get(), true);
302 }
303 }
304
DoFinalInit()305 void ProfileImpl::DoFinalInit() {
306 PrefService* prefs = GetPrefs();
307 pref_change_registrar_.Init(prefs);
308 pref_change_registrar_.Add(prefs::kSpellCheckDictionary, this);
309 pref_change_registrar_.Add(prefs::kEnableSpellCheck, this);
310 pref_change_registrar_.Add(prefs::kEnableAutoSpellCorrect, this);
311 pref_change_registrar_.Add(prefs::kClearSiteDataOnExit, this);
312
313 // It would be nice to use PathService for fetching this directory, but
314 // the cache directory depends on the profile directory, which isn't available
315 // to PathService.
316 chrome::GetUserCacheDirectory(path_, &base_cache_path_);
317 if (!delegate_) {
318 file_util::CreateDirectory(base_cache_path_);
319 } else {
320 // Async profile loading is used, so call this on the FILE thread instead.
321 // It is safe since all other file operations should also be done there.
322 BrowserThread::PostTask(BrowserThread::FILE,
323 FROM_HERE,
324 NewRunnableFunction(&file_util::CreateDirectory,
325 base_cache_path_));
326 }
327
328 #if !defined(OS_CHROMEOS)
329 // Listen for bookmark model load, to bootstrap the sync service.
330 // On CrOS sync service will be initialized after sign in.
331 registrar_.Add(this, NotificationType::BOOKMARK_MODEL_LOADED,
332 Source<Profile>(this));
333 #endif
334
335 PrefService* local_state = g_browser_process->local_state();
336 ssl_config_service_manager_.reset(
337 SSLConfigServiceManager::CreateDefaultManager(GetPrefs(), local_state));
338
339 PinnedTabServiceFactory::GetForProfile(this);
340
341 // Initialize the BackgroundModeManager - this has to be done here before
342 // InitExtensions() is called because it relies on receiving notifications
343 // when extensions are loaded. BackgroundModeManager is not needed under
344 // ChromeOS because Chrome is always running (no need for special keep-alive
345 // or launch-on-startup support).
346 #if !defined(OS_CHROMEOS)
347 BackgroundModeManagerFactory::GetForProfile(this);
348 #endif
349
350 BackgroundContentsServiceFactory::GetForProfile(this);
351
352 extension_info_map_ = new ExtensionInfoMap();
353
354 InitRegisteredProtocolHandlers();
355
356 clear_local_state_on_exit_ = prefs->GetBoolean(prefs::kClearSiteDataOnExit);
357 if (clear_local_state_on_exit_) {
358 UserMetrics::RecordAction(
359 UserMetricsAction("ClearSiteDataOnExitEnabled"));
360 } else {
361 UserMetrics::RecordAction(
362 UserMetricsAction("ClearSiteDataOnExitDisabled"));
363 }
364
365 // Log the profile size after a reasonable startup delay.
366 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE,
367 new ProfileSizeTask(path_), 112000);
368
369 InstantController::RecordMetrics(this);
370
371 FilePath cookie_path = GetPath();
372 cookie_path = cookie_path.Append(chrome::kCookieFilename);
373 FilePath cache_path = base_cache_path_;
374 int cache_max_size;
375 GetCacheParameters(kNormalContext, &cache_path, &cache_max_size);
376 cache_path = GetCachePath(cache_path);
377
378 FilePath media_cache_path = base_cache_path_;
379 int media_cache_max_size;
380 GetCacheParameters(kMediaContext, &media_cache_path, &media_cache_max_size);
381 media_cache_path = GetMediaCachePath(media_cache_path);
382
383 FilePath extensions_cookie_path = GetPath();
384 extensions_cookie_path =
385 extensions_cookie_path.Append(chrome::kExtensionsCookieFilename);
386
387 FilePath app_path = GetPath().Append(chrome::kIsolatedAppStateDirname);
388
389 // Make sure we initialize the ProfileIOData after everything else has been
390 // initialized that we might be reading from the IO thread.
391 io_data_.Init(cookie_path, cache_path, cache_max_size,
392 media_cache_path, media_cache_max_size, extensions_cookie_path,
393 app_path);
394
395 // Initialize the ProfilePolicyConnector after |io_data_| since it requires
396 // the URLRequestContextGetter to be initialized.
397 GetPolicyConnector()->Initialize();
398
399 // Creation has been finished.
400 if (delegate_)
401 delegate_->OnProfileCreated(this, true);
402 }
403
InitExtensions(bool extensions_enabled)404 void ProfileImpl::InitExtensions(bool extensions_enabled) {
405 if (user_script_master_ || extensions_service_)
406 return; // Already initialized.
407
408 const CommandLine* command_line = CommandLine::ForCurrentProcess();
409 if (command_line->HasSwitch(
410 switches::kEnableExtensionTimelineApi)) {
411 extension_devtools_manager_ = new ExtensionDevToolsManager(this);
412 }
413
414 extension_process_manager_.reset(ExtensionProcessManager::Create(this));
415 extension_event_router_.reset(new ExtensionEventRouter(this));
416 extension_message_service_ = new ExtensionMessageService(this);
417
418 ExtensionErrorReporter::Init(true); // allow noisy errors.
419
420 FilePath script_dir; // Don't look for user scripts in any directory.
421 // TODO(aa): We should just remove this functionality,
422 // since it isn't used anymore.
423 user_script_master_ = new UserScriptMaster(script_dir, this);
424
425 bool autoupdate_enabled = true;
426 #if defined(OS_CHROMEOS)
427 if (!extensions_enabled)
428 autoupdate_enabled = false;
429 else
430 autoupdate_enabled = !command_line->HasSwitch(switches::kGuestSession);
431 #endif
432 extensions_service_ = new ExtensionService(
433 this,
434 CommandLine::ForCurrentProcess(),
435 GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),
436 extension_prefs_.get(),
437 autoupdate_enabled,
438 extensions_enabled);
439
440 RegisterComponentExtensions();
441 extensions_service_->Init();
442
443 if (extensions_enabled) {
444 // Load any extensions specified with --load-extension.
445 if (command_line->HasSwitch(switches::kLoadExtension)) {
446 FilePath path = command_line->GetSwitchValuePath(
447 switches::kLoadExtension);
448 extensions_service_->LoadExtension(path);
449 }
450 }
451
452 // Make the chrome://extension-icon/ resource available.
453 GetChromeURLDataManager()->AddDataSource(new ExtensionIconSource(this));
454 }
455
RegisterComponentExtensions()456 void ProfileImpl::RegisterComponentExtensions() {
457 // Register the component extensions.
458 //
459 // Component extension manifest must contain a 'key' property with a unique
460 // public key, serialized in base64. You can create a suitable value with the
461 // following commands on a unixy system:
462 //
463 // ssh-keygen -t rsa -b 1024 -N '' -f /tmp/key.pem
464 // openssl rsa -pubout -outform DER < /tmp/key.pem 2>/dev/null | base64 -w 0
465 typedef std::list<std::pair<FilePath::StringType, int> >
466 ComponentExtensionList;
467 ComponentExtensionList component_extensions;
468
469 // Bookmark manager.
470 component_extensions.push_back(std::make_pair(
471 FILE_PATH_LITERAL("bookmark_manager"),
472 IDR_BOOKMARKS_MANIFEST));
473
474 #if defined(FILE_MANAGER_EXTENSION)
475 #if defined(OS_CHROMEOS)
476 if (!CommandLine::ForCurrentProcess()->HasSwitch(
477 switches::kSkipChromeOSComponents)) {
478 #endif
479 component_extensions.push_back(std::make_pair(
480 FILE_PATH_LITERAL("file_manager"),
481 IDR_FILEMANAGER_MANIFEST));
482 #if defined(OS_CHROMEOS)
483 }
484 #endif
485 #endif
486
487 #if defined(TOUCH_UI)
488 component_extensions.push_back(std::make_pair(
489 FILE_PATH_LITERAL("keyboard"),
490 IDR_KEYBOARD_MANIFEST));
491 #endif
492
493 #if defined(OS_CHROMEOS)
494 if (!CommandLine::ForCurrentProcess()->HasSwitch(
495 switches::kSkipChromeOSComponents)) {
496 component_extensions.push_back(std::make_pair(
497 FILE_PATH_LITERAL("/usr/share/chromeos-assets/mobile"),
498 IDR_MOBILE_MANIFEST));
499
500 #if defined(OFFICIAL_BUILD)
501 if (browser_defaults::enable_help_app) {
502 component_extensions.push_back(std::make_pair(
503 FILE_PATH_LITERAL("/usr/share/chromeos-assets/helpapp"),
504 IDR_HELP_MANIFEST));
505 }
506 #endif
507 }
508 #endif
509
510 // Web Store.
511 component_extensions.push_back(std::make_pair(
512 FILE_PATH_LITERAL("web_store"),
513 IDR_WEBSTORE_MANIFEST));
514
515 for (ComponentExtensionList::iterator iter = component_extensions.begin();
516 iter != component_extensions.end(); ++iter) {
517 FilePath path(iter->first);
518 if (!path.IsAbsolute()) {
519 if (PathService::Get(chrome::DIR_RESOURCES, &path)) {
520 path = path.Append(iter->first);
521 } else {
522 NOTREACHED();
523 }
524 }
525
526 std::string manifest =
527 ResourceBundle::GetSharedInstance().GetRawDataResource(
528 iter->second).as_string();
529 extensions_service_->register_component_extension(
530 ExtensionService::ComponentExtensionInfo(manifest, path));
531 }
532
533 #if defined(OS_CHROMEOS)
534 // Register access extensions only if accessibility is enabled.
535 if (g_browser_process->local_state()->
536 GetBoolean(prefs::kAccessibilityEnabled)) {
537 FilePath path = FilePath(extension_misc::kAccessExtensionPath)
538 .AppendASCII("access_chromevox");
539 std::string manifest =
540 ResourceBundle::GetSharedInstance().GetRawDataResource(
541 IDR_CHROMEVOX_MANIFEST).as_string();
542 extensions_service_->register_component_extension(
543 ExtensionService::ComponentExtensionInfo(manifest, path));
544 }
545 #endif
546 }
547
InitPromoResources()548 void ProfileImpl::InitPromoResources() {
549 if (promo_resource_service_)
550 return;
551
552 promo_resource_service_ = new PromoResourceService(this);
553 promo_resource_service_->StartAfterDelay();
554 }
555
InitRegisteredProtocolHandlers()556 void ProfileImpl::InitRegisteredProtocolHandlers() {
557 if (protocol_handler_registry_)
558 return;
559 protocol_handler_registry_ = new ProtocolHandlerRegistry(this);
560 protocol_handler_registry_->Load();
561 }
562
GetNTPResourceCache()563 NTPResourceCache* ProfileImpl::GetNTPResourceCache() {
564 if (!ntp_resource_cache_.get())
565 ntp_resource_cache_.reset(new NTPResourceCache(this));
566 return ntp_resource_cache_.get();
567 }
568
last_selected_directory()569 FilePath ProfileImpl::last_selected_directory() {
570 return GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory);
571 }
572
set_last_selected_directory(const FilePath & path)573 void ProfileImpl::set_last_selected_directory(const FilePath& path) {
574 GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory, path);
575 }
576
~ProfileImpl()577 ProfileImpl::~ProfileImpl() {
578 NotificationService::current()->Notify(
579 NotificationType::PROFILE_DESTROYED,
580 Source<Profile>(this),
581 NotificationService::NoDetails());
582
583 GetPolicyConnector()->Shutdown();
584
585 ProfileDependencyManager::GetInstance()->DestroyProfileServices(this);
586
587 tab_restore_service_ = NULL;
588
589 StopCreateSessionServiceTimer();
590 // TemplateURLModel schedules a task on the WebDataService from its
591 // destructor. Delete it first to ensure the task gets scheduled before we
592 // shut down the database.
593 template_url_model_.reset();
594
595 // DownloadManager is lazily created, so check before accessing it.
596 if (download_manager_.get()) {
597 // The download manager queries the history system and should be shut down
598 // before the history is shut down so it can properly cancel all requests.
599 download_manager_->Shutdown();
600 download_manager_ = NULL;
601 }
602
603 // Remove pref observers
604 pref_change_registrar_.RemoveAll();
605
606 // Delete the NTP resource cache so we can unregister pref observers.
607 ntp_resource_cache_.reset();
608
609 // The sync service needs to be deleted before the services it calls.
610 sync_service_.reset();
611
612 // Password store uses WebDB, shut it down before the WebDB has been shutdown.
613 if (password_store_.get())
614 password_store_->Shutdown();
615
616 // Both HistoryService and WebDataService maintain threads for background
617 // processing. Its possible each thread still has tasks on it that have
618 // increased the ref count of the service. In such a situation, when we
619 // decrement the refcount, it won't be 0, and the threads/databases aren't
620 // properly shut down. By explicitly calling Cleanup/Shutdown we ensure the
621 // databases are properly closed.
622 if (web_data_service_.get())
623 web_data_service_->Shutdown();
624
625 if (top_sites_.get())
626 top_sites_->Shutdown();
627
628 if (history_service_.get())
629 history_service_->Cleanup();
630
631 if (spellcheck_host_.get())
632 spellcheck_host_->UnsetObserver();
633
634 if (io_data_.HasMainRequestContext() &&
635 default_request_context_ == GetRequestContext()) {
636 default_request_context_ = NULL;
637 }
638
639 // HistoryService may call into the BookmarkModel, as such we need to
640 // delete HistoryService before the BookmarkModel. The destructor for
641 // HistoryService will join with HistoryService's backend thread so that
642 // by the time the destructor has finished we're sure it will no longer call
643 // into the BookmarkModel.
644 history_service_ = NULL;
645 bookmark_bar_model_.reset();
646
647 // FaviconService depends on HistoryServce so make sure we delete
648 // HistoryService first.
649 favicon_service_ = NULL;
650
651 if (extension_message_service_)
652 extension_message_service_->DestroyingProfile();
653
654 if (extensions_service_)
655 extensions_service_->DestroyingProfile();
656
657 if (pref_proxy_config_tracker_)
658 pref_proxy_config_tracker_->DetachFromPrefService();
659
660 // This causes the Preferences file to be written to disk.
661 MarkAsCleanShutdown();
662 }
663
GetRuntimeId()664 ProfileId ProfileImpl::GetRuntimeId() {
665 return reinterpret_cast<ProfileId>(this);
666 }
667
GetPath()668 FilePath ProfileImpl::GetPath() {
669 return path_;
670 }
671
IsOffTheRecord()672 bool ProfileImpl::IsOffTheRecord() {
673 return false;
674 }
675
GetOffTheRecordProfile()676 Profile* ProfileImpl::GetOffTheRecordProfile() {
677 if (!off_the_record_profile_.get()) {
678 scoped_ptr<Profile> p(CreateOffTheRecordProfile());
679 off_the_record_profile_.swap(p);
680
681 NotificationService::current()->Notify(
682 NotificationType::OTR_PROFILE_CREATED,
683 Source<Profile>(off_the_record_profile_.get()),
684 NotificationService::NoDetails());
685 }
686 return off_the_record_profile_.get();
687 }
688
DestroyOffTheRecordProfile()689 void ProfileImpl::DestroyOffTheRecordProfile() {
690 off_the_record_profile_.reset();
691 }
692
HasOffTheRecordProfile()693 bool ProfileImpl::HasOffTheRecordProfile() {
694 return off_the_record_profile_.get() != NULL;
695 }
696
GetOriginalProfile()697 Profile* ProfileImpl::GetOriginalProfile() {
698 return this;
699 }
700
GetAppCacheService()701 ChromeAppCacheService* ProfileImpl::GetAppCacheService() {
702 if (!appcache_service_) {
703 appcache_service_ = new ChromeAppCacheService;
704 BrowserThread::PostTask(
705 BrowserThread::IO, FROM_HERE,
706 NewRunnableMethod(
707 appcache_service_.get(),
708 &ChromeAppCacheService::InitializeOnIOThread,
709 IsOffTheRecord()
710 ? FilePath() : GetPath().Append(chrome::kAppCacheDirname),
711 make_scoped_refptr(GetHostContentSettingsMap()),
712 make_scoped_refptr(GetExtensionSpecialStoragePolicy()),
713 clear_local_state_on_exit_));
714 }
715 return appcache_service_;
716 }
717
GetDatabaseTracker()718 webkit_database::DatabaseTracker* ProfileImpl::GetDatabaseTracker() {
719 if (!db_tracker_) {
720 db_tracker_ = new webkit_database::DatabaseTracker(
721 GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
722 }
723 return db_tracker_;
724 }
725
GetVisitedLinkMaster()726 VisitedLinkMaster* ProfileImpl::GetVisitedLinkMaster() {
727 if (!visited_link_master_.get()) {
728 scoped_ptr<VisitedLinkMaster> visited_links(
729 new VisitedLinkMaster(visited_link_event_listener_.get(), this));
730 if (!visited_links->Init())
731 return NULL;
732 visited_link_master_.swap(visited_links);
733 }
734
735 return visited_link_master_.get();
736 }
737
GetExtensionService()738 ExtensionService* ProfileImpl::GetExtensionService() {
739 return extensions_service_.get();
740 }
741
GetStatusTray()742 StatusTray* ProfileImpl::GetStatusTray() {
743 if (!status_tray_.get())
744 status_tray_.reset(StatusTray::Create());
745 return status_tray_.get();
746 }
747
GetUserScriptMaster()748 UserScriptMaster* ProfileImpl::GetUserScriptMaster() {
749 return user_script_master_.get();
750 }
751
GetExtensionDevToolsManager()752 ExtensionDevToolsManager* ProfileImpl::GetExtensionDevToolsManager() {
753 return extension_devtools_manager_.get();
754 }
755
GetExtensionProcessManager()756 ExtensionProcessManager* ProfileImpl::GetExtensionProcessManager() {
757 return extension_process_manager_.get();
758 }
759
GetExtensionMessageService()760 ExtensionMessageService* ProfileImpl::GetExtensionMessageService() {
761 return extension_message_service_.get();
762 }
763
GetExtensionEventRouter()764 ExtensionEventRouter* ProfileImpl::GetExtensionEventRouter() {
765 return extension_event_router_.get();
766 }
767
768 ExtensionSpecialStoragePolicy*
GetExtensionSpecialStoragePolicy()769 ProfileImpl::GetExtensionSpecialStoragePolicy() {
770 if (!extension_special_storage_policy_.get())
771 extension_special_storage_policy_ = new ExtensionSpecialStoragePolicy();
772 return extension_special_storage_policy_.get();
773 }
774
GetSSLHostState()775 SSLHostState* ProfileImpl::GetSSLHostState() {
776 if (!ssl_host_state_.get())
777 ssl_host_state_.reset(new SSLHostState());
778
779 DCHECK(ssl_host_state_->CalledOnValidThread());
780 return ssl_host_state_.get();
781 }
782
783 net::TransportSecurityState*
GetTransportSecurityState()784 ProfileImpl::GetTransportSecurityState() {
785 if (!transport_security_state_.get()) {
786 transport_security_state_ = new net::TransportSecurityState();
787 transport_security_persister_ =
788 new TransportSecurityPersister(false /* read-write */);
789 transport_security_persister_->Initialize(
790 transport_security_state_.get(), path_);
791 }
792
793 return transport_security_state_.get();
794 }
795
OnPrefsLoaded(PrefService * prefs,bool success)796 void ProfileImpl::OnPrefsLoaded(PrefService* prefs, bool success) {
797 DCHECK(prefs == prefs_.get());
798
799 if (!success) {
800 DCHECK(delegate_);
801 delegate_->OnProfileCreated(this, false);
802 return;
803 }
804
805 // The Profile class and ProfileManager class may read some prefs so
806 // register known prefs as soon as possible.
807 Profile::RegisterUserPrefs(prefs_.get());
808 browser::RegisterUserPrefs(prefs_.get());
809 // TODO(mirandac): remove migration code after 6 months (crbug.com/69995).
810 if (g_browser_process->local_state()) {
811 browser::MigrateBrowserPrefs(prefs_.get(),
812 g_browser_process->local_state());
813 }
814
815 // The last session exited cleanly if there is no pref for
816 // kSessionExitedCleanly or the value for kSessionExitedCleanly is true.
817 last_session_exited_cleanly_ =
818 prefs_->GetBoolean(prefs::kSessionExitedCleanly);
819 // Mark the session as open.
820 prefs_->SetBoolean(prefs::kSessionExitedCleanly, false);
821 // Make sure we save to disk that the session has opened.
822 prefs_->ScheduleSavePersistentPrefs();
823
824 // Ensure that preferences set by extensions are restored in the profile
825 // as early as possible. The constructor takes care of that.
826 extension_prefs_.reset(new ExtensionPrefs(
827 prefs_.get(),
828 GetPath().AppendASCII(ExtensionService::kInstallDirectoryName),
829 GetExtensionPrefValueMap()));
830
831 DCHECK(!net_pref_observer_.get());
832 net_pref_observer_.reset(
833 new NetPrefObserver(prefs_.get(), GetPrerenderManager()));
834
835 DoFinalInit();
836 }
837
GetPrefs()838 PrefService* ProfileImpl::GetPrefs() {
839 DCHECK(prefs_.get()); // Should explicitly be initialized.
840 return prefs_.get();
841 }
842
GetOffTheRecordPrefs()843 PrefService* ProfileImpl::GetOffTheRecordPrefs() {
844 if (!otr_prefs_.get()) {
845 // The new ExtensionPrefStore is ref_counted and the new PrefService
846 // stores a reference so that we do not leak memory here.
847 otr_prefs_.reset(GetPrefs()->CreateIncognitoPrefService(
848 new ExtensionPrefStore(GetExtensionPrefValueMap(), true)));
849 }
850 return otr_prefs_.get();
851 }
852
GetPrefFilePath()853 FilePath ProfileImpl::GetPrefFilePath() {
854 FilePath pref_file_path = path_;
855 pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename);
856 return pref_file_path;
857 }
858
GetRequestContext()859 net::URLRequestContextGetter* ProfileImpl::GetRequestContext() {
860 net::URLRequestContextGetter* request_context =
861 io_data_.GetMainRequestContextGetter();
862 // The first request context is always a normal (non-OTR) request context.
863 // Even when Chromium is started in OTR mode, a normal profile is always
864 // created first.
865 if (!default_request_context_) {
866 default_request_context_ = request_context;
867 request_context->set_is_main(true);
868 // TODO(eroman): this isn't terribly useful anymore now that the
869 // net::URLRequestContext is constructed by the IO thread...
870 NotificationService::current()->Notify(
871 NotificationType::DEFAULT_REQUEST_CONTEXT_AVAILABLE,
872 NotificationService::AllSources(), NotificationService::NoDetails());
873 }
874
875 return request_context;
876 }
877
GetRequestContextForPossibleApp(const Extension * installed_app)878 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForPossibleApp(
879 const Extension* installed_app) {
880 if (CommandLine::ForCurrentProcess()->HasSwitch(
881 switches::kEnableExperimentalAppManifests) &&
882 installed_app != NULL &&
883 installed_app->is_storage_isolated())
884 return GetRequestContextForIsolatedApp(installed_app->id());
885
886 return GetRequestContext();
887 }
888
GetRequestContextForMedia()889 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForMedia() {
890 return io_data_.GetMediaRequestContextGetter();
891 }
892
GetResourceContext()893 const content::ResourceContext& ProfileImpl::GetResourceContext() {
894 return io_data_.GetResourceContext();
895 }
896
GetFaviconService(ServiceAccessType sat)897 FaviconService* ProfileImpl::GetFaviconService(ServiceAccessType sat) {
898 if (!favicon_service_created_) {
899 favicon_service_created_ = true;
900 scoped_refptr<FaviconService> service(new FaviconService(this));
901 favicon_service_.swap(service);
902 }
903 return favicon_service_.get();
904 }
905
GetRequestContextForExtensions()906 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() {
907 return io_data_.GetExtensionsRequestContextGetter();
908 }
909
GetRequestContextForIsolatedApp(const std::string & app_id)910 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForIsolatedApp(
911 const std::string& app_id) {
912 return io_data_.GetIsolatedAppRequestContextGetter(app_id);
913 }
914
RegisterExtensionWithRequestContexts(const Extension * extension)915 void ProfileImpl::RegisterExtensionWithRequestContexts(
916 const Extension* extension) {
917 BrowserThread::PostTask(
918 BrowserThread::IO, FROM_HERE,
919 NewRunnableMethod(extension_info_map_.get(),
920 &ExtensionInfoMap::AddExtension,
921 make_scoped_refptr(extension)));
922 }
923
UnregisterExtensionWithRequestContexts(const std::string & extension_id,const UnloadedExtensionInfo::Reason reason)924 void ProfileImpl::UnregisterExtensionWithRequestContexts(
925 const std::string& extension_id,
926 const UnloadedExtensionInfo::Reason reason) {
927 BrowserThread::PostTask(
928 BrowserThread::IO, FROM_HERE,
929 NewRunnableMethod(extension_info_map_.get(),
930 &ExtensionInfoMap::RemoveExtension,
931 extension_id,
932 reason));
933 }
934
GetSSLConfigService()935 net::SSLConfigService* ProfileImpl::GetSSLConfigService() {
936 return ssl_config_service_manager_->Get();
937 }
938
GetHostContentSettingsMap()939 HostContentSettingsMap* ProfileImpl::GetHostContentSettingsMap() {
940 if (!host_content_settings_map_.get())
941 host_content_settings_map_ = new HostContentSettingsMap(this);
942 return host_content_settings_map_.get();
943 }
944
GetHostZoomMap()945 HostZoomMap* ProfileImpl::GetHostZoomMap() {
946 if (!host_zoom_map_)
947 host_zoom_map_ = new HostZoomMap(this);
948 return host_zoom_map_.get();
949 }
950
GetGeolocationContentSettingsMap()951 GeolocationContentSettingsMap* ProfileImpl::GetGeolocationContentSettingsMap() {
952 if (!geolocation_content_settings_map_.get())
953 geolocation_content_settings_map_ = new GeolocationContentSettingsMap(this);
954 return geolocation_content_settings_map_.get();
955 }
956
GetGeolocationPermissionContext()957 GeolocationPermissionContext* ProfileImpl::GetGeolocationPermissionContext() {
958 if (!geolocation_permission_context_.get())
959 geolocation_permission_context_ = new GeolocationPermissionContext(this);
960 return geolocation_permission_context_.get();
961 }
962
GetUserStyleSheetWatcher()963 UserStyleSheetWatcher* ProfileImpl::GetUserStyleSheetWatcher() {
964 if (!user_style_sheet_watcher_.get()) {
965 user_style_sheet_watcher_ = new UserStyleSheetWatcher(GetPath());
966 user_style_sheet_watcher_->Init();
967 }
968 return user_style_sheet_watcher_.get();
969 }
970
GetFindBarState()971 FindBarState* ProfileImpl::GetFindBarState() {
972 if (!find_bar_state_.get()) {
973 find_bar_state_.reset(new FindBarState());
974 }
975 return find_bar_state_.get();
976 }
977
GetHistoryService(ServiceAccessType sat)978 HistoryService* ProfileImpl::GetHistoryService(ServiceAccessType sat) {
979 // If saving history is disabled, only allow explicit access.
980 if (GetPrefs()->GetBoolean(prefs::kSavingBrowserHistoryDisabled) &&
981 sat != EXPLICIT_ACCESS)
982 return NULL;
983
984 if (!history_service_created_) {
985 history_service_created_ = true;
986 scoped_refptr<HistoryService> history(new HistoryService(this));
987 if (!history->Init(GetPath(), GetBookmarkModel()))
988 return NULL;
989 history_service_.swap(history);
990
991 // Send out the notification that the history service was created.
992 NotificationService::current()->
993 Notify(NotificationType::HISTORY_CREATED, Source<Profile>(this),
994 Details<HistoryService>(history_service_.get()));
995 }
996 return history_service_.get();
997 }
998
GetHistoryServiceWithoutCreating()999 HistoryService* ProfileImpl::GetHistoryServiceWithoutCreating() {
1000 return history_service_.get();
1001 }
1002
GetTemplateURLModel()1003 TemplateURLModel* ProfileImpl::GetTemplateURLModel() {
1004 if (!template_url_model_.get())
1005 template_url_model_.reset(new TemplateURLModel(this));
1006 return template_url_model_.get();
1007 }
1008
GetTemplateURLFetcher()1009 TemplateURLFetcher* ProfileImpl::GetTemplateURLFetcher() {
1010 if (!template_url_fetcher_.get())
1011 template_url_fetcher_.reset(new TemplateURLFetcher(this));
1012 return template_url_fetcher_.get();
1013 }
1014
GetAutocompleteClassifier()1015 AutocompleteClassifier* ProfileImpl::GetAutocompleteClassifier() {
1016 if (!autocomplete_classifier_.get())
1017 autocomplete_classifier_.reset(new AutocompleteClassifier(this));
1018 return autocomplete_classifier_.get();
1019 }
1020
GetWebDataService(ServiceAccessType sat)1021 WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) {
1022 if (!created_web_data_service_)
1023 CreateWebDataService();
1024 return web_data_service_.get();
1025 }
1026
GetWebDataServiceWithoutCreating()1027 WebDataService* ProfileImpl::GetWebDataServiceWithoutCreating() {
1028 return web_data_service_.get();
1029 }
1030
CreateWebDataService()1031 void ProfileImpl::CreateWebDataService() {
1032 DCHECK(!created_web_data_service_ && web_data_service_.get() == NULL);
1033 created_web_data_service_ = true;
1034 scoped_refptr<WebDataService> wds(new WebDataService());
1035 if (!wds->Init(GetPath()))
1036 return;
1037 web_data_service_.swap(wds);
1038 }
1039
GetPasswordStore(ServiceAccessType sat)1040 PasswordStore* ProfileImpl::GetPasswordStore(ServiceAccessType sat) {
1041 if (!created_password_store_)
1042 CreatePasswordStore();
1043 return password_store_.get();
1044 }
1045
CreatePasswordStore()1046 void ProfileImpl::CreatePasswordStore() {
1047 DCHECK(!created_password_store_ && password_store_.get() == NULL);
1048 created_password_store_ = true;
1049 scoped_refptr<PasswordStore> ps;
1050 FilePath login_db_file_path = GetPath();
1051 login_db_file_path = login_db_file_path.Append(chrome::kLoginDataFileName);
1052 LoginDatabase* login_db = new LoginDatabase();
1053 if (!login_db->Init(login_db_file_path)) {
1054 LOG(ERROR) << "Could not initialize login database.";
1055 delete login_db;
1056 return;
1057 }
1058 #if defined(OS_WIN)
1059 ps = new PasswordStoreWin(login_db, this,
1060 GetWebDataService(Profile::IMPLICIT_ACCESS));
1061 #elif defined(OS_MACOSX)
1062 ps = new PasswordStoreMac(new MacKeychain(), login_db);
1063 #elif defined(OS_CHROMEOS)
1064 // For now, we use PasswordStoreDefault. We might want to make a native
1065 // backend for PasswordStoreX (see below) in the future though.
1066 ps = new PasswordStoreDefault(login_db, this,
1067 GetWebDataService(Profile::IMPLICIT_ACCESS));
1068 #elif defined(OS_POSIX)
1069 // On POSIX systems, we try to use the "native" password management system of
1070 // the desktop environment currently running, allowing GNOME Keyring in XFCE.
1071 // (In all cases we fall back on the basic store in case of failure.)
1072 base::nix::DesktopEnvironment desktop_env;
1073 std::string store_type =
1074 CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
1075 switches::kPasswordStore);
1076 if (store_type == "kwallet") {
1077 desktop_env = base::nix::DESKTOP_ENVIRONMENT_KDE4;
1078 } else if (store_type == "gnome") {
1079 desktop_env = base::nix::DESKTOP_ENVIRONMENT_GNOME;
1080 } else if (store_type == "basic") {
1081 desktop_env = base::nix::DESKTOP_ENVIRONMENT_OTHER;
1082 } else {
1083 // Detect the store to use automatically.
1084 scoped_ptr<base::Environment> env(base::Environment::Create());
1085 desktop_env = base::nix::GetDesktopEnvironment(env.get());
1086 const char* name = base::nix::GetDesktopEnvironmentName(desktop_env);
1087 VLOG(1) << "Password storage detected desktop environment: "
1088 << (name ? name : "(unknown)");
1089 }
1090
1091 scoped_ptr<PasswordStoreX::NativeBackend> backend;
1092 if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_KDE4) {
1093 // KDE3 didn't use DBus, which our KWallet store uses.
1094 VLOG(1) << "Trying KWallet for password storage.";
1095 backend.reset(new NativeBackendKWallet());
1096 if (backend->Init())
1097 VLOG(1) << "Using KWallet for password storage.";
1098 else
1099 backend.reset();
1100 } else if (desktop_env == base::nix::DESKTOP_ENVIRONMENT_GNOME ||
1101 desktop_env == base::nix::DESKTOP_ENVIRONMENT_XFCE) {
1102 #if defined(USE_GNOME_KEYRING)
1103 VLOG(1) << "Trying GNOME keyring for password storage.";
1104 backend.reset(new NativeBackendGnome());
1105 if (backend->Init())
1106 VLOG(1) << "Using GNOME keyring for password storage.";
1107 else
1108 backend.reset();
1109 #endif // defined(USE_GNOME_KEYRING)
1110 }
1111
1112 if (!backend.get()) {
1113 LOG(INFO) << "Using basic (unencrypted) store for password storage. "
1114 "See http://code.google.com/p/chromium/wiki/LinuxPasswordStorage for "
1115 "more information about password storage options.";
1116 }
1117
1118 ps = new PasswordStoreX(login_db, this,
1119 GetWebDataService(Profile::IMPLICIT_ACCESS),
1120 backend.release());
1121 #else
1122 NOTIMPLEMENTED();
1123 #endif
1124 if (!ps)
1125 delete login_db;
1126
1127 if (!ps || !ps->Init()) {
1128 NOTREACHED() << "Could not initialize password manager.";
1129 return;
1130 }
1131 password_store_.swap(ps);
1132 }
1133
GetDownloadManager()1134 DownloadManager* ProfileImpl::GetDownloadManager() {
1135 if (!created_download_manager_) {
1136 scoped_refptr<DownloadManager> dlm(
1137 new DownloadManager(g_browser_process->download_status_updater()));
1138 dlm->Init(this);
1139 created_download_manager_ = true;
1140 download_manager_.swap(dlm);
1141 }
1142 return download_manager_.get();
1143 }
1144
HasCreatedDownloadManager() const1145 bool ProfileImpl::HasCreatedDownloadManager() const {
1146 return created_download_manager_;
1147 }
1148
GetPersonalDataManager()1149 PersonalDataManager* ProfileImpl::GetPersonalDataManager() {
1150 if (!personal_data_manager_.get()) {
1151 personal_data_manager_ = new PersonalDataManager();
1152 personal_data_manager_->Init(this);
1153 }
1154 return personal_data_manager_.get();
1155 }
1156
GetFileSystemContext()1157 fileapi::FileSystemContext* ProfileImpl::GetFileSystemContext() {
1158 if (!file_system_context_.get())
1159 file_system_context_ = CreateFileSystemContext(
1160 GetPath(), IsOffTheRecord(), GetExtensionSpecialStoragePolicy());
1161 DCHECK(file_system_context_.get());
1162 return file_system_context_.get();
1163 }
1164
GetSessionService()1165 SessionService* ProfileImpl::GetSessionService() {
1166 if (!session_service_.get() && !shutdown_session_service_) {
1167 session_service_ = new SessionService(this);
1168 session_service_->ResetFromCurrentBrowsers();
1169 }
1170 return session_service_.get();
1171 }
1172
ShutdownSessionService()1173 void ProfileImpl::ShutdownSessionService() {
1174 if (shutdown_session_service_)
1175 return;
1176
1177 // We're about to exit, force creation of the session service if it hasn't
1178 // been created yet. We do this to ensure session state matches the point in
1179 // time the user exited.
1180 GetSessionService();
1181 shutdown_session_service_ = true;
1182 session_service_ = NULL;
1183 }
1184
HasSessionService() const1185 bool ProfileImpl::HasSessionService() const {
1186 return (session_service_.get() != NULL);
1187 }
1188
HasProfileSyncService() const1189 bool ProfileImpl::HasProfileSyncService() const {
1190 return (sync_service_.get() != NULL);
1191 }
1192
DidLastSessionExitCleanly()1193 bool ProfileImpl::DidLastSessionExitCleanly() {
1194 // last_session_exited_cleanly_ is set when the preferences are loaded. Force
1195 // it to be set by asking for the prefs.
1196 GetPrefs();
1197 return last_session_exited_cleanly_;
1198 }
1199
GetBookmarkModel()1200 BookmarkModel* ProfileImpl::GetBookmarkModel() {
1201 if (!bookmark_bar_model_.get()) {
1202 bookmark_bar_model_.reset(new BookmarkModel(this));
1203 bookmark_bar_model_->Load();
1204 }
1205 return bookmark_bar_model_.get();
1206 }
1207
GetProtocolHandlerRegistry()1208 ProtocolHandlerRegistry* ProfileImpl::GetProtocolHandlerRegistry() {
1209 return protocol_handler_registry_.get();
1210 }
1211
IsSameProfile(Profile * profile)1212 bool ProfileImpl::IsSameProfile(Profile* profile) {
1213 if (profile == static_cast<Profile*>(this))
1214 return true;
1215 Profile* otr_profile = off_the_record_profile_.get();
1216 return otr_profile && profile == otr_profile;
1217 }
1218
GetStartTime() const1219 Time ProfileImpl::GetStartTime() const {
1220 return start_time_;
1221 }
1222
GetTabRestoreService()1223 TabRestoreService* ProfileImpl::GetTabRestoreService() {
1224 if (!tab_restore_service_.get())
1225 tab_restore_service_ = new TabRestoreService(this);
1226 return tab_restore_service_.get();
1227 }
1228
GetTopSites()1229 history::TopSites* ProfileImpl::GetTopSites() {
1230 if (!top_sites_.get()) {
1231 top_sites_ = new history::TopSites(this);
1232 top_sites_->Init(GetPath().Append(chrome::kTopSitesFilename));
1233 }
1234 return top_sites_;
1235 }
1236
GetTopSitesWithoutCreating()1237 history::TopSites* ProfileImpl::GetTopSitesWithoutCreating() {
1238 return top_sites_;
1239 }
1240
ResetTabRestoreService()1241 void ProfileImpl::ResetTabRestoreService() {
1242 tab_restore_service_ = NULL;
1243 }
1244
GetSpellCheckHost()1245 SpellCheckHost* ProfileImpl::GetSpellCheckHost() {
1246 return spellcheck_host_ready_ ? spellcheck_host_.get() : NULL;
1247 }
1248
ReinitializeSpellCheckHost(bool force)1249 void ProfileImpl::ReinitializeSpellCheckHost(bool force) {
1250 // If we are already loading the spellchecker, and this is just a hint to
1251 // load the spellchecker, do nothing.
1252 if (!force && spellcheck_host_.get())
1253 return;
1254
1255 spellcheck_host_ready_ = false;
1256
1257 bool notify = false;
1258 if (spellcheck_host_.get()) {
1259 spellcheck_host_->UnsetObserver();
1260 spellcheck_host_ = NULL;
1261 notify = true;
1262 }
1263
1264 PrefService* prefs = GetPrefs();
1265 if (prefs->GetBoolean(prefs::kEnableSpellCheck)) {
1266 // Retrieve the (perhaps updated recently) dictionary name from preferences.
1267 spellcheck_host_ = SpellCheckHost::Create(
1268 this,
1269 prefs->GetString(prefs::kSpellCheckDictionary),
1270 GetRequestContext());
1271 } else if (notify) {
1272 // The spellchecker has been disabled.
1273 SpellCheckHostInitialized();
1274 }
1275 }
1276
SpellCheckHostInitialized()1277 void ProfileImpl::SpellCheckHostInitialized() {
1278 spellcheck_host_ready_ = spellcheck_host_ &&
1279 (spellcheck_host_->GetDictionaryFile() !=
1280 base::kInvalidPlatformFileValue ||
1281 spellcheck_host_->IsUsingPlatformChecker());
1282 NotificationService::current()->Notify(
1283 NotificationType::SPELLCHECK_HOST_REINITIALIZED,
1284 Source<Profile>(this), NotificationService::NoDetails());
1285 }
1286
GetExtensionPrefValueMap()1287 ExtensionPrefValueMap* ProfileImpl::GetExtensionPrefValueMap() {
1288 if (!extension_pref_value_map_.get())
1289 extension_pref_value_map_.reset(new ExtensionPrefValueMap);
1290 return extension_pref_value_map_.get();
1291 }
1292
GetWebKitContext()1293 WebKitContext* ProfileImpl::GetWebKitContext() {
1294 if (!webkit_context_.get()) {
1295 webkit_context_ = new WebKitContext(
1296 IsOffTheRecord(), GetPath(), GetExtensionSpecialStoragePolicy(),
1297 clear_local_state_on_exit_);
1298 }
1299 return webkit_context_.get();
1300 }
1301
MarkAsCleanShutdown()1302 void ProfileImpl::MarkAsCleanShutdown() {
1303 if (prefs_.get()) {
1304 // The session cleanly exited, set kSessionExitedCleanly appropriately.
1305 prefs_->SetBoolean(prefs::kSessionExitedCleanly, true);
1306
1307 // NOTE: If you change what thread this writes on, be sure and update
1308 // ChromeFrame::EndSession().
1309 prefs_->SavePersistentPrefs();
1310 }
1311 }
1312
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)1313 void ProfileImpl::Observe(NotificationType type,
1314 const NotificationSource& source,
1315 const NotificationDetails& details) {
1316 if (NotificationType::PREF_CHANGED == type) {
1317 std::string* pref_name_in = Details<std::string>(details).ptr();
1318 PrefService* prefs = Source<PrefService>(source).ptr();
1319 DCHECK(pref_name_in && prefs);
1320 if (*pref_name_in == prefs::kSpellCheckDictionary ||
1321 *pref_name_in == prefs::kEnableSpellCheck) {
1322 ReinitializeSpellCheckHost(true);
1323 } else if (*pref_name_in == prefs::kEnableAutoSpellCorrect) {
1324 NotificationService::current()->Notify(
1325 NotificationType::SPELLCHECK_AUTOSPELL_TOGGLED,
1326 Source<Profile>(this), NotificationService::NoDetails());
1327 } else if (*pref_name_in == prefs::kClearSiteDataOnExit) {
1328 clear_local_state_on_exit_ =
1329 prefs->GetBoolean(prefs::kClearSiteDataOnExit);
1330 if (webkit_context_) {
1331 webkit_context_->set_clear_local_state_on_exit(
1332 clear_local_state_on_exit_);
1333 }
1334 if (appcache_service_) {
1335 appcache_service_->SetClearLocalStateOnExit(
1336 clear_local_state_on_exit_);
1337 }
1338 }
1339 } else if (NotificationType::BOOKMARK_MODEL_LOADED == type) {
1340 GetProfileSyncService(); // Causes lazy-load if sync is enabled.
1341 registrar_.Remove(this, NotificationType::BOOKMARK_MODEL_LOADED,
1342 Source<Profile>(this));
1343 }
1344 }
1345
StopCreateSessionServiceTimer()1346 void ProfileImpl::StopCreateSessionServiceTimer() {
1347 create_session_service_timer_.Stop();
1348 }
1349
GetTokenService()1350 TokenService* ProfileImpl::GetTokenService() {
1351 if (!token_service_.get()) {
1352 token_service_.reset(new TokenService());
1353 }
1354 return token_service_.get();
1355 }
1356
GetProfileSyncService()1357 ProfileSyncService* ProfileImpl::GetProfileSyncService() {
1358 #if defined(OS_CHROMEOS)
1359 if (!sync_service_.get()) {
1360 // In ChromeOS, sync only gets initialized properly from login, when
1361 // kLoginManager is specified. If this gets called before login, or
1362 // during a debugging session without kLoginManager, this will return
1363 // NULL, so ensure that calls either handle a NULL result, or use
1364 // HasProfileSyncService() to guard against the call.
1365 return NULL;
1366 }
1367 #endif
1368 return GetProfileSyncService("");
1369 }
1370
GetProfileSyncService(const std::string & cros_user)1371 ProfileSyncService* ProfileImpl::GetProfileSyncService(
1372 const std::string& cros_user) {
1373
1374 if (!ProfileSyncService::IsSyncEnabled())
1375 return NULL;
1376 if (!sync_service_.get())
1377 InitSyncService(cros_user);
1378 return sync_service_.get();
1379 }
1380
GetBrowserSignin()1381 BrowserSignin* ProfileImpl::GetBrowserSignin() {
1382 if (!browser_signin_.get()) {
1383 browser_signin_.reset(new BrowserSignin(this));
1384 }
1385 return browser_signin_.get();
1386 }
1387
GetCloudPrintProxyService()1388 CloudPrintProxyService* ProfileImpl::GetCloudPrintProxyService() {
1389 if (!cloud_print_proxy_service_.get())
1390 InitCloudPrintProxyService();
1391 return cloud_print_proxy_service_.get();
1392 }
1393
InitSyncService(const std::string & cros_user)1394 void ProfileImpl::InitSyncService(const std::string& cros_user) {
1395 profile_sync_factory_.reset(
1396 new ProfileSyncFactoryImpl(this, CommandLine::ForCurrentProcess()));
1397 sync_service_.reset(
1398 profile_sync_factory_->CreateProfileSyncService(cros_user));
1399 sync_service_->Initialize();
1400 }
1401
InitCloudPrintProxyService()1402 void ProfileImpl::InitCloudPrintProxyService() {
1403 cloud_print_proxy_service_ = new CloudPrintProxyService(this);
1404 cloud_print_proxy_service_->Initialize();
1405 }
1406
GetBlobStorageContext()1407 ChromeBlobStorageContext* ProfileImpl::GetBlobStorageContext() {
1408 if (!blob_storage_context_) {
1409 blob_storage_context_ = new ChromeBlobStorageContext();
1410 BrowserThread::PostTask(
1411 BrowserThread::IO, FROM_HERE,
1412 NewRunnableMethod(blob_storage_context_.get(),
1413 &ChromeBlobStorageContext::InitializeOnIOThread));
1414 }
1415 return blob_storage_context_;
1416 }
1417
GetExtensionInfoMap()1418 ExtensionInfoMap* ProfileImpl::GetExtensionInfoMap() {
1419 return extension_info_map_.get();
1420 }
1421
GetPolicyConnector()1422 policy::ProfilePolicyConnector* ProfileImpl::GetPolicyConnector() {
1423 if (!profile_policy_connector_.get())
1424 profile_policy_connector_.reset(new policy::ProfilePolicyConnector(this));
1425
1426 return profile_policy_connector_.get();
1427 }
1428
GetChromeURLDataManager()1429 ChromeURLDataManager* ProfileImpl::GetChromeURLDataManager() {
1430 if (!chrome_url_data_manager_.get())
1431 chrome_url_data_manager_.reset(new ChromeURLDataManager(this));
1432 return chrome_url_data_manager_.get();
1433 }
1434
GetInstantPromoCounter()1435 PromoCounter* ProfileImpl::GetInstantPromoCounter() {
1436 #if defined(OS_WIN)
1437 // TODO: enable this when we're ready to turn on the promo.
1438 /*
1439 if (!checked_instant_promo_) {
1440 checked_instant_promo_ = true;
1441 PrefService* prefs = GetPrefs();
1442 if (!prefs->GetBoolean(prefs::kInstantEnabledOnce) &&
1443 !InstantController::IsEnabled(this) &&
1444 InstallUtil::IsChromeSxSProcess()) {
1445 DCHECK(!instant_promo_counter_.get());
1446 instant_promo_counter_.reset(
1447 new PromoCounter(this, prefs::kInstantPromo, "Instant.Promo", 3, 3));
1448 }
1449 }
1450 */
1451 return instant_promo_counter_.get();
1452 #else
1453 return NULL;
1454 #endif
1455 }
1456
1457 #if defined(OS_CHROMEOS)
ChangeAppLocale(const std::string & new_locale,AppLocaleChangedVia via)1458 void ProfileImpl::ChangeAppLocale(
1459 const std::string& new_locale, AppLocaleChangedVia via) {
1460 if (new_locale.empty()) {
1461 NOTREACHED();
1462 return;
1463 }
1464 PrefService* local_state = g_browser_process->local_state();
1465 DCHECK(local_state);
1466 if (local_state->IsManagedPreference(prefs::kApplicationLocale))
1467 return;
1468 std::string pref_locale = GetPrefs()->GetString(prefs::kApplicationLocale);
1469 bool do_update_pref = true;
1470 switch (via) {
1471 case APP_LOCALE_CHANGED_VIA_SETTINGS:
1472 case APP_LOCALE_CHANGED_VIA_REVERT: {
1473 // We keep kApplicationLocaleBackup value as a reference. In case value
1474 // of kApplicationLocale preference would change due to sync from other
1475 // device then kApplicationLocaleBackup value will trigger and allow us to
1476 // show notification about automatic locale change in LocaleChangeGuard.
1477 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
1478 GetPrefs()->ClearPref(prefs::kApplicationLocaleAccepted);
1479 // We maintain kApplicationLocale property in both a global storage
1480 // and user's profile. Global property determines locale of login screen,
1481 // while user's profile determines his personal locale preference.
1482 break;
1483 }
1484 case APP_LOCALE_CHANGED_VIA_LOGIN: {
1485 if (!pref_locale.empty()) {
1486 DCHECK(pref_locale == new_locale);
1487 std::string accepted_locale =
1488 GetPrefs()->GetString(prefs::kApplicationLocaleAccepted);
1489 if (accepted_locale == new_locale) {
1490 // If locale is accepted then we do not want to show LocaleChange
1491 // notification. This notification is triggered by different values
1492 // of kApplicationLocaleBackup and kApplicationLocale preferences,
1493 // so make them identical.
1494 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
1495 } else {
1496 // Back up locale of login screen.
1497 std::string cur_locale = g_browser_process->GetApplicationLocale();
1498 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
1499 if (locale_change_guard_ == NULL)
1500 locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this));
1501 locale_change_guard_->PrepareChangingLocale(cur_locale, new_locale);
1502 }
1503 } else {
1504 std::string cur_locale = g_browser_process->GetApplicationLocale();
1505 std::string backup_locale =
1506 GetPrefs()->GetString(prefs::kApplicationLocaleBackup);
1507 // Profile synchronization takes time and is not completed at that
1508 // moment at first login. So we initialize locale preference in steps:
1509 // (1) first save it to temporary backup;
1510 // (2) on next login we assume that synchronization is already completed
1511 // and we may finalize initialization.
1512 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
1513 if (!backup_locale.empty())
1514 GetPrefs()->SetString(prefs::kApplicationLocale, backup_locale);
1515 do_update_pref = false;
1516 }
1517 break;
1518 }
1519 case APP_LOCALE_CHANGED_VIA_UNKNOWN:
1520 default: {
1521 NOTREACHED();
1522 break;
1523 }
1524 }
1525 if (do_update_pref)
1526 GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
1527 local_state->SetString(prefs::kApplicationLocale, new_locale);
1528
1529 if (chromeos::UserManager::Get()->current_user_is_owner())
1530 local_state->SetString(prefs::kOwnerLocale, new_locale);
1531
1532 GetPrefs()->ScheduleSavePersistentPrefs();
1533 local_state->ScheduleSavePersistentPrefs();
1534 }
1535
OnLogin()1536 void ProfileImpl::OnLogin() {
1537 if (locale_change_guard_ == NULL)
1538 locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this));
1539 locale_change_guard_->OnLogin();
1540 }
1541
SetupChromeOSEnterpriseExtensionObserver()1542 void ProfileImpl::SetupChromeOSEnterpriseExtensionObserver() {
1543 DCHECK(!chromeos_enterprise_extension_observer_.get());
1544 chromeos_enterprise_extension_observer_.reset(
1545 new chromeos::EnterpriseExtensionObserver(this));
1546 }
1547
InitChromeOSPreferences()1548 void ProfileImpl::InitChromeOSPreferences() {
1549 chromeos_preferences_.reset(new chromeos::Preferences());
1550 chromeos_preferences_->Init(GetPrefs());
1551 }
1552 #endif // defined(OS_CHROMEOS)
1553
GetProxyConfigTracker()1554 PrefProxyConfigTracker* ProfileImpl::GetProxyConfigTracker() {
1555 if (!pref_proxy_config_tracker_)
1556 pref_proxy_config_tracker_ = new PrefProxyConfigTracker(GetPrefs());
1557
1558 return pref_proxy_config_tracker_;
1559 }
1560
GetPrerenderManager()1561 prerender::PrerenderManager* ProfileImpl::GetPrerenderManager() {
1562 if (!prerender::PrerenderManager::IsPrerenderingPossible())
1563 return NULL;
1564 if (!prerender_manager_)
1565 prerender_manager_ = new prerender::PrerenderManager(this);
1566 return prerender_manager_;
1567 }
1568