4df068db2e8ab59c96abf0b040accd2cc8430a1c
[platform/framework/web/crosswalk.git] / src / chrome / browser / profiles / off_the_record_profile_impl.cc
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 }