Fix build break
[chromium-blink-merge.git] / chrome / browser / profiles / profile_impl.cc
blob67f480340743f55ea10a67cf9de854663ddc3d39
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/profiles/profile_impl.h"
7 #include "base/bind.h"
8 #include "base/callback.h"
9 #include "base/command_line.h"
10 #include "base/compiler_specific.h"
11 #include "base/environment.h"
12 #include "base/file_util.h"
13 #include "base/files/file_path.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/path_service.h"
16 #include "base/prefs/json_pref_store.h"
17 #include "base/string_util.h"
18 #include "base/stringprintf.h"
19 #include "base/strings/string_number_conversions.h"
20 #include "base/synchronization/waitable_event.h"
21 #include "base/threading/sequenced_worker_pool.h"
22 #include "base/utf_string_conversions.h"
23 #include "base/version.h"
24 #include "chrome/browser/autocomplete/autocomplete_classifier.h"
25 #include "chrome/browser/background/background_contents_service_factory.h"
26 #include "chrome/browser/background/background_mode_manager.h"
27 #include "chrome/browser/bookmarks/bookmark_model.h"
28 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
29 #include "chrome/browser/browser_process.h"
30 #include "chrome/browser/content_settings/cookie_settings.h"
31 #include "chrome/browser/content_settings/host_content_settings_map.h"
32 #include "chrome/browser/download/chrome_download_manager_delegate.h"
33 #include "chrome/browser/download/download_service.h"
34 #include "chrome/browser/download/download_service_factory.h"
35 #include "chrome/browser/extensions/extension_pref_store.h"
36 #include "chrome/browser/extensions/extension_pref_value_map.h"
37 #include "chrome/browser/extensions/extension_pref_value_map_factory.h"
38 #include "chrome/browser/extensions/extension_service.h"
39 #include "chrome/browser/extensions/extension_special_storage_policy.h"
40 #include "chrome/browser/extensions/extension_system.h"
41 #include "chrome/browser/geolocation/chrome_geolocation_permission_context.h"
42 #include "chrome/browser/geolocation/chrome_geolocation_permission_context_factory.h"
43 #include "chrome/browser/history/shortcuts_backend.h"
44 #include "chrome/browser/history/top_sites.h"
45 #include "chrome/browser/metrics/metrics_service.h"
46 #include "chrome/browser/net/chrome_url_request_context.h"
47 #include "chrome/browser/net/net_pref_observer.h"
48 #include "chrome/browser/net/predictor.h"
49 #include "chrome/browser/net/proxy_service_factory.h"
50 #include "chrome/browser/net/ssl_config_service_manager.h"
51 #include "chrome/browser/net/url_fixer_upper.h"
52 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
53 #include "chrome/browser/plugins/plugin_prefs.h"
54 #include "chrome/browser/prefs/browser_prefs.h"
55 #include "chrome/browser/prefs/chrome_pref_service_factory.h"
56 #include "chrome/browser/prefs/pref_service_syncable.h"
57 #include "chrome/browser/prefs/scoped_user_pref_update.h"
58 #include "chrome/browser/prerender/prerender_manager_factory.h"
59 #include "chrome/browser/profiles/bookmark_model_loaded_observer.h"
60 #include "chrome/browser/profiles/chrome_version_service.h"
61 #include "chrome/browser/profiles/gaia_info_update_service_factory.h"
62 #include "chrome/browser/profiles/profile_dependency_manager.h"
63 #include "chrome/browser/profiles/profile_destroyer.h"
64 #include "chrome/browser/profiles/profile_info_cache.h"
65 #include "chrome/browser/profiles/profile_manager.h"
66 #include "chrome/browser/search_engines/template_url_fetcher.h"
67 #include "chrome/browser/sessions/session_service_factory.h"
68 #include "chrome/browser/speech/chrome_speech_recognition_preferences.h"
69 #include "chrome/browser/ui/startup/startup_browser_creator.h"
70 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
71 #include "chrome/browser/user_style_sheet_watcher.h"
72 #include "chrome/browser/webdata/web_data_service.h"
73 #include "chrome/common/chrome_constants.h"
74 #include "chrome/common/chrome_notification_types.h"
75 #include "chrome/common/chrome_paths_internal.h"
76 #include "chrome/common/chrome_switches.h"
77 #include "chrome/common/chrome_version_info.h"
78 #include "chrome/common/pref_names.h"
79 #include "chrome/common/startup_metric_utils.h"
80 #include "chrome/common/url_constants.h"
81 #include "components/user_prefs/pref_registry_syncable.h"
82 #include "components/user_prefs/user_prefs.h"
83 #include "content/public/browser/browser_thread.h"
84 #include "content/public/browser/dom_storage_context.h"
85 #include "content/public/browser/host_zoom_map.h"
86 #include "content/public/browser/notification_service.h"
87 #include "content/public/browser/render_process_host.h"
88 #include "content/public/browser/storage_partition.h"
89 #include "content/public/browser/user_metrics.h"
90 #include "content/public/common/content_constants.h"
91 #include "grit/chromium_strings.h"
92 #include "grit/generated_resources.h"
93 #include "ui/base/l10n/l10n_util.h"
95 #if defined(ENABLE_CONFIGURATION_POLICY)
96 #include "chrome/browser/policy/browser_policy_connector.h"
97 #if !defined(OS_CHROMEOS)
98 #include "chrome/browser/policy/cloud/user_cloud_policy_manager.h"
99 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
100 #endif
101 #if defined(ENABLE_MANAGED_USERS)
102 #include "chrome/browser/policy/managed_mode_policy_provider.h"
103 #endif
104 #else
105 #include "chrome/browser/policy/policy_service_stub.h"
106 #endif // defined(ENABLE_CONFIGURATION_POLICY)
108 #if defined(OS_WIN)
109 #include "chrome/installer/util/install_util.h"
110 #endif
112 #if defined(OS_CHROMEOS)
113 #include "chrome/browser/chromeos/enterprise_extension_observer.h"
114 #include "chrome/browser/chromeos/locale_change_guard.h"
115 #include "chrome/browser/chromeos/login/user_manager.h"
116 #include "chrome/browser/chromeos/preferences.h"
117 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
118 #endif
120 using base::Time;
121 using base::TimeDelta;
122 using content::BrowserThread;
123 using content::DownloadManagerDelegate;
124 using content::HostZoomMap;
125 using content::UserMetricsAction;
127 namespace {
129 // Constrict us to a very specific platform and architecture to make sure
130 // ifdefs don't cause problems with the check.
131 #if defined(OS_LINUX) && defined(TOOLKIT_GTK) && defined(ARCH_CPU_X86_64) && \
132 !defined(_GLIBCXX_DEBUG)
133 // Make sure that the ProfileImpl doesn't grow. We're currently trying to drive
134 // the number of services that are included in ProfileImpl (instead of using
135 // ProfileKeyedServiceFactory) to zero.
137 // If you don't know about this effort, please read:
138 // https://sites.google.com/a/chromium.org/dev/developers/design-documents/profile-architecture
140 // REVIEWERS: Do not let anyone increment this. We need to drive the number of
141 // raw accessed services down to zero. DO NOT LET PEOPLE REGRESS THIS UNLESS
142 // THE PATCH ITSELF IS MAKING PROGRESS ON PKSF REFACTORING.
143 COMPILE_ASSERT(sizeof(ProfileImpl) <= 744u, profile_impl_size_unexpected);
144 #endif
146 #if defined(ENABLE_SESSION_SERVICE)
147 // Delay, in milliseconds, before we explicitly create the SessionService.
148 static const int kCreateSessionServiceDelayMS = 500;
149 #endif
151 // Text content of README file created in each profile directory. Both %s
152 // placeholders must contain the product name. This is not localizable and hence
153 // not in resources.
154 static const char kReadmeText[] =
155 "%s settings and storage represent user-selected preferences and "
156 "information and MUST not be extracted, overwritten or modified except "
157 "through %s defined APIs.";
159 // Value written to prefs for EXIT_CRASHED and EXIT_SESSION_ENDED.
160 const char* const kPrefExitTypeCrashed = "Crashed";
161 const char* const kPrefExitTypeSessionEnded = "SessionEnded";
163 // Helper method needed because PostTask cannot currently take a Callback
164 // function with non-void return type.
165 void CreateDirectoryAndSignal(const base::FilePath& path,
166 base::WaitableEvent* done_creating) {
167 DVLOG(1) << "Creating directory " << path.value();
168 file_util::CreateDirectory(path);
169 done_creating->Signal();
172 // Task that blocks the FILE thread until CreateDirectoryAndSignal() finishes on
173 // blocking I/O pool.
174 void BlockFileThreadOnDirectoryCreate(base::WaitableEvent* done_creating) {
175 done_creating->Wait();
178 // Initiates creation of profile directory on |sequenced_task_runner| and
179 // ensures that FILE thread is blocked until that operation finishes.
180 void CreateProfileDirectory(base::SequencedTaskRunner* sequenced_task_runner,
181 const base::FilePath& path) {
182 base::WaitableEvent* done_creating = new base::WaitableEvent(false, false);
183 sequenced_task_runner->PostTask(FROM_HERE,
184 base::Bind(&CreateDirectoryAndSignal,
185 path,
186 done_creating));
187 // Block the FILE thread until directory is created on I/O pool to make sure
188 // that we don't attempt any operation until that part completes.
189 BrowserThread::PostTask(
190 BrowserThread::FILE, FROM_HERE,
191 base::Bind(&BlockFileThreadOnDirectoryCreate,
192 base::Owned(done_creating)));
195 base::FilePath GetCachePath(const base::FilePath& base) {
196 return base.Append(chrome::kCacheDirname);
199 base::FilePath GetMediaCachePath(const base::FilePath& base) {
200 return base.Append(chrome::kMediaCacheDirname);
203 void EnsureReadmeFile(const base::FilePath& base) {
204 base::FilePath readme_path = base.Append(chrome::kReadmeFilename);
205 if (file_util::PathExists(readme_path))
206 return;
207 std::string product_name = l10n_util::GetStringUTF8(IDS_PRODUCT_NAME);
208 std::string readme_text = base::StringPrintf(
209 kReadmeText, product_name.c_str(), product_name.c_str());
210 if (file_util::WriteFile(
211 readme_path, readme_text.data(), readme_text.size()) == -1) {
212 LOG(ERROR) << "Could not create README file.";
216 // Converts the kSessionExitedCleanly pref to the corresponding EXIT_TYPE.
217 Profile::ExitType SessionTypePrefValueToExitType(const std::string& value) {
218 if (value == kPrefExitTypeSessionEnded)
219 return Profile::EXIT_SESSION_ENDED;
220 if (value == kPrefExitTypeCrashed)
221 return Profile::EXIT_CRASHED;
222 return Profile::EXIT_NORMAL;
225 // Converts an ExitType into a string that is written to prefs.
226 std::string ExitTypeToSessionTypePrefValue(Profile::ExitType type) {
227 switch (type) {
228 case Profile::EXIT_NORMAL:
229 return ProfileImpl::kPrefExitTypeNormal;
230 case Profile::EXIT_SESSION_ENDED:
231 return kPrefExitTypeSessionEnded;
232 case Profile::EXIT_CRASHED:
233 return kPrefExitTypeCrashed;
235 NOTREACHED();
236 return std::string();
239 } // namespace
241 // static
242 Profile* Profile::CreateProfile(const base::FilePath& path,
243 Delegate* delegate,
244 CreateMode create_mode) {
245 // Get sequenced task runner for making sure that file operations of
246 // this profile (defined by |path|) are executed in expected order
247 // (what was previously assured by the FILE thread).
248 scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
249 JsonPrefStore::GetTaskRunnerForFile(path,
250 BrowserThread::GetBlockingPool());
251 if (create_mode == CREATE_MODE_ASYNCHRONOUS) {
252 DCHECK(delegate);
253 CreateProfileDirectory(sequenced_task_runner, path);
254 } else if (create_mode == CREATE_MODE_SYNCHRONOUS) {
255 if (!file_util::PathExists(path)) {
256 // TODO(tc): http://b/1094718 Bad things happen if we can't write to the
257 // profile directory. We should eventually be able to run in this
258 // situation.
259 if (!file_util::CreateDirectory(path))
260 return NULL;
262 } else {
263 NOTREACHED();
266 return new ProfileImpl(path, delegate, create_mode, sequenced_task_runner);
269 // static
270 int ProfileImpl::create_readme_delay_ms = 60000;
272 // static
273 const char* const ProfileImpl::kPrefExitTypeNormal = "Normal";
275 // static
276 void ProfileImpl::RegisterUserPrefs(PrefRegistrySyncable* registry) {
277 registry->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled,
278 false,
279 PrefRegistrySyncable::UNSYNCABLE_PREF);
280 registry->RegisterBooleanPref(prefs::kAllowDeletingBrowserHistory,
281 true,
282 PrefRegistrySyncable::UNSYNCABLE_PREF);
283 registry->RegisterBooleanPref(prefs::kSigninAllowed,
284 true,
285 PrefRegistrySyncable::UNSYNCABLE_PREF);
286 registry->RegisterBooleanPref(prefs::kForceSafeSearch,
287 false,
288 PrefRegistrySyncable::UNSYNCABLE_PREF);
289 registry->RegisterIntegerPref(prefs::kProfileAvatarIndex,
291 PrefRegistrySyncable::SYNCABLE_PREF);
292 registry->RegisterStringPref(
293 prefs::kProfileName, std::string(), PrefRegistrySyncable::SYNCABLE_PREF);
294 registry->RegisterBooleanPref(prefs::kProfileIsManaged,
295 false,
296 PrefRegistrySyncable::SYNCABLE_PREF);
297 registry->RegisterStringPref(prefs::kHomePage,
298 std::string(),
299 PrefRegistrySyncable::SYNCABLE_PREF);
300 #if defined(ENABLE_PRINTING)
301 registry->RegisterBooleanPref(prefs::kPrintingEnabled,
302 true,
303 PrefRegistrySyncable::UNSYNCABLE_PREF);
304 #endif
305 registry->RegisterBooleanPref(prefs::kPrintPreviewDisabled,
306 #if defined(GOOGLE_CHROME_BUILD)
307 false,
308 #else
309 true,
310 #endif
311 PrefRegistrySyncable::UNSYNCABLE_PREF);
313 // Initialize the cache prefs.
314 registry->RegisterFilePathPref(prefs::kDiskCacheDir,
315 base::FilePath(),
316 PrefRegistrySyncable::UNSYNCABLE_PREF);
317 registry->RegisterIntegerPref(prefs::kDiskCacheSize,
319 PrefRegistrySyncable::UNSYNCABLE_PREF);
320 registry->RegisterIntegerPref(prefs::kMediaCacheSize,
322 PrefRegistrySyncable::UNSYNCABLE_PREF);
324 // Deprecated. Kept around for migration.
325 registry->RegisterBooleanPref(prefs::kClearSiteDataOnExit,
326 false,
327 PrefRegistrySyncable::SYNCABLE_PREF);
330 ProfileImpl::ProfileImpl(
331 const base::FilePath& path,
332 Delegate* delegate,
333 CreateMode create_mode,
334 base::SequencedTaskRunner* sequenced_task_runner)
335 : zoom_callback_(base::Bind(&ProfileImpl::OnZoomLevelChanged,
336 base::Unretained(this))),
337 path_(path),
338 pref_registry_(new PrefRegistrySyncable),
339 ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)),
340 host_content_settings_map_(NULL),
341 last_session_exit_type_(EXIT_NORMAL),
342 start_time_(Time::Now()),
343 delegate_(delegate),
344 predictor_(NULL) {
345 DCHECK(!path.empty()) << "Using an empty path will attempt to write " <<
346 "profile files to the root directory!";
348 #if defined(ENABLE_SESSION_SERVICE)
349 create_session_service_timer_.Start(FROM_HERE,
350 TimeDelta::FromMilliseconds(kCreateSessionServiceDelayMS), this,
351 &ProfileImpl::EnsureSessionServiceCreated);
352 #endif
354 // Determine if prefetch is enabled for this profile.
355 // If not profile_manager is present, it means we are in a unittest.
356 const CommandLine* command_line = CommandLine::ForCurrentProcess();
357 predictor_ = chrome_browser_net::Predictor::CreatePredictor(
358 !command_line->HasSwitch(switches::kDisablePreconnect),
359 g_browser_process->profile_manager() == NULL);
361 #if defined(ENABLE_CONFIGURATION_POLICY)
362 // If we are creating the profile synchronously, then we should load the
363 // policy data immediately.
364 bool force_immediate_policy_load = (create_mode == CREATE_MODE_SYNCHRONOUS);
366 // TODO(atwilson): Change |cloud_policy_manager_| and
367 // |managed_mode_policy_provider_| to proper ProfileKeyedServices once
368 // PrefServiceSyncable is a ProfileKeyedService (policy must be initialized
369 // before PrefServiceSyncable because PrefServiceSyncable depends on policy
370 // loading to get overridden pref values).
371 #if !defined(OS_CHROMEOS)
372 if (!command_line->HasSwitch(switches::kDisableCloudPolicyOnSignin)) {
373 cloud_policy_manager_ =
374 policy::UserCloudPolicyManagerFactory::CreateForProfile(
375 this, force_immediate_policy_load);
376 cloud_policy_manager_->Init();
378 #endif
379 #if defined(ENABLE_MANAGED_USERS)
380 managed_mode_policy_provider_ =
381 policy::ManagedModePolicyProvider::Create(this,
382 sequenced_task_runner,
383 force_immediate_policy_load);
384 managed_mode_policy_provider_->Init();
385 #endif
386 policy_service_ =
387 g_browser_process->browser_policy_connector()->CreatePolicyService(this);
388 #else
389 policy_service_.reset(new policy::PolicyServiceStub());
390 #endif
392 DCHECK(create_mode == CREATE_MODE_ASYNCHRONOUS ||
393 create_mode == CREATE_MODE_SYNCHRONOUS);
394 bool async_prefs = create_mode == CREATE_MODE_ASYNCHRONOUS;
396 chrome::RegisterUserPrefs(pref_registry_);
399 // On startup, preference loading is always synchronous so a scoped timer
400 // will work here.
401 startup_metric_utils::ScopedSlowStartupUMA
402 scoped_timer("Startup.SlowStartupPreferenceLoading");
403 prefs_.reset(chrome_prefs::CreateProfilePrefs(
404 GetPrefFilePath(),
405 sequenced_task_runner,
406 policy_service_.get(),
407 new ExtensionPrefStore(
408 ExtensionPrefValueMapFactory::GetForProfile(this), false),
409 pref_registry_,
410 async_prefs));
411 // Register on BrowserContext.
412 components::UserPrefs::Set(this, prefs_.get());
415 startup_metric_utils::ScopedSlowStartupUMA
416 scoped_timer("Startup.SlowStartupFinalProfileInit");
417 if (async_prefs) {
418 // Wait for the notification that prefs has been loaded
419 // (successfully or not). Note that we can use base::Unretained
420 // because the PrefService is owned by this class and lives on
421 // the same thread.
422 prefs_->AddPrefInitObserver(base::Bind(&ProfileImpl::OnPrefsLoaded,
423 base::Unretained(this)));
424 } else {
425 // Prefs were loaded synchronously so we can continue directly.
426 OnPrefsLoaded(true);
430 void ProfileImpl::DoFinalInit() {
431 PrefService* prefs = GetPrefs();
432 pref_change_registrar_.Init(prefs);
433 pref_change_registrar_.Add(
434 prefs::kGoogleServicesUsername,
435 base::Bind(&ProfileImpl::UpdateProfileUserNameCache,
436 base::Unretained(this)));
437 pref_change_registrar_.Add(
438 prefs::kDefaultZoomLevel,
439 base::Bind(&ProfileImpl::OnDefaultZoomLevelChanged,
440 base::Unretained(this)));
441 pref_change_registrar_.Add(
442 prefs::kProfileAvatarIndex,
443 base::Bind(&ProfileImpl::UpdateProfileAvatarCache,
444 base::Unretained(this)));
445 pref_change_registrar_.Add(
446 prefs::kProfileName,
447 base::Bind(&ProfileImpl::UpdateProfileNameCache,
448 base::Unretained(this)));
450 // It would be nice to use PathService for fetching this directory, but
451 // the cache directory depends on the profile directory, which isn't available
452 // to PathService.
453 chrome::GetUserCacheDirectory(path_, &base_cache_path_);
454 // Always create the cache directory asynchronously.
455 scoped_refptr<base::SequencedTaskRunner> sequenced_task_runner =
456 JsonPrefStore::GetTaskRunnerForFile(base_cache_path_,
457 BrowserThread::GetBlockingPool());
458 CreateProfileDirectory(sequenced_task_runner, base_cache_path_);
460 // Now that the profile is hooked up to receive pref change notifications to
461 // kGoogleServicesUsername, initialize components that depend on it to reflect
462 // the current value.
463 UpdateProfileUserNameCache();
464 GAIAInfoUpdateServiceFactory::GetForProfile(this);
466 PrefService* local_state = g_browser_process->local_state();
467 ssl_config_service_manager_.reset(
468 SSLConfigServiceManager::CreateDefaultManager(local_state, prefs));
470 // Initialize the BackgroundModeManager - this has to be done here before
471 // InitExtensions() is called because it relies on receiving notifications
472 // when extensions are loaded. BackgroundModeManager is not needed under
473 // ChromeOS because Chrome is always running, no need for special keep-alive
474 // or launch-on-startup support unless kKeepAliveForTest is set.
475 bool init_background_mode_manager = true;
476 #if defined(OS_CHROMEOS)
477 if (!CommandLine::ForCurrentProcess()->HasSwitch(switches::kKeepAliveForTest))
478 init_background_mode_manager = false;
479 #endif
480 if (init_background_mode_manager) {
481 if (g_browser_process->background_mode_manager())
482 g_browser_process->background_mode_manager()->RegisterProfile(this);
485 base::FilePath cookie_path = GetPath();
486 cookie_path = cookie_path.Append(chrome::kCookieFilename);
487 base::FilePath server_bound_cert_path = GetPath();
488 server_bound_cert_path =
489 server_bound_cert_path.Append(chrome::kOBCertFilename);
490 base::FilePath cache_path = base_cache_path_;
491 int cache_max_size;
492 GetCacheParameters(false, &cache_path, &cache_max_size);
493 cache_path = GetCachePath(cache_path);
495 base::FilePath media_cache_path = base_cache_path_;
496 int media_cache_max_size;
497 GetCacheParameters(true, &media_cache_path, &media_cache_max_size);
498 media_cache_path = GetMediaCachePath(media_cache_path);
500 base::FilePath extensions_cookie_path = GetPath();
501 extensions_cookie_path =
502 extensions_cookie_path.Append(chrome::kExtensionsCookieFilename);
504 base::FilePath infinite_cache_path = GetPath();
505 infinite_cache_path =
506 infinite_cache_path.Append(FILE_PATH_LITERAL("Infinite Cache"));
508 #if defined(OS_ANDROID)
509 SessionStartupPref::Type startup_pref_type =
510 SessionStartupPref::GetDefaultStartupType();
511 #else
512 SessionStartupPref::Type startup_pref_type =
513 StartupBrowserCreator::GetSessionStartupPref(
514 *CommandLine::ForCurrentProcess(), this).type;
515 #endif
516 bool restore_old_session_cookies =
517 (GetLastSessionExitType() == Profile::EXIT_CRASHED ||
518 startup_pref_type == SessionStartupPref::LAST);
520 InitHostZoomMap();
522 // Make sure we initialize the ProfileIOData after everything else has been
523 // initialized that we might be reading from the IO thread.
525 io_data_.Init(cookie_path, server_bound_cert_path, cache_path,
526 cache_max_size, media_cache_path, media_cache_max_size,
527 extensions_cookie_path, GetPath(), infinite_cache_path,
528 predictor_,
529 restore_old_session_cookies,
530 GetSpecialStoragePolicy());
532 #if defined(ENABLE_PLUGINS)
533 ChromePluginServiceFilter::GetInstance()->RegisterResourceContext(
534 PluginPrefs::GetForProfile(this),
535 io_data_.GetResourceContextNoInit());
536 #endif
538 // Delay README creation to not impact startup performance.
539 BrowserThread::PostDelayedTask(
540 BrowserThread::FILE, FROM_HERE,
541 base::Bind(&EnsureReadmeFile, GetPath()),
542 base::TimeDelta::FromMilliseconds(create_readme_delay_ms));
544 if (!CommandLine::ForCurrentProcess()->HasSwitch(
545 switches::kDisableRestoreSessionState)) {
546 content::BrowserContext::GetDefaultStoragePartition(this)->
547 GetDOMStorageContext()->SetSaveSessionStorageOnDisk();
550 // Creation has been finished.
551 if (delegate_)
552 delegate_->OnProfileCreated(this, true, IsNewProfile());
554 content::NotificationService::current()->Notify(
555 chrome::NOTIFICATION_PROFILE_CREATED,
556 content::Source<Profile>(this),
557 content::NotificationService::NoDetails());
559 #if !defined(OS_CHROMEOS)
560 // Listen for bookmark model load, to bootstrap the sync service.
561 // On CrOS sync service will be initialized after sign in.
562 if (!g_browser_process->profile_manager()->will_import()) {
563 // If |will_import()| is true we add the observer in
564 // ProfileManager::OnImportFinished().
565 BookmarkModel* model = BookmarkModelFactory::GetForProfile(this);
566 model->AddObserver(new BookmarkModelLoadedObserver(this));
568 #endif
571 void ProfileImpl::InitHostZoomMap() {
572 HostZoomMap* host_zoom_map = HostZoomMap::GetForBrowserContext(this);
573 host_zoom_map->SetDefaultZoomLevel(
574 prefs_->GetDouble(prefs::kDefaultZoomLevel));
576 const DictionaryValue* host_zoom_dictionary =
577 prefs_->GetDictionary(prefs::kPerHostZoomLevels);
578 // Careful: The returned value could be NULL if the pref has never been set.
579 if (host_zoom_dictionary != NULL) {
580 for (DictionaryValue::Iterator i(*host_zoom_dictionary); !i.IsAtEnd();
581 i.Advance()) {
582 const std::string& host(i.key());
583 double zoom_level = 0;
585 bool success = i.value().GetAsDouble(&zoom_level);
586 DCHECK(success);
587 host_zoom_map->SetZoomLevelForHost(host, zoom_level);
591 host_zoom_map->AddZoomLevelChangedCallback(zoom_callback_);
594 base::FilePath ProfileImpl::last_selected_directory() {
595 return GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory);
598 void ProfileImpl::set_last_selected_directory(const base::FilePath& path) {
599 GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory, path);
602 ProfileImpl::~ProfileImpl() {
603 MaybeSendDestroyedNotification();
605 HostZoomMap::GetForBrowserContext(this)->RemoveZoomLevelChangedCallback(
606 zoom_callback_);
608 bool prefs_loaded = prefs_->GetInitializationStatus() !=
609 PrefService::INITIALIZATION_STATUS_WAITING;
611 #if defined(ENABLE_SESSION_SERVICE)
612 StopCreateSessionServiceTimer();
613 #endif
615 // Remove pref observers
616 pref_change_registrar_.RemoveAll();
618 #if defined(ENABLE_PLUGINS)
619 ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext(
620 io_data_.GetResourceContextNoInit());
621 #endif
623 // Destroy OTR profile and its profile services first.
624 if (off_the_record_profile_.get()) {
625 ProfileDestroyer::DestroyOffTheRecordProfileNow(
626 off_the_record_profile_.get());
627 } else {
628 ExtensionPrefValueMapFactory::GetForProfile(this)->
629 ClearAllIncognitoSessionOnlyPreferences();
632 ProfileDependencyManager::GetInstance()->DestroyProfileServices(this);
634 if (top_sites_.get())
635 top_sites_->Shutdown();
637 if (pref_proxy_config_tracker_.get())
638 pref_proxy_config_tracker_->DetachFromPrefService();
640 if (host_content_settings_map_)
641 host_content_settings_map_->ShutdownOnUIThread();
643 #if defined(ENABLE_CONFIGURATION_POLICY) && defined(ENABLE_MANAGED_USERS)
644 if (managed_mode_policy_provider_)
645 managed_mode_policy_provider_->Shutdown();
646 #endif
648 // This causes the Preferences file to be written to disk.
649 if (prefs_loaded)
650 SetExitType(EXIT_NORMAL);
653 std::string ProfileImpl::GetProfileName() {
654 return GetPrefs()->GetString(prefs::kGoogleServicesUsername);
657 base::FilePath ProfileImpl::GetPath() {
658 return path_;
661 scoped_refptr<base::SequencedTaskRunner> ProfileImpl::GetIOTaskRunner() {
662 return JsonPrefStore::GetTaskRunnerForFile(
663 GetPath(), BrowserThread::GetBlockingPool());
666 bool ProfileImpl::IsOffTheRecord() const {
667 return false;
670 Profile* ProfileImpl::GetOffTheRecordProfile() {
671 if (!off_the_record_profile_.get()) {
672 scoped_ptr<Profile> p(CreateOffTheRecordProfile());
673 off_the_record_profile_.swap(p);
675 content::NotificationService::current()->Notify(
676 chrome::NOTIFICATION_PROFILE_CREATED,
677 content::Source<Profile>(off_the_record_profile_.get()),
678 content::NotificationService::NoDetails());
680 return off_the_record_profile_.get();
683 void ProfileImpl::DestroyOffTheRecordProfile() {
684 off_the_record_profile_.reset();
685 ExtensionPrefValueMapFactory::GetForProfile(this)->
686 ClearAllIncognitoSessionOnlyPreferences();
689 bool ProfileImpl::HasOffTheRecordProfile() {
690 return off_the_record_profile_.get() != NULL;
693 Profile* ProfileImpl::GetOriginalProfile() {
694 return this;
697 ExtensionService* ProfileImpl::GetExtensionService() {
698 return extensions::ExtensionSystem::Get(this)->extension_service();
701 ExtensionSpecialStoragePolicy*
702 ProfileImpl::GetExtensionSpecialStoragePolicy() {
703 if (!extension_special_storage_policy_.get()) {
704 extension_special_storage_policy_ = new ExtensionSpecialStoragePolicy(
705 CookieSettings::Factory::GetForProfile(this));
707 return extension_special_storage_policy_.get();
710 void ProfileImpl::OnPrefsLoaded(bool success) {
711 if (!success) {
712 if (delegate_)
713 delegate_->OnProfileCreated(this, false, false);
714 return;
717 // TODO(mirandac): remove migration code after 6 months (crbug.com/69995).
718 if (g_browser_process->local_state())
719 chrome::MigrateBrowserPrefs(this, g_browser_process->local_state());
720 // TODO(ivankr): remove cleanup code eventually (crbug.com/165672).
721 chrome::MigrateUserPrefs(this);
723 // |kSessionExitType| was added after |kSessionExitedCleanly|. If the pref
724 // value is empty fallback to checking for |kSessionExitedCleanly|.
725 const std::string exit_type_pref_value(
726 prefs_->GetString(prefs::kSessionExitType));
727 if (exit_type_pref_value.empty()) {
728 last_session_exit_type_ =
729 prefs_->GetBoolean(prefs::kSessionExitedCleanly) ?
730 EXIT_NORMAL : EXIT_CRASHED;
731 } else {
732 last_session_exit_type_ =
733 SessionTypePrefValueToExitType(exit_type_pref_value);
735 // Mark the session as open.
736 prefs_->SetString(prefs::kSessionExitType, kPrefExitTypeCrashed);
737 // Force this to true in case we fallback and use it.
738 // TODO(sky): remove this in a couple of releases (m28ish).
739 prefs_->SetBoolean(prefs::kSessionExitedCleanly, true);
741 ProfileDependencyManager::GetInstance()->CreateProfileServices(this, false);
743 DCHECK(!net_pref_observer_.get());
744 net_pref_observer_.reset(new NetPrefObserver(
745 prefs_.get(),
746 prerender::PrerenderManagerFactory::GetForProfile(this),
747 predictor_));
749 ChromeVersionService::OnProfileLoaded(prefs_.get(), IsNewProfile());
750 DoFinalInit();
753 bool ProfileImpl::WasCreatedByVersionOrLater(const std::string& version) {
754 Version profile_version(ChromeVersionService::GetVersion(prefs_.get()));
755 Version arg_version(version);
756 return (profile_version.CompareTo(arg_version) >= 0);
759 void ProfileImpl::SetExitType(ExitType exit_type) {
760 if (!prefs_)
761 return;
762 ExitType current_exit_type = SessionTypePrefValueToExitType(
763 prefs_->GetString(prefs::kSessionExitType));
764 // This may be invoked multiple times during shutdown. Only persist the value
765 // first passed in (unless it's a reset to the crash state, which happens when
766 // foregrounding the app on mobile).
767 if (exit_type == EXIT_CRASHED || current_exit_type == EXIT_CRASHED) {
768 prefs_->SetString(prefs::kSessionExitType,
769 ExitTypeToSessionTypePrefValue(exit_type));
771 // NOTE: If you change what thread this writes on, be sure and update
772 // ChromeFrame::EndSession().
773 prefs_->CommitPendingWrite();
777 Profile::ExitType ProfileImpl::GetLastSessionExitType() {
778 // last_session_exited_cleanly_ is set when the preferences are loaded. Force
779 // it to be set by asking for the prefs.
780 GetPrefs();
781 return last_session_exit_type_;
784 policy::ManagedModePolicyProvider* ProfileImpl::GetManagedModePolicyProvider() {
785 #if defined(ENABLE_CONFIGURATION_POLICY) && defined(ENABLE_MANAGED_USERS)
786 return managed_mode_policy_provider_.get();
787 #else
788 return NULL;
789 #endif
792 policy::PolicyService* ProfileImpl::GetPolicyService() {
793 DCHECK(policy_service_.get()); // Should explicitly be initialized.
794 return policy_service_.get();
797 PrefService* ProfileImpl::GetPrefs() {
798 DCHECK(prefs_.get()); // Should explicitly be initialized.
799 return prefs_.get();
802 PrefService* ProfileImpl::GetOffTheRecordPrefs() {
803 DCHECK(prefs_.get());
804 if (!otr_prefs_.get()) {
805 // The new ExtensionPrefStore is ref_counted and the new PrefService
806 // stores a reference so that we do not leak memory here.
807 otr_prefs_.reset(prefs_->CreateIncognitoPrefService(
808 new ExtensionPrefStore(
809 ExtensionPrefValueMapFactory::GetForProfile(this), true)));
811 return otr_prefs_.get();
814 base::FilePath ProfileImpl::GetPrefFilePath() {
815 base::FilePath pref_file_path = path_;
816 pref_file_path = pref_file_path.Append(chrome::kPreferencesFilename);
817 return pref_file_path;
820 net::URLRequestContextGetter* ProfileImpl::CreateRequestContext(
821 content::ProtocolHandlerMap* protocol_handlers) {
822 return io_data_.CreateMainRequestContextGetter(
823 protocol_handlers,
824 g_browser_process->local_state(),
825 g_browser_process->io_thread());
828 net::URLRequestContextGetter* ProfileImpl::GetRequestContext() {
829 return GetDefaultStoragePartition(this)->GetURLRequestContext();
832 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForRenderProcess(
833 int renderer_child_id) {
834 content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
835 renderer_child_id);
837 return rph->GetStoragePartition()->GetURLRequestContext();
840 net::URLRequestContextGetter* ProfileImpl::GetMediaRequestContext() {
841 // Return the default media context.
842 return io_data_.GetMediaRequestContextGetter();
845 net::URLRequestContextGetter*
846 ProfileImpl::GetMediaRequestContextForRenderProcess(
847 int renderer_child_id) {
848 content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
849 renderer_child_id);
850 content::StoragePartition* storage_partition = rph->GetStoragePartition();
852 return storage_partition->GetMediaURLRequestContext();
855 net::URLRequestContextGetter*
856 ProfileImpl::GetMediaRequestContextForStoragePartition(
857 const base::FilePath& partition_path,
858 bool in_memory) {
859 return io_data_.GetIsolatedMediaRequestContextGetter(partition_path,
860 in_memory);
863 content::ResourceContext* ProfileImpl::GetResourceContext() {
864 return io_data_.GetResourceContext();
867 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() {
868 return io_data_.GetExtensionsRequestContextGetter();
871 net::URLRequestContextGetter*
872 ProfileImpl::CreateRequestContextForStoragePartition(
873 const base::FilePath& partition_path,
874 bool in_memory,
875 content::ProtocolHandlerMap* protocol_handlers) {
876 return io_data_.CreateIsolatedAppRequestContextGetter(
877 partition_path, in_memory, protocol_handlers);
880 net::SSLConfigService* ProfileImpl::GetSSLConfigService() {
881 // If ssl_config_service_manager_ is null, this typically means that some
882 // ProfileKeyedService is trying to create a RequestContext at startup, but
883 // SSLConfigServiceManager is not initialized until DoFinalInit() which is
884 // invoked after all ProfileKeyedServices have been initialized (see
885 // http://crbug.com/171406).
886 DCHECK(ssl_config_service_manager_.get()) <<
887 "SSLConfigServiceManager is not initialized yet";
888 return ssl_config_service_manager_->Get();
891 HostContentSettingsMap* ProfileImpl::GetHostContentSettingsMap() {
892 if (!host_content_settings_map_.get()) {
893 host_content_settings_map_ = new HostContentSettingsMap(GetPrefs(), false);
895 return host_content_settings_map_.get();
898 content::GeolocationPermissionContext*
899 ProfileImpl::GetGeolocationPermissionContext() {
900 return ChromeGeolocationPermissionContextFactory::GetForProfile(this);
903 content::SpeechRecognitionPreferences*
904 ProfileImpl::GetSpeechRecognitionPreferences() {
905 #if defined(ENABLE_INPUT_SPEECH)
906 return ChromeSpeechRecognitionPreferences::GetForProfile(this);
907 #else
908 return NULL;
909 #endif
912 DownloadManagerDelegate* ProfileImpl::GetDownloadManagerDelegate() {
913 return DownloadServiceFactory::GetForProfile(this)->
914 GetDownloadManagerDelegate();
917 quota::SpecialStoragePolicy* ProfileImpl::GetSpecialStoragePolicy() {
918 return GetExtensionSpecialStoragePolicy();
921 bool ProfileImpl::IsSameProfile(Profile* profile) {
922 if (profile == static_cast<Profile*>(this))
923 return true;
924 Profile* otr_profile = off_the_record_profile_.get();
925 return otr_profile && profile == otr_profile;
928 Time ProfileImpl::GetStartTime() const {
929 return start_time_;
932 history::TopSites* ProfileImpl::GetTopSites() {
933 if (!top_sites_.get()) {
934 top_sites_ = new history::TopSites(this);
935 top_sites_->Init(GetPath().Append(chrome::kTopSitesFilename));
937 return top_sites_;
940 history::TopSites* ProfileImpl::GetTopSitesWithoutCreating() {
941 return top_sites_;
944 void ProfileImpl::OnDefaultZoomLevelChanged() {
945 HostZoomMap::GetForBrowserContext(this)->SetDefaultZoomLevel(
946 pref_change_registrar_.prefs()->GetDouble(prefs::kDefaultZoomLevel));
949 void ProfileImpl::OnZoomLevelChanged(
950 const HostZoomMap::ZoomLevelChange& change) {
952 if (change.mode != HostZoomMap::ZOOM_CHANGED_FOR_HOST)
953 return;
954 HostZoomMap* host_zoom_map = HostZoomMap::GetForBrowserContext(this);
955 double level = change.zoom_level;
956 DictionaryPrefUpdate update(prefs_.get(), prefs::kPerHostZoomLevels);
957 DictionaryValue* host_zoom_dictionary = update.Get();
958 if (level == host_zoom_map->GetDefaultZoomLevel()) {
959 host_zoom_dictionary->RemoveWithoutPathExpansion(change.host, NULL);
960 } else {
961 host_zoom_dictionary->SetWithoutPathExpansion(
962 change.host, Value::CreateDoubleValue(level));
966 #if defined(ENABLE_SESSION_SERVICE)
967 void ProfileImpl::StopCreateSessionServiceTimer() {
968 create_session_service_timer_.Stop();
971 void ProfileImpl::EnsureSessionServiceCreated() {
972 SessionServiceFactory::GetForProfile(this);
974 #endif
976 #if defined(OS_CHROMEOS)
977 void ProfileImpl::ChangeAppLocale(
978 const std::string& new_locale, AppLocaleChangedVia via) {
979 if (new_locale.empty()) {
980 NOTREACHED();
981 return;
983 PrefService* local_state = g_browser_process->local_state();
984 DCHECK(local_state);
985 if (local_state->IsManagedPreference(prefs::kApplicationLocale))
986 return;
987 std::string pref_locale = GetPrefs()->GetString(prefs::kApplicationLocale);
988 bool do_update_pref = true;
989 switch (via) {
990 case APP_LOCALE_CHANGED_VIA_SETTINGS:
991 case APP_LOCALE_CHANGED_VIA_REVERT: {
992 // We keep kApplicationLocaleBackup value as a reference. In case value
993 // of kApplicationLocale preference would change due to sync from other
994 // device then kApplicationLocaleBackup value will trigger and allow us to
995 // show notification about automatic locale change in LocaleChangeGuard.
996 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
997 GetPrefs()->ClearPref(prefs::kApplicationLocaleAccepted);
998 // We maintain kApplicationLocale property in both a global storage
999 // and user's profile. Global property determines locale of login screen,
1000 // while user's profile determines his personal locale preference.
1001 break;
1003 case APP_LOCALE_CHANGED_VIA_LOGIN: {
1004 if (!pref_locale.empty()) {
1005 DCHECK(pref_locale == new_locale);
1006 std::string accepted_locale =
1007 GetPrefs()->GetString(prefs::kApplicationLocaleAccepted);
1008 if (accepted_locale == new_locale) {
1009 // If locale is accepted then we do not want to show LocaleChange
1010 // notification. This notification is triggered by different values
1011 // of kApplicationLocaleBackup and kApplicationLocale preferences,
1012 // so make them identical.
1013 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, new_locale);
1014 } else {
1015 // Back up locale of login screen.
1016 std::string cur_locale = g_browser_process->GetApplicationLocale();
1017 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
1018 if (locale_change_guard_ == NULL)
1019 locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this));
1020 locale_change_guard_->PrepareChangingLocale(cur_locale, new_locale);
1022 } else {
1023 std::string cur_locale = g_browser_process->GetApplicationLocale();
1024 std::string backup_locale =
1025 GetPrefs()->GetString(prefs::kApplicationLocaleBackup);
1026 // Profile synchronization takes time and is not completed at that
1027 // moment at first login. So we initialize locale preference in steps:
1028 // (1) first save it to temporary backup;
1029 // (2) on next login we assume that synchronization is already completed
1030 // and we may finalize initialization.
1031 GetPrefs()->SetString(prefs::kApplicationLocaleBackup, cur_locale);
1032 if (!backup_locale.empty())
1033 GetPrefs()->SetString(prefs::kApplicationLocale, backup_locale);
1034 do_update_pref = false;
1036 break;
1038 case APP_LOCALE_CHANGED_VIA_UNKNOWN:
1039 default: {
1040 NOTREACHED();
1041 break;
1044 if (do_update_pref)
1045 GetPrefs()->SetString(prefs::kApplicationLocale, new_locale);
1046 local_state->SetString(prefs::kApplicationLocale, new_locale);
1048 if (chromeos::UserManager::Get()->IsCurrentUserOwner())
1049 local_state->SetString(prefs::kOwnerLocale, new_locale);
1052 void ProfileImpl::OnLogin() {
1053 if (locale_change_guard_ == NULL)
1054 locale_change_guard_.reset(new chromeos::LocaleChangeGuard(this));
1055 locale_change_guard_->OnLogin();
1058 void ProfileImpl::SetupChromeOSEnterpriseExtensionObserver() {
1059 DCHECK(!chromeos_enterprise_extension_observer_.get());
1060 chromeos_enterprise_extension_observer_.reset(
1061 new chromeos::EnterpriseExtensionObserver(this));
1064 void ProfileImpl::InitChromeOSPreferences() {
1065 chromeos_preferences_.reset(new chromeos::Preferences());
1066 chromeos_preferences_->Init(PrefServiceSyncable::FromProfile(this));
1068 #endif // defined(OS_CHROMEOS)
1070 PrefProxyConfigTracker* ProfileImpl::GetProxyConfigTracker() {
1071 if (!pref_proxy_config_tracker_.get()) {
1072 pref_proxy_config_tracker_.reset(
1073 ProxyServiceFactory::CreatePrefProxyConfigTracker(GetPrefs()));
1075 return pref_proxy_config_tracker_.get();
1078 chrome_browser_net::Predictor* ProfileImpl::GetNetworkPredictor() {
1079 return predictor_;
1082 void ProfileImpl::ClearNetworkingHistorySince(base::Time time,
1083 const base::Closure& completion) {
1084 io_data_.ClearNetworkingHistorySince(time, completion);
1087 GURL ProfileImpl::GetHomePage() {
1088 // --homepage overrides any preferences.
1089 const CommandLine& command_line = *CommandLine::ForCurrentProcess();
1090 if (command_line.HasSwitch(switches::kHomePage)) {
1091 // TODO(evanm): clean up usage of DIR_CURRENT.
1092 // http://code.google.com/p/chromium/issues/detail?id=60630
1093 // For now, allow this code to call getcwd().
1094 base::ThreadRestrictions::ScopedAllowIO allow_io;
1096 base::FilePath browser_directory;
1097 PathService::Get(base::DIR_CURRENT, &browser_directory);
1098 GURL home_page(URLFixerUpper::FixupRelativeFile(browser_directory,
1099 command_line.GetSwitchValuePath(switches::kHomePage)));
1100 if (home_page.is_valid())
1101 return home_page;
1104 if (GetPrefs()->GetBoolean(prefs::kHomePageIsNewTabPage))
1105 return GURL(chrome::kChromeUINewTabURL);
1106 GURL home_page(URLFixerUpper::FixupURL(
1107 GetPrefs()->GetString(prefs::kHomePage),
1108 std::string()));
1109 if (!home_page.is_valid())
1110 return GURL(chrome::kChromeUINewTabURL);
1111 return home_page;
1114 void ProfileImpl::UpdateProfileUserNameCache() {
1115 ProfileManager* profile_manager = g_browser_process->profile_manager();
1116 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1117 size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1118 if (index != std::string::npos) {
1119 std::string user_name =
1120 GetPrefs()->GetString(prefs::kGoogleServicesUsername);
1121 cache.SetUserNameOfProfileAtIndex(index, UTF8ToUTF16(user_name));
1125 void ProfileImpl::UpdateProfileNameCache() {
1126 ProfileManager* profile_manager = g_browser_process->profile_manager();
1127 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1128 size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1129 if (index != std::string::npos) {
1130 std::string profile_name =
1131 GetPrefs()->GetString(prefs::kProfileName);
1132 cache.SetNameOfProfileAtIndex(index, UTF8ToUTF16(profile_name));
1136 void ProfileImpl::UpdateProfileAvatarCache() {
1137 ProfileManager* profile_manager = g_browser_process->profile_manager();
1138 ProfileInfoCache& cache = profile_manager->GetProfileInfoCache();
1139 size_t index = cache.GetIndexOfProfileWithPath(GetPath());
1140 if (index != std::string::npos) {
1141 size_t avatar_index =
1142 GetPrefs()->GetInteger(prefs::kProfileAvatarIndex);
1143 cache.SetAvatarIconOfProfileAtIndex(index, avatar_index);
1147 // Gets the cache parameters from the command line. If |is_media_context| is
1148 // set to true then settings for the media context type is what we need,
1149 // |cache_path| will be set to the user provided path, or will not be touched if
1150 // there is not an argument. |max_size| will be the user provided value or zero
1151 // by default.
1152 void ProfileImpl::GetCacheParameters(bool is_media_context,
1153 base::FilePath* cache_path,
1154 int* max_size) {
1155 DCHECK(cache_path);
1156 DCHECK(max_size);
1157 base::FilePath path(prefs_->GetFilePath(prefs::kDiskCacheDir));
1158 if (!path.empty())
1159 *cache_path = path;
1160 *max_size = is_media_context ? prefs_->GetInteger(prefs::kMediaCacheSize) :
1161 prefs_->GetInteger(prefs::kDiskCacheSize);