Home | History | Annotate | Download | only in profiles
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/profiles/off_the_record_profile_impl.h"
      6 
      7 #include "base/bind.h"
      8 #include "base/command_line.h"
      9 #include "base/compiler_specific.h"
     10 #include "base/files/file_path.h"
     11 #include "base/memory/scoped_ptr.h"
     12 #include "base/path_service.h"
     13 #include "base/prefs/json_pref_store.h"
     14 #include "base/strings/string_number_conversions.h"
     15 #include "base/strings/string_util.h"
     16 #include "build/build_config.h"
     17 #include "chrome/browser/background/background_contents_service_factory.h"
     18 #include "chrome/browser/browser_process.h"
     19 #include "chrome/browser/content_settings/host_content_settings_map.h"
     20 #include "chrome/browser/dom_distiller/profile_utils.h"
     21 #include "chrome/browser/download/chrome_download_manager_delegate.h"
     22 #include "chrome/browser/download/download_service.h"
     23 #include "chrome/browser/download/download_service_factory.h"
     24 #include "chrome/browser/extensions/extension_service.h"
     25 #include "chrome/browser/extensions/extension_special_storage_policy.h"
     26 #include "chrome/browser/io_thread.h"
     27 #include "chrome/browser/net/chrome_url_request_context_getter.h"
     28 #include "chrome/browser/net/pref_proxy_config_tracker.h"
     29 #include "chrome/browser/net/proxy_service_factory.h"
     30 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
     31 #include "chrome/browser/plugins/plugin_prefs.h"
     32 #include "chrome/browser/prefs/incognito_mode_prefs.h"
     33 #include "chrome/browser/prefs/pref_service_syncable.h"
     34 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate.h"
     35 #include "chrome/browser/ssl/chrome_ssl_host_state_delegate_factory.h"
     36 #include "chrome/browser/themes/theme_service.h"
     37 #include "chrome/browser/ui/webui/extensions/extension_icon_source.h"
     38 #include "chrome/common/chrome_constants.h"
     39 #include "chrome/common/chrome_paths.h"
     40 #include "chrome/common/chrome_switches.h"
     41 #include "chrome/common/pref_names.h"
     42 #include "chrome/common/render_messages.h"
     43 #include "components/keyed_service/content/browser_context_dependency_manager.h"
     44 #include "components/user_prefs/user_prefs.h"
     45 #include "content/public/browser/browser_thread.h"
     46 #include "content/public/browser/host_zoom_map.h"
     47 #include "content/public/browser/render_process_host.h"
     48 #include "content/public/browser/storage_partition.h"
     49 #include "content/public/browser/url_data_source.h"
     50 #include "content/public/browser/web_contents.h"
     51 #include "net/http/http_server_properties.h"
     52 #include "net/http/transport_security_state.h"
     53 #include "storage/browser/database/database_tracker.h"
     54 
     55 #if defined(OS_ANDROID)
     56 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
     57 #include "chrome/browser/media/protected_media_identifier_permission_context_factory.h"
     58 #endif  // defined(OS_ANDROID)
     59 
     60 #if defined(OS_ANDROID) || defined(OS_IOS)
     61 #include "base/prefs/scoped_user_pref_update.h"
     62 #include "chrome/browser/prefs/proxy_prefs.h"
     63 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
     64 
     65 #if defined(OS_CHROMEOS)
     66 #include "chrome/browser/chromeos/preferences.h"
     67 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     68 #endif
     69 
     70 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS)
     71 #include "chrome/browser/policy/cloud/user_cloud_policy_manager_factory.h"
     72 #endif
     73 
     74 #if defined(ENABLE_EXTENSIONS)
     75 #include "extensions/browser/api/web_request/web_request_api.h"
     76 #include "extensions/browser/extension_system.h"
     77 #include "extensions/browser/guest_view/guest_view_manager.h"
     78 #include "extensions/common/extension.h"
     79 #endif
     80 
     81 using content::BrowserThread;
     82 using content::DownloadManagerDelegate;
     83 using content::HostZoomMap;
     84 
     85 #if defined(ENABLE_EXTENSIONS)
     86 namespace {
     87 
     88 void NotifyOTRProfileCreatedOnIOThread(void* original_profile,
     89                                        void* otr_profile) {
     90   ExtensionWebRequestEventRouter::GetInstance()->OnOTRBrowserContextCreated(
     91       original_profile, otr_profile);
     92 }
     93 
     94 void NotifyOTRProfileDestroyedOnIOThread(void* original_profile,
     95                                          void* otr_profile) {
     96   ExtensionWebRequestEventRouter::GetInstance()->OnOTRBrowserContextDestroyed(
     97       original_profile, otr_profile);
     98 }
     99 
    100 }  // namespace
    101 #endif
    102 
    103 OffTheRecordProfileImpl::OffTheRecordProfileImpl(Profile* real_profile)
    104     : profile_(real_profile),
    105       prefs_(PrefServiceSyncable::IncognitoFromProfile(real_profile)),
    106       start_time_(Time::Now()) {
    107   // Register on BrowserContext.
    108   user_prefs::UserPrefs::Set(this, prefs_);
    109 }
    110 
    111 void OffTheRecordProfileImpl::Init() {
    112   // The construction of OffTheRecordProfileIOData::Handle needs the profile
    113   // type returned by this->GetProfileType().  Since GetProfileType() is a
    114   // virtual member function, we cannot call the function defined in the most
    115   // derived class (e.g. GuestSessionProfile) until a ctor finishes.  Thus,
    116   // we have to instantiate OffTheRecordProfileIOData::Handle here after a ctor.
    117   InitIoData();
    118 
    119 #if defined(ENABLE_CONFIGURATION_POLICY) && !defined(OS_CHROMEOS)
    120   // Because UserCloudPolicyManager is in a component, it cannot access
    121   // GetOriginalProfile. Instead, we have to inject this relation here.
    122   policy::UserCloudPolicyManagerFactory::RegisterForOffTheRecordBrowserContext(
    123       this->GetOriginalProfile(), this);
    124 #endif
    125 
    126   BrowserContextDependencyManager::GetInstance()->CreateBrowserContextServices(
    127       this);
    128 
    129   // Guest profiles may always be OTR. Check IncognitoModePrefs otherwise.
    130   DCHECK(profile_->IsGuestSession() ||
    131          IncognitoModePrefs::GetAvailability(profile_->GetPrefs()) !=
    132              IncognitoModePrefs::DISABLED);
    133 
    134 #if defined(OS_ANDROID) || defined(OS_IOS)
    135   UseSystemProxy();
    136 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
    137 
    138   // TODO(oshima): Remove the need to eagerly initialize the request context
    139   // getter. chromeos::OnlineAttempt is illegally trying to access this
    140   // Profile member from a thread other than the UI thread, so we need to
    141   // prevent a race.
    142 #if defined(OS_CHROMEOS)
    143   GetRequestContext();
    144 #endif  // defined(OS_CHROMEOS)
    145 
    146   InitHostZoomMap();
    147 
    148 #if defined(ENABLE_PLUGINS)
    149   ChromePluginServiceFilter::GetInstance()->RegisterResourceContext(
    150       PluginPrefs::GetForProfile(this).get(),
    151       io_data_->GetResourceContextNoInit());
    152 #endif
    153 
    154 #if defined(ENABLE_EXTENSIONS)
    155   // Make the chrome//extension-icon/ resource available.
    156   extensions::ExtensionIconSource* icon_source =
    157       new extensions::ExtensionIconSource(profile_);
    158   content::URLDataSource::Add(this, icon_source);
    159 
    160   BrowserThread::PostTask(
    161       BrowserThread::IO, FROM_HERE,
    162       base::Bind(&NotifyOTRProfileCreatedOnIOThread, profile_, this));
    163 #endif
    164 
    165   // The DomDistillerViewerSource is not a normal WebUI so it must be registered
    166   // as a URLDataSource early.
    167   RegisterDomDistillerViewerSource(this);
    168 }
    169 
    170 OffTheRecordProfileImpl::~OffTheRecordProfileImpl() {
    171   MaybeSendDestroyedNotification();
    172 
    173 #if defined(ENABLE_PLUGINS)
    174   ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext(
    175       io_data_->GetResourceContextNoInit());
    176 #endif
    177 
    178   BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(
    179       this);
    180 
    181 #if defined(ENABLE_EXTENSIONS)
    182   BrowserThread::PostTask(
    183       BrowserThread::IO, FROM_HERE,
    184       base::Bind(&NotifyOTRProfileDestroyedOnIOThread, profile_, this));
    185 #endif
    186 
    187   if (host_content_settings_map_.get())
    188     host_content_settings_map_->ShutdownOnUIThread();
    189 
    190   if (pref_proxy_config_tracker_)
    191     pref_proxy_config_tracker_->DetachFromPrefService();
    192 
    193   // Clears any data the network stack contains that may be related to the
    194   // OTR session.
    195   g_browser_process->io_thread()->ChangedToOnTheRecord();
    196 }
    197 
    198 void OffTheRecordProfileImpl::InitIoData() {
    199   io_data_.reset(new OffTheRecordProfileIOData::Handle(this));
    200 }
    201 
    202 void OffTheRecordProfileImpl::InitHostZoomMap() {
    203   HostZoomMap* host_zoom_map = HostZoomMap::GetDefaultForBrowserContext(this);
    204   HostZoomMap* parent_host_zoom_map =
    205       HostZoomMap::GetDefaultForBrowserContext(profile_);
    206   host_zoom_map->CopyFrom(parent_host_zoom_map);
    207   // Observe parent's HZM change for propagating change of parent's
    208   // change to this HZM.
    209   zoom_subscription_ = parent_host_zoom_map->AddZoomLevelChangedCallback(
    210       base::Bind(&OffTheRecordProfileImpl::OnZoomLevelChanged,
    211                  base::Unretained(this)));
    212 }
    213 
    214 #if defined(OS_ANDROID) || defined(OS_IOS)
    215 void OffTheRecordProfileImpl::UseSystemProxy() {
    216   // Force the use of the system-assigned proxy when off the record.
    217   const char kProxyMode[] = "mode";
    218   const char kProxyServer[] = "server";
    219   const char kProxyBypassList[] = "bypass_list";
    220   const char kProxyPacUrl[] = "pac_url";
    221   DictionaryPrefUpdate update(prefs_, prefs::kProxy);
    222   base::DictionaryValue* dict = update.Get();
    223   dict->SetString(kProxyMode, ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
    224   dict->SetString(kProxyPacUrl, "");
    225   dict->SetString(kProxyServer, "");
    226   dict->SetString(kProxyBypassList, "");
    227 }
    228 #endif  // defined(OS_ANDROID) || defined(OS_IOS)
    229 
    230 std::string OffTheRecordProfileImpl::GetProfileName() {
    231   // Incognito profile should not return the profile name.
    232   return std::string();
    233 }
    234 
    235 Profile::ProfileType OffTheRecordProfileImpl::GetProfileType() const {
    236   return INCOGNITO_PROFILE;
    237 }
    238 
    239 base::FilePath OffTheRecordProfileImpl::GetPath() const {
    240   return profile_->GetPath();
    241 }
    242 
    243 scoped_refptr<base::SequencedTaskRunner>
    244 OffTheRecordProfileImpl::GetIOTaskRunner() {
    245   return profile_->GetIOTaskRunner();
    246 }
    247 
    248 bool OffTheRecordProfileImpl::IsOffTheRecord() const {
    249   return true;
    250 }
    251 
    252 Profile* OffTheRecordProfileImpl::GetOffTheRecordProfile() {
    253   return this;
    254 }
    255 
    256 void OffTheRecordProfileImpl::DestroyOffTheRecordProfile() {
    257   // Suicide is bad!
    258   NOTREACHED();
    259 }
    260 
    261 bool OffTheRecordProfileImpl::HasOffTheRecordProfile() {
    262   return true;
    263 }
    264 
    265 Profile* OffTheRecordProfileImpl::GetOriginalProfile() {
    266   return profile_;
    267 }
    268 
    269 ExtensionSpecialStoragePolicy*
    270     OffTheRecordProfileImpl::GetExtensionSpecialStoragePolicy() {
    271   return GetOriginalProfile()->GetExtensionSpecialStoragePolicy();
    272 }
    273 
    274 bool OffTheRecordProfileImpl::IsSupervised() {
    275   return GetOriginalProfile()->IsSupervised();
    276 }
    277 
    278 PrefService* OffTheRecordProfileImpl::GetPrefs() {
    279   return prefs_;
    280 }
    281 
    282 PrefService* OffTheRecordProfileImpl::GetOffTheRecordPrefs() {
    283   return prefs_;
    284 }
    285 
    286 DownloadManagerDelegate* OffTheRecordProfileImpl::GetDownloadManagerDelegate() {
    287   return DownloadServiceFactory::GetForBrowserContext(this)->
    288       GetDownloadManagerDelegate();
    289 }
    290 
    291 net::URLRequestContextGetter* OffTheRecordProfileImpl::GetRequestContext() {
    292   return GetDefaultStoragePartition(this)->GetURLRequestContext();
    293 }
    294 
    295 net::URLRequestContextGetter* OffTheRecordProfileImpl::CreateRequestContext(
    296     content::ProtocolHandlerMap* protocol_handlers,
    297     content::URLRequestInterceptorScopedVector request_interceptors) {
    298   return io_data_->CreateMainRequestContextGetter(
    299       protocol_handlers, request_interceptors.Pass()).get();
    300 }
    301 
    302 net::URLRequestContextGetter*
    303     OffTheRecordProfileImpl::GetRequestContextForRenderProcess(
    304         int renderer_child_id) {
    305   content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
    306       renderer_child_id);
    307   return rph->GetStoragePartition()->GetURLRequestContext();
    308 }
    309 
    310 net::URLRequestContextGetter*
    311     OffTheRecordProfileImpl::GetMediaRequestContext() {
    312   // In OTR mode, media request context is the same as the original one.
    313   return GetRequestContext();
    314 }
    315 
    316 net::URLRequestContextGetter*
    317     OffTheRecordProfileImpl::GetMediaRequestContextForRenderProcess(
    318         int renderer_child_id) {
    319   // In OTR mode, media request context is the same as the original one.
    320   return GetRequestContextForRenderProcess(renderer_child_id);
    321 }
    322 
    323 net::URLRequestContextGetter*
    324 OffTheRecordProfileImpl::GetMediaRequestContextForStoragePartition(
    325     const base::FilePath& partition_path,
    326     bool in_memory) {
    327   return io_data_->GetIsolatedAppRequestContextGetter(partition_path, in_memory)
    328       .get();
    329 }
    330 
    331 net::URLRequestContextGetter*
    332     OffTheRecordProfileImpl::GetRequestContextForExtensions() {
    333   return io_data_->GetExtensionsRequestContextGetter().get();
    334 }
    335 
    336 net::URLRequestContextGetter*
    337 OffTheRecordProfileImpl::CreateRequestContextForStoragePartition(
    338     const base::FilePath& partition_path,
    339     bool in_memory,
    340     content::ProtocolHandlerMap* protocol_handlers,
    341     content::URLRequestInterceptorScopedVector request_interceptors) {
    342   return io_data_->CreateIsolatedAppRequestContextGetter(
    343       partition_path,
    344       in_memory,
    345       protocol_handlers,
    346       request_interceptors.Pass()).get();
    347 }
    348 
    349 content::ResourceContext* OffTheRecordProfileImpl::GetResourceContext() {
    350   return io_data_->GetResourceContext();
    351 }
    352 
    353 net::SSLConfigService* OffTheRecordProfileImpl::GetSSLConfigService() {
    354   return profile_->GetSSLConfigService();
    355 }
    356 
    357 HostContentSettingsMap* OffTheRecordProfileImpl::GetHostContentSettingsMap() {
    358   // Retrieve the host content settings map of the parent profile in order to
    359   // ensure the preferences have been migrated.
    360   profile_->GetHostContentSettingsMap();
    361   if (!host_content_settings_map_.get()) {
    362     host_content_settings_map_ = new HostContentSettingsMap(GetPrefs(), true);
    363 #if defined(ENABLE_EXTENSIONS)
    364     ExtensionService* extension_service =
    365         extensions::ExtensionSystem::Get(this)->extension_service();
    366     if (extension_service) {
    367       extension_service->RegisterContentSettings(
    368           host_content_settings_map_.get());
    369     }
    370 #endif
    371   }
    372   return host_content_settings_map_.get();
    373 }
    374 
    375 content::BrowserPluginGuestManager* OffTheRecordProfileImpl::GetGuestManager() {
    376 #if defined(ENABLE_EXTENSIONS)
    377   return extensions::GuestViewManager::FromBrowserContext(this);
    378 #else
    379   return NULL;
    380 #endif
    381 }
    382 
    383 storage::SpecialStoragePolicy*
    384 OffTheRecordProfileImpl::GetSpecialStoragePolicy() {
    385   return GetExtensionSpecialStoragePolicy();
    386 }
    387 
    388 content::PushMessagingService*
    389 OffTheRecordProfileImpl::GetPushMessagingService() {
    390   // TODO(johnme): Support push messaging in incognito if possible.
    391   return NULL;
    392 }
    393 
    394 content::SSLHostStateDelegate*
    395 OffTheRecordProfileImpl::GetSSLHostStateDelegate() {
    396   return ChromeSSLHostStateDelegateFactory::GetForProfile(this);
    397 }
    398 
    399 bool OffTheRecordProfileImpl::IsSameProfile(Profile* profile) {
    400   return (profile == this) || (profile == profile_);
    401 }
    402 
    403 Time OffTheRecordProfileImpl::GetStartTime() const {
    404   return start_time_;
    405 }
    406 
    407 history::TopSites* OffTheRecordProfileImpl::GetTopSitesWithoutCreating() {
    408   return NULL;
    409 }
    410 
    411 history::TopSites* OffTheRecordProfileImpl::GetTopSites() {
    412   return NULL;
    413 }
    414 
    415 void OffTheRecordProfileImpl::SetExitType(ExitType exit_type) {
    416 }
    417 
    418 base::FilePath OffTheRecordProfileImpl::last_selected_directory() {
    419   const base::FilePath& directory = last_selected_directory_;
    420   if (directory.empty()) {
    421     return profile_->last_selected_directory();
    422   }
    423   return directory;
    424 }
    425 
    426 void OffTheRecordProfileImpl::set_last_selected_directory(
    427     const base::FilePath& path) {
    428   last_selected_directory_ = path;
    429 }
    430 
    431 bool OffTheRecordProfileImpl::WasCreatedByVersionOrLater(
    432     const std::string& version) {
    433   return profile_->WasCreatedByVersionOrLater(version);
    434 }
    435 
    436 Profile::ExitType OffTheRecordProfileImpl::GetLastSessionExitType() {
    437   return profile_->GetLastSessionExitType();
    438 }
    439 
    440 #if defined(OS_CHROMEOS)
    441 void OffTheRecordProfileImpl::ChangeAppLocale(const std::string& locale,
    442                                               AppLocaleChangedVia) {
    443 }
    444 
    445 void OffTheRecordProfileImpl::OnLogin() {
    446 }
    447 
    448 void OffTheRecordProfileImpl::InitChromeOSPreferences() {
    449   // The incognito profile shouldn't have Chrome OS's preferences.
    450   // The preferences are associated with the regular user profile.
    451 }
    452 #endif  // defined(OS_CHROMEOS)
    453 
    454 PrefProxyConfigTracker* OffTheRecordProfileImpl::GetProxyConfigTracker() {
    455   if (!pref_proxy_config_tracker_)
    456     pref_proxy_config_tracker_.reset(CreateProxyConfigTracker());
    457   return pref_proxy_config_tracker_.get();
    458 }
    459 
    460 chrome_browser_net::Predictor* OffTheRecordProfileImpl::GetNetworkPredictor() {
    461   // We do not store information about websites visited in OTR profiles which
    462   // is necessary for a Predictor, so we do not have a Predictor at all.
    463   return NULL;
    464 }
    465 
    466 DevToolsNetworkController*
    467 OffTheRecordProfileImpl::GetDevToolsNetworkController() {
    468   return io_data_->GetDevToolsNetworkController();
    469 }
    470 
    471 void OffTheRecordProfileImpl::ClearNetworkingHistorySince(
    472     base::Time time,
    473     const base::Closure& completion) {
    474   // Nothing to do here, our transport security state is read-only.
    475   // Still, fire the callback to indicate we have finished, otherwise the
    476   // BrowsingDataRemover will never be destroyed and the dialog will never be
    477   // closed. We must do this asynchronously in order to avoid reentrancy issues.
    478   if (!completion.is_null()) {
    479     BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, completion);
    480   }
    481 }
    482 
    483 GURL OffTheRecordProfileImpl::GetHomePage() {
    484   return profile_->GetHomePage();
    485 }
    486 
    487 #if defined(OS_CHROMEOS)
    488 // Special case of the OffTheRecordProfileImpl which is used while Guest
    489 // session in CrOS.
    490 class GuestSessionProfile : public OffTheRecordProfileImpl {
    491  public:
    492   explicit GuestSessionProfile(Profile* real_profile)
    493       : OffTheRecordProfileImpl(real_profile) {
    494   }
    495 
    496   virtual ProfileType GetProfileType() const OVERRIDE {
    497     return GUEST_PROFILE;
    498   }
    499 
    500   virtual void InitChromeOSPreferences() OVERRIDE {
    501     chromeos_preferences_.reset(new chromeos::Preferences());
    502     chromeos_preferences_->Init(
    503         this, user_manager::UserManager::Get()->GetActiveUser());
    504   }
    505 
    506  private:
    507   // The guest user should be able to customize Chrome OS preferences.
    508   scoped_ptr<chromeos::Preferences> chromeos_preferences_;
    509 };
    510 #endif
    511 
    512 Profile* Profile::CreateOffTheRecordProfile() {
    513   OffTheRecordProfileImpl* profile = NULL;
    514 #if defined(OS_CHROMEOS)
    515   if (IsGuestSession())
    516     profile = new GuestSessionProfile(this);
    517 #endif
    518   if (!profile)
    519     profile = new OffTheRecordProfileImpl(this);
    520   profile->Init();
    521   return profile;
    522 }
    523 
    524 void OffTheRecordProfileImpl::OnZoomLevelChanged(
    525     const HostZoomMap::ZoomLevelChange& change) {
    526   HostZoomMap* host_zoom_map = HostZoomMap::GetDefaultForBrowserContext(this);
    527   switch (change.mode) {
    528     case HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
    529        return;
    530     case HostZoomMap::ZOOM_CHANGED_FOR_HOST:
    531        host_zoom_map->SetZoomLevelForHost(change.host, change.zoom_level);
    532        return;
    533     case HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
    534        host_zoom_map->SetZoomLevelForHostAndScheme(change.scheme,
    535            change.host,
    536            change.zoom_level);
    537        return;
    538   }
    539 }
    540 
    541 PrefProxyConfigTracker* OffTheRecordProfileImpl::CreateProxyConfigTracker() {
    542 #if defined(OS_CHROMEOS)
    543   if (chromeos::ProfileHelper::IsSigninProfile(this)) {
    544     return ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
    545         g_browser_process->local_state());
    546   }
    547 #endif  // defined(OS_CHROMEOS)
    548   return ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
    549       GetPrefs(), g_browser_process->local_state());
    550 }
    551