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.
5 #include "chrome/browser/prefs/incognito_mode_prefs.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/metrics/histogram_macros.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/threading/thread_restrictions.h"
12 #include "base/time/time.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/pref_names.h"
16 #include "components/pref_registry/pref_registry_syncable.h"
17 #include "content/public/browser/browser_thread.h"
22 #include "base/bind.h"
23 #include "base/bind_helpers.h"
24 #include "base/memory/singleton.h"
25 #include "base/win/scoped_comptr.h"
26 #include "base/win/windows_version.h"
29 #if defined(OS_ANDROID)
30 #include "chrome/browser/android/chrome_application.h"
33 using content::BrowserThread
;
38 // This singleton allows us to attempt to calculate the Platform Parental
39 // Controls enabled value on a worker thread before the UI thread needs the
40 // value. If the UI thread finishes sooner than we expect, that's no worse than
41 // today where we block.
42 class PlatformParentalControlsValue
{
44 static PlatformParentalControlsValue
* GetInstance() {
45 return base::Singleton
<PlatformParentalControlsValue
>::get();
48 bool is_enabled() const {
53 friend struct base::DefaultSingletonTraits
<PlatformParentalControlsValue
>;
55 // Histogram enum for tracking the thread that checked parental controls.
56 enum class ThreadType
{
62 PlatformParentalControlsValue()
63 : is_enabled_(IsParentalControlActivityLoggingOn()) {}
65 ~PlatformParentalControlsValue() = default;
67 // Returns true if Windows Parental control activity logging is enabled. This
68 // feature is available on Windows 7 and beyond. This function should be
69 // called on a COM Initialized thread and is potentially blocking.
70 static bool IsParentalControlActivityLoggingOn() {
71 // Since we can potentially block, make sure the thread is okay with this.
72 base::ThreadRestrictions::AssertIOAllowed();
73 base::ThreadRestrictions::AssertWaitAllowed();
75 // Query this info on Windows 7 and above.
76 if (base::win::GetVersion() < base::win::VERSION_WIN7
)
79 ThreadType thread_type
= ThreadType::BLOCKING
;
80 if (BrowserThread::IsThreadInitialized(BrowserThread::UI
) &&
81 content::BrowserThread::CurrentlyOn(content::BrowserThread::UI
)) {
82 thread_type
= ThreadType::UI
;
85 UMA_HISTOGRAM_ENUMERATION(
86 "IncognitoModePrefs.WindowsParentalControlsInitThread",
87 static_cast<int32_t>(thread_type
),
88 static_cast<int32_t>(ThreadType::COUNT
));
90 base::Time begin_time
= base::Time::Now();
91 bool result
= IsParentalControlActivityLoggingOnImpl();
92 UMA_HISTOGRAM_TIMES("IncognitoModePrefs.WindowsParentalControlsInitTime",
93 base::Time::Now() - begin_time
);
97 // Does the work of determining if Windows Parental control activity logging
99 static bool IsParentalControlActivityLoggingOnImpl() {
100 base::win::ScopedComPtr
<IWindowsParentalControlsCore
> parent_controls
;
101 HRESULT hr
= parent_controls
.CreateInstance(
102 __uuidof(WindowsParentalControls
));
106 base::win::ScopedComPtr
<IWPCSettings
> settings
;
107 hr
= parent_controls
->GetUserSettings(nullptr, settings
.Receive());
111 unsigned long restrictions
= 0;
112 settings
->GetRestrictions(&restrictions
);
114 return (restrictions
& WPCFLAG_LOGGING_REQUIRED
) ==
115 WPCFLAG_LOGGING_REQUIRED
;
118 const bool is_enabled_
;
120 DISALLOW_COPY_AND_ASSIGN(PlatformParentalControlsValue
);
127 bool IncognitoModePrefs::IntToAvailability(int in_value
,
128 Availability
* out_value
) {
129 if (in_value
< 0 || in_value
>= AVAILABILITY_NUM_TYPES
) {
130 *out_value
= ENABLED
;
133 *out_value
= static_cast<Availability
>(in_value
);
138 IncognitoModePrefs::Availability
IncognitoModePrefs::GetAvailability(
139 const PrefService
* pref_service
) {
140 DCHECK(pref_service
);
141 int pref_value
= pref_service
->GetInteger(prefs::kIncognitoModeAvailability
);
142 Availability result
= IncognitoModePrefs::ENABLED
;
143 bool valid
= IntToAvailability(pref_value
, &result
);
145 if (ArePlatformParentalControlsEnabled()) {
146 if (result
== IncognitoModePrefs::FORCED
)
147 LOG(ERROR
) << "Ignoring FORCED incognito. Parental control logging on";
148 return IncognitoModePrefs::DISABLED
;
154 void IncognitoModePrefs::SetAvailability(PrefService
* prefs
,
155 const Availability availability
) {
156 prefs
->SetInteger(prefs::kIncognitoModeAvailability
, availability
);
160 void IncognitoModePrefs::RegisterProfilePrefs(
161 user_prefs::PrefRegistrySyncable
* registry
) {
162 registry
->RegisterIntegerPref(prefs::kIncognitoModeAvailability
,
163 IncognitoModePrefs::ENABLED
);
167 bool IncognitoModePrefs::ShouldLaunchIncognito(
168 const base::CommandLine
& command_line
,
169 const PrefService
* prefs
) {
170 Availability incognito_avail
= GetAvailability(prefs
);
171 return incognito_avail
!= IncognitoModePrefs::DISABLED
&&
172 (command_line
.HasSwitch(switches::kIncognito
) ||
173 incognito_avail
== IncognitoModePrefs::FORCED
);
177 bool IncognitoModePrefs::CanOpenBrowser(Profile
* profile
) {
178 if (profile
->IsGuestSession())
181 switch (GetAvailability(profile
->GetPrefs())) {
182 case IncognitoModePrefs::ENABLED
:
185 case IncognitoModePrefs::DISABLED
:
186 return !profile
->IsOffTheRecord();
188 case IncognitoModePrefs::FORCED
:
189 return profile
->IsOffTheRecord();
199 void IncognitoModePrefs::InitializePlatformParentalControls() {
200 content::BrowserThread::PostBlockingPoolTask(
203 base::IgnoreResult(&PlatformParentalControlsValue::GetInstance
)));
208 bool IncognitoModePrefs::ArePlatformParentalControlsEnabled() {
210 return PlatformParentalControlsValue::GetInstance()->is_enabled();
211 #elif defined(OS_ANDROID)
212 return chrome::android::ChromeApplication::AreParentalControlsEnabled();