Home | History | Annotate | Download | only in profiles
      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.
    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 
    168 FilePath GetCachePath(const FilePath& base) {
    169   return base.Append(chrome::kCacheDirname);
    170 }
    171 
    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:
    179   explicit ProfileSizeTask(const FilePath& path) : path_(path) {}
    180   virtual ~ProfileSizeTask() {}
    181 
    182   virtual void Run();
    183  private:
    184   FilePath path_;
    185 };
    186 
    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
    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
    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
    257 void ProfileImpl::RegisterUserPrefs(PrefService* prefs) {
    258   prefs->RegisterBooleanPref(prefs::kSavingBrowserHistoryDisabled, false);
    259   prefs->RegisterBooleanPref(prefs::kClearSiteDataOnExit, false);
    260 }
    261 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    569 FilePath ProfileImpl::last_selected_directory() {
    570   return GetPrefs()->GetFilePath(prefs::kSelectFileLastDirectory);
    571 }
    572 
    573 void ProfileImpl::set_last_selected_directory(const FilePath& path) {
    574   GetPrefs()->SetFilePath(prefs::kSelectFileLastDirectory, path);
    575 }
    576 
    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 
    664 ProfileId ProfileImpl::GetRuntimeId() {
    665   return reinterpret_cast<ProfileId>(this);
    666 }
    667 
    668 FilePath ProfileImpl::GetPath() {
    669   return path_;
    670 }
    671 
    672 bool ProfileImpl::IsOffTheRecord() {
    673   return false;
    674 }
    675 
    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 
    689 void ProfileImpl::DestroyOffTheRecordProfile() {
    690   off_the_record_profile_.reset();
    691 }
    692 
    693 bool ProfileImpl::HasOffTheRecordProfile() {
    694   return off_the_record_profile_.get() != NULL;
    695 }
    696 
    697 Profile* ProfileImpl::GetOriginalProfile() {
    698   return this;
    699 }
    700 
    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 
    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 
    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 
    738 ExtensionService* ProfileImpl::GetExtensionService() {
    739   return extensions_service_.get();
    740 }
    741 
    742 StatusTray* ProfileImpl::GetStatusTray() {
    743   if (!status_tray_.get())
    744     status_tray_.reset(StatusTray::Create());
    745   return status_tray_.get();
    746 }
    747 
    748 UserScriptMaster* ProfileImpl::GetUserScriptMaster() {
    749   return user_script_master_.get();
    750 }
    751 
    752 ExtensionDevToolsManager* ProfileImpl::GetExtensionDevToolsManager() {
    753   return extension_devtools_manager_.get();
    754 }
    755 
    756 ExtensionProcessManager* ProfileImpl::GetExtensionProcessManager() {
    757   return extension_process_manager_.get();
    758 }
    759 
    760 ExtensionMessageService* ProfileImpl::GetExtensionMessageService() {
    761   return extension_message_service_.get();
    762 }
    763 
    764 ExtensionEventRouter* ProfileImpl::GetExtensionEventRouter() {
    765   return extension_event_router_.get();
    766 }
    767 
    768 ExtensionSpecialStoragePolicy*
    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 
    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*
    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 
    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 
    838 PrefService* ProfileImpl::GetPrefs() {
    839   DCHECK(prefs_.get());  // Should explicitly be initialized.
    840   return prefs_.get();
    841 }
    842 
    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 
    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 
    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 
    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 
    889 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForMedia() {
    890   return io_data_.GetMediaRequestContextGetter();
    891 }
    892 
    893 const content::ResourceContext& ProfileImpl::GetResourceContext() {
    894   return io_data_.GetResourceContext();
    895 }
    896 
    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 
    906 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForExtensions() {
    907   return io_data_.GetExtensionsRequestContextGetter();
    908 }
    909 
    910 net::URLRequestContextGetter* ProfileImpl::GetRequestContextForIsolatedApp(
    911     const std::string& app_id) {
    912   return io_data_.GetIsolatedAppRequestContextGetter(app_id);
    913 }
    914 
    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 
    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 
    935 net::SSLConfigService* ProfileImpl::GetSSLConfigService() {
    936   return ssl_config_service_manager_->Get();
    937 }
    938 
    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 
    945 HostZoomMap* ProfileImpl::GetHostZoomMap() {
    946   if (!host_zoom_map_)
    947     host_zoom_map_ = new HostZoomMap(this);
    948   return host_zoom_map_.get();
    949 }
    950 
    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 
    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 
    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 
    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 
    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 
    999 HistoryService* ProfileImpl::GetHistoryServiceWithoutCreating() {
   1000   return history_service_.get();
   1001 }
   1002 
   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 
   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 
   1015 AutocompleteClassifier* ProfileImpl::GetAutocompleteClassifier() {
   1016   if (!autocomplete_classifier_.get())
   1017     autocomplete_classifier_.reset(new AutocompleteClassifier(this));
   1018   return autocomplete_classifier_.get();
   1019 }
   1020 
   1021 WebDataService* ProfileImpl::GetWebDataService(ServiceAccessType sat) {
   1022   if (!created_web_data_service_)
   1023     CreateWebDataService();
   1024   return web_data_service_.get();
   1025 }
   1026 
   1027 WebDataService* ProfileImpl::GetWebDataServiceWithoutCreating() {
   1028   return web_data_service_.get();
   1029 }
   1030 
   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 
   1040 PasswordStore* ProfileImpl::GetPasswordStore(ServiceAccessType sat) {
   1041   if (!created_password_store_)
   1042     CreatePasswordStore();
   1043   return password_store_.get();
   1044 }
   1045 
   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 
   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 
   1145 bool ProfileImpl::HasCreatedDownloadManager() const {
   1146   return created_download_manager_;
   1147 }
   1148 
   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 
   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 
   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 
   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 
   1185 bool ProfileImpl::HasSessionService() const {
   1186   return (session_service_.get() != NULL);
   1187 }
   1188 
   1189 bool ProfileImpl::HasProfileSyncService() const {
   1190   return (sync_service_.get() != NULL);
   1191 }
   1192 
   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 
   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 
   1208 ProtocolHandlerRegistry* ProfileImpl::GetProtocolHandlerRegistry() {
   1209   return protocol_handler_registry_.get();
   1210 }
   1211 
   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 
   1219 Time ProfileImpl::GetStartTime() const {
   1220   return start_time_;
   1221 }
   1222 
   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 
   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 
   1237 history::TopSites* ProfileImpl::GetTopSitesWithoutCreating() {
   1238   return top_sites_;
   1239 }
   1240 
   1241 void ProfileImpl::ResetTabRestoreService() {
   1242   tab_restore_service_ = NULL;
   1243 }
   1244 
   1245 SpellCheckHost* ProfileImpl::GetSpellCheckHost() {
   1246   return spellcheck_host_ready_ ? spellcheck_host_.get() : NULL;
   1247 }
   1248 
   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 
   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 
   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 
   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 
   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 
   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 
   1346 void ProfileImpl::StopCreateSessionServiceTimer() {
   1347   create_session_service_timer_.Stop();
   1348 }
   1349 
   1350 TokenService* ProfileImpl::GetTokenService() {
   1351   if (!token_service_.get()) {
   1352     token_service_.reset(new TokenService());
   1353   }
   1354   return token_service_.get();
   1355 }
   1356 
   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 
   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 
   1381 BrowserSignin* ProfileImpl::GetBrowserSignin() {
   1382   if (!browser_signin_.get()) {
   1383     browser_signin_.reset(new BrowserSignin(this));
   1384   }
   1385   return browser_signin_.get();
   1386 }
   1387 
   1388 CloudPrintProxyService* ProfileImpl::GetCloudPrintProxyService() {
   1389   if (!cloud_print_proxy_service_.get())
   1390     InitCloudPrintProxyService();
   1391   return cloud_print_proxy_service_.get();
   1392 }
   1393 
   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 
   1402 void ProfileImpl::InitCloudPrintProxyService() {
   1403   cloud_print_proxy_service_ = new CloudPrintProxyService(this);
   1404   cloud_print_proxy_service_->Initialize();
   1405 }
   1406 
   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 
   1418 ExtensionInfoMap* ProfileImpl::GetExtensionInfoMap() {
   1419   return extension_info_map_.get();
   1420 }
   1421 
   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 
   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 
   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)
   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 
   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 
   1542 void ProfileImpl::SetupChromeOSEnterpriseExtensionObserver() {
   1543   DCHECK(!chromeos_enterprise_extension_observer_.get());
   1544   chromeos_enterprise_extension_observer_.reset(
   1545       new chromeos::EnterpriseExtensionObserver(this));
   1546 }
   1547 
   1548 void ProfileImpl::InitChromeOSPreferences() {
   1549   chromeos_preferences_.reset(new chromeos::Preferences());
   1550   chromeos_preferences_->Init(GetPrefs());
   1551 }
   1552 #endif  // defined(OS_CHROMEOS)
   1553 
   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 
   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