• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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