off_the_record_profile_impl.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/file_util.h"
11#include "base/files/file_path.h"
12#include "base/memory/scoped_ptr.h"
13#include "base/path_service.h"
14#include "base/prefs/json_pref_store.h"
15#include "base/string_util.h"
16#include "base/strings/string_number_conversions.h"
17#include "build/build_config.h"
18#include "chrome/browser/background/background_contents_service_factory.h"
19#include "chrome/browser/browser_process.h"
20#include "chrome/browser/content_settings/host_content_settings_map.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/api/web_request/web_request_api.h"
25#include "chrome/browser/extensions/extension_info_map.h"
26#include "chrome/browser/extensions/extension_service.h"
27#include "chrome/browser/extensions/extension_special_storage_policy.h"
28#include "chrome/browser/extensions/extension_system.h"
29#include "chrome/browser/io_thread.h"
30#include "chrome/browser/net/proxy_service_factory.h"
31#include "chrome/browser/plugins/chrome_plugin_service_filter.h"
32#include "chrome/browser/plugins/plugin_prefs.h"
33#include "chrome/browser/prefs/incognito_mode_prefs.h"
34#include "chrome/browser/prefs/pref_service_syncable.h"
35#include "chrome/browser/profiles/profile_dependency_manager.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/extensions/extension.h"
42#include "chrome/common/pref_names.h"
43#include "chrome/common/render_messages.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 "webkit/database/database_tracker.h"
54
55#if defined(OS_ANDROID) || defined(OS_IOS)
56#include "chrome/browser/prefs/scoped_user_pref_update.h"
57#endif  // defined(OS_ANDROID) || defined(OS_IOS)
58
59#if defined(OS_CHROMEOS)
60#include "chrome/browser/chromeos/preferences.h"
61#include "chrome/browser/chromeos/proxy_config_service_impl.h"
62#endif
63
64using content::BrowserThread;
65using content::DownloadManagerDelegate;
66using content::HostZoomMap;
67
68namespace {
69
70void NotifyOTRProfileCreatedOnIOThread(void* original_profile,
71                                       void* otr_profile) {
72  ExtensionWebRequestEventRouter::GetInstance()->OnOTRProfileCreated(
73      original_profile, otr_profile);
74}
75
76void NotifyOTRProfileDestroyedOnIOThread(void* original_profile,
77                                         void* otr_profile) {
78  ExtensionWebRequestEventRouter::GetInstance()->OnOTRProfileDestroyed(
79      original_profile, otr_profile);
80}
81
82}  // namespace
83
84OffTheRecordProfileImpl::OffTheRecordProfileImpl(Profile* real_profile)
85    : profile_(real_profile),
86      prefs_(PrefServiceSyncable::IncognitoFromProfile(real_profile)),
87      ALLOW_THIS_IN_INITIALIZER_LIST(io_data_(this)),
88      start_time_(Time::Now()),
89      zoom_callback_(base::Bind(&OffTheRecordProfileImpl::OnZoomLevelChanged,
90                                base::Unretained(this))) {
91  // Register on BrowserContext.
92  components::UserPrefs::Set(this, prefs_);
93}
94
95void OffTheRecordProfileImpl::Init() {
96  ProfileDependencyManager::GetInstance()->CreateProfileServices(this, false);
97
98  extensions::ExtensionSystem::Get(this)->InitForOTRProfile();
99
100  DCHECK_NE(IncognitoModePrefs::DISABLED,
101            IncognitoModePrefs::GetAvailability(profile_->GetPrefs()));
102
103#if defined(OS_ANDROID) || defined(OS_IOS)
104  UseSystemProxy();
105#endif  // defined(OS_ANDROID) || defined(OS_IOS)
106
107  // TODO(oshima): Remove the need to eagerly initialize the request context
108  // getter. chromeos::OnlineAttempt is illegally trying to access this
109  // Profile member from a thread other than the UI thread, so we need to
110  // prevent a race.
111#if defined(OS_CHROMEOS)
112  GetRequestContext();
113#endif  // defined(OS_CHROMEOS)
114
115  InitHostZoomMap();
116
117  // Make the chrome//extension-icon/ resource available.
118  ExtensionIconSource* icon_source = new ExtensionIconSource(profile_);
119  content::URLDataSource::Add(this, icon_source);
120
121#if defined(ENABLE_PLUGINS)
122  ChromePluginServiceFilter::GetInstance()->RegisterResourceContext(
123      PluginPrefs::GetForProfile(this), io_data_.GetResourceContextNoInit());
124#endif
125
126  BrowserThread::PostTask(
127      BrowserThread::IO, FROM_HERE,
128      base::Bind(&NotifyOTRProfileCreatedOnIOThread, profile_, this));
129}
130
131OffTheRecordProfileImpl::~OffTheRecordProfileImpl() {
132  MaybeSendDestroyedNotification();
133
134  HostZoomMap::GetForBrowserContext(profile_)->RemoveZoomLevelChangedCallback(
135      zoom_callback_);
136
137#if defined(ENABLE_PLUGINS)
138  ChromePluginServiceFilter::GetInstance()->UnregisterResourceContext(
139    io_data_.GetResourceContextNoInit());
140#endif
141
142  ProfileDependencyManager::GetInstance()->DestroyProfileServices(this);
143
144  BrowserThread::PostTask(
145      BrowserThread::IO, FROM_HERE,
146      base::Bind(&NotifyOTRProfileDestroyedOnIOThread, profile_, this));
147
148  if (host_content_settings_map_)
149    host_content_settings_map_->ShutdownOnUIThread();
150
151  if (pref_proxy_config_tracker_.get())
152    pref_proxy_config_tracker_->DetachFromPrefService();
153
154  // Clears any data the network stack contains that may be related to the
155  // OTR session.
156  g_browser_process->io_thread()->ChangedToOnTheRecord();
157}
158
159void OffTheRecordProfileImpl::InitHostZoomMap() {
160  HostZoomMap* host_zoom_map = HostZoomMap::GetForBrowserContext(this);
161  HostZoomMap* parent_host_zoom_map =
162      HostZoomMap::GetForBrowserContext(profile_);
163  host_zoom_map->CopyFrom(parent_host_zoom_map);
164  // Observe parent's HZM change for propagating change of parent's
165  // change to this HZM.
166  parent_host_zoom_map->AddZoomLevelChangedCallback(zoom_callback_);
167}
168
169#if defined(OS_ANDROID) || defined(OS_IOS)
170void OffTheRecordProfileImpl::UseSystemProxy() {
171  // Force the use of the system-assigned proxy when off the record.
172  const char kProxyMode[] = "mode";
173  const char kProxyServer[] = "server";
174  const char kProxyBypassList[] = "bypass_list";
175  const char kProxyPacUrl[] = "pac_url";
176  DictionaryPrefUpdate update(prefs_, prefs::kProxy);
177  DictionaryValue* dict = update.Get();
178  dict->SetString(kProxyMode, ProxyModeToString(ProxyPrefs::MODE_SYSTEM));
179  dict->SetString(kProxyPacUrl, "");
180  dict->SetString(kProxyServer, "");
181  dict->SetString(kProxyBypassList, "");
182}
183#endif  // defined(OS_ANDROID) || defined(OS_IOS)
184
185std::string OffTheRecordProfileImpl::GetProfileName() {
186  // Incognito profile should not return the profile name.
187  return std::string();
188}
189
190base::FilePath OffTheRecordProfileImpl::GetPath() {
191  return profile_->GetPath();
192}
193
194scoped_refptr<base::SequencedTaskRunner>
195OffTheRecordProfileImpl::GetIOTaskRunner() {
196  return profile_->GetIOTaskRunner();
197}
198
199bool OffTheRecordProfileImpl::IsOffTheRecord() const {
200  return true;
201}
202
203Profile* OffTheRecordProfileImpl::GetOffTheRecordProfile() {
204  return this;
205}
206
207void OffTheRecordProfileImpl::DestroyOffTheRecordProfile() {
208  // Suicide is bad!
209  NOTREACHED();
210}
211
212bool OffTheRecordProfileImpl::HasOffTheRecordProfile() {
213  return true;
214}
215
216Profile* OffTheRecordProfileImpl::GetOriginalProfile() {
217  return profile_;
218}
219
220ExtensionService* OffTheRecordProfileImpl::GetExtensionService() {
221  return extensions::ExtensionSystem::Get(this)->extension_service();
222}
223
224ExtensionSpecialStoragePolicy*
225    OffTheRecordProfileImpl::GetExtensionSpecialStoragePolicy() {
226  return GetOriginalProfile()->GetExtensionSpecialStoragePolicy();
227}
228
229policy::ManagedModePolicyProvider*
230    OffTheRecordProfileImpl::GetManagedModePolicyProvider() {
231  return profile_->GetManagedModePolicyProvider();
232}
233
234policy::PolicyService* OffTheRecordProfileImpl::GetPolicyService() {
235  return profile_->GetPolicyService();
236}
237
238PrefService* OffTheRecordProfileImpl::GetPrefs() {
239  return prefs_;
240}
241
242PrefService* OffTheRecordProfileImpl::GetOffTheRecordPrefs() {
243  return prefs_;
244}
245
246DownloadManagerDelegate* OffTheRecordProfileImpl::GetDownloadManagerDelegate() {
247  return DownloadServiceFactory::GetForProfile(this)->
248      GetDownloadManagerDelegate();
249}
250
251net::URLRequestContextGetter* OffTheRecordProfileImpl::GetRequestContext() {
252  return GetDefaultStoragePartition(this)->GetURLRequestContext();
253}
254
255net::URLRequestContextGetter* OffTheRecordProfileImpl::CreateRequestContext(
256    content::ProtocolHandlerMap* protocol_handlers) {
257  return io_data_.CreateMainRequestContextGetter(protocol_handlers);
258}
259
260net::URLRequestContextGetter*
261    OffTheRecordProfileImpl::GetRequestContextForRenderProcess(
262        int renderer_child_id) {
263  content::RenderProcessHost* rph = content::RenderProcessHost::FromID(
264      renderer_child_id);
265  return rph->GetStoragePartition()->GetURLRequestContext();
266}
267
268net::URLRequestContextGetter*
269    OffTheRecordProfileImpl::GetMediaRequestContext() {
270  // In OTR mode, media request context is the same as the original one.
271  return GetRequestContext();
272}
273
274net::URLRequestContextGetter*
275    OffTheRecordProfileImpl::GetMediaRequestContextForRenderProcess(
276        int renderer_child_id) {
277  // In OTR mode, media request context is the same as the original one.
278  return GetRequestContextForRenderProcess(renderer_child_id);
279}
280
281net::URLRequestContextGetter*
282OffTheRecordProfileImpl::GetMediaRequestContextForStoragePartition(
283    const base::FilePath& partition_path,
284    bool in_memory) {
285  return io_data_.GetIsolatedAppRequestContextGetter(partition_path, in_memory);
286}
287
288net::URLRequestContextGetter*
289    OffTheRecordProfileImpl::GetRequestContextForExtensions() {
290  return io_data_.GetExtensionsRequestContextGetter();
291}
292
293net::URLRequestContextGetter*
294    OffTheRecordProfileImpl::CreateRequestContextForStoragePartition(
295        const base::FilePath& partition_path,
296        bool in_memory,
297        content::ProtocolHandlerMap* protocol_handlers) {
298  return io_data_.CreateIsolatedAppRequestContextGetter(
299      partition_path, in_memory, protocol_handlers);
300}
301
302content::ResourceContext* OffTheRecordProfileImpl::GetResourceContext() {
303  return io_data_.GetResourceContext();
304}
305
306net::SSLConfigService* OffTheRecordProfileImpl::GetSSLConfigService() {
307  return profile_->GetSSLConfigService();
308}
309
310HostContentSettingsMap* OffTheRecordProfileImpl::GetHostContentSettingsMap() {
311  // Retrieve the host content settings map of the parent profile in order to
312  // ensure the preferences have been migrated.
313  profile_->GetHostContentSettingsMap();
314  if (!host_content_settings_map_.get()) {
315    host_content_settings_map_ = new HostContentSettingsMap(GetPrefs(), true);
316#if defined(ENABLE_EXTENSIONS)
317    ExtensionService* extension_service = GetExtensionService();
318    if (extension_service)
319      host_content_settings_map_->RegisterExtensionService(extension_service);
320#endif
321  }
322  return host_content_settings_map_.get();
323}
324
325content::GeolocationPermissionContext*
326    OffTheRecordProfileImpl::GetGeolocationPermissionContext() {
327  return profile_->GetGeolocationPermissionContext();
328}
329
330content::SpeechRecognitionPreferences*
331    OffTheRecordProfileImpl::GetSpeechRecognitionPreferences() {
332  return profile_->GetSpeechRecognitionPreferences();
333}
334
335quota::SpecialStoragePolicy*
336    OffTheRecordProfileImpl::GetSpecialStoragePolicy() {
337  return GetExtensionSpecialStoragePolicy();
338}
339
340ProtocolHandlerRegistry* OffTheRecordProfileImpl::GetProtocolHandlerRegistry() {
341  return profile_->GetProtocolHandlerRegistry();
342}
343
344bool OffTheRecordProfileImpl::IsSameProfile(Profile* profile) {
345  return (profile == this) || (profile == profile_);
346}
347
348Time OffTheRecordProfileImpl::GetStartTime() const {
349  return start_time_;
350}
351
352history::TopSites* OffTheRecordProfileImpl::GetTopSitesWithoutCreating() {
353  return NULL;
354}
355
356history::TopSites* OffTheRecordProfileImpl::GetTopSites() {
357  return NULL;
358}
359
360void OffTheRecordProfileImpl::SetExitType(ExitType exit_type) {
361}
362
363base::FilePath OffTheRecordProfileImpl::last_selected_directory() {
364  const base::FilePath& directory = last_selected_directory_;
365  if (directory.empty()) {
366    return profile_->last_selected_directory();
367  }
368  return directory;
369}
370
371void OffTheRecordProfileImpl::set_last_selected_directory(
372    const base::FilePath& path) {
373  last_selected_directory_ = path;
374}
375
376bool OffTheRecordProfileImpl::WasCreatedByVersionOrLater(
377    const std::string& version) {
378  return profile_->WasCreatedByVersionOrLater(version);
379}
380
381Profile::ExitType OffTheRecordProfileImpl::GetLastSessionExitType() {
382  return profile_->GetLastSessionExitType();
383}
384
385#if defined(OS_CHROMEOS)
386void OffTheRecordProfileImpl::SetupChromeOSEnterpriseExtensionObserver() {
387  profile_->SetupChromeOSEnterpriseExtensionObserver();
388}
389
390void OffTheRecordProfileImpl::InitChromeOSPreferences() {
391  // The incognito profile shouldn't have Chrome OS's preferences.
392  // The preferences are associated with the regular user profile.
393}
394#endif  // defined(OS_CHROMEOS)
395
396#if defined(OS_CHROMEOS)
397void OffTheRecordProfileImpl::ChangeAppLocale(const std::string& locale,
398                                              AppLocaleChangedVia) {
399}
400
401void OffTheRecordProfileImpl::OnLogin() {
402}
403#endif  // defined(OS_CHROMEOS)
404
405PrefProxyConfigTracker* OffTheRecordProfileImpl::GetProxyConfigTracker() {
406  if (!pref_proxy_config_tracker_.get()) {
407    pref_proxy_config_tracker_.reset(
408        ProxyServiceFactory::CreatePrefProxyConfigTracker(GetPrefs()));
409  }
410  return pref_proxy_config_tracker_.get();
411}
412
413chrome_browser_net::Predictor* OffTheRecordProfileImpl::GetNetworkPredictor() {
414  // We do not store information about websites visited in OTR profiles which
415  // is necessary for a Predictor, so we do not have a Predictor at all.
416  return NULL;
417}
418
419void OffTheRecordProfileImpl::ClearNetworkingHistorySince(
420    base::Time time,
421    const base::Closure& completion) {
422  // Nothing to do here, our transport security state is read-only.
423  // Still, fire the callback to indicate we have finished, otherwise the
424  // BrowsingDataRemover will never be destroyed and the dialog will never be
425  // closed. We must do this asynchronously in order to avoid reentrancy issues.
426  if (!completion.is_null()) {
427    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, completion);
428  }
429}
430
431GURL OffTheRecordProfileImpl::GetHomePage() {
432  return profile_->GetHomePage();
433}
434
435#if defined(OS_CHROMEOS)
436// Special case of the OffTheRecordProfileImpl which is used while Guest
437// session in CrOS.
438class GuestSessionProfile : public OffTheRecordProfileImpl {
439 public:
440  explicit GuestSessionProfile(Profile* real_profile)
441      : OffTheRecordProfileImpl(real_profile) {
442  }
443
444  virtual void InitChromeOSPreferences() OVERRIDE {
445    chromeos_preferences_.reset(new chromeos::Preferences());
446    chromeos_preferences_->Init(static_cast<PrefServiceSyncable*>(GetPrefs()));
447  }
448
449 private:
450  // The guest user should be able to customize Chrome OS preferences.
451  scoped_ptr<chromeos::Preferences> chromeos_preferences_;
452};
453#endif
454
455Profile* Profile::CreateOffTheRecordProfile() {
456  OffTheRecordProfileImpl* profile = NULL;
457#if defined(OS_CHROMEOS)
458  if (IsGuestSession())
459    profile = new GuestSessionProfile(this);
460#endif
461  if (!profile)
462    profile = new OffTheRecordProfileImpl(this);
463  profile->Init();
464  return profile;
465}
466
467void OffTheRecordProfileImpl::OnZoomLevelChanged(
468    const HostZoomMap::ZoomLevelChange& change) {
469  HostZoomMap* host_zoom_map = HostZoomMap::GetForBrowserContext(this);
470  switch (change.mode) {
471    case HostZoomMap::ZOOM_CHANGED_TEMPORARY_ZOOM:
472       return;
473    case HostZoomMap::ZOOM_CHANGED_FOR_HOST:
474       host_zoom_map->SetZoomLevelForHost(change.host, change.zoom_level);
475       return;
476    case HostZoomMap::ZOOM_CHANGED_FOR_SCHEME_AND_HOST:
477       host_zoom_map->SetZoomLevelForHostAndScheme(change.scheme,
478           change.host,
479           change.zoom_level);
480       return;
481  }
482}
483