1 // Copyright 2014 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 "components/policy/core/browser/browser_policy_connector.h"
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/metrics/histogram_macros.h"
13 #include "base/metrics/sparse_histogram.h"
14 #include "base/prefs/pref_registry_simple.h"
15 #include "base/strings/string16.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
18 #include "components/policy/core/common/cloud/device_management_service.h"
19 #include "components/policy/core/common/configuration_policy_provider.h"
20 #include "components/policy/core/common/policy_namespace.h"
21 #include "components/policy/core/common/policy_pref_names.h"
22 #include "components/policy/core/common/policy_statistics_collector.h"
23 #include "components/policy/core/common/policy_switches.h"
24 #include "google_apis/gaia/gaia_auth_util.h"
25 #include "policy/policy_constants.h"
26 #include "third_party/icu/source/i18n/unicode/regex.h"
32 // The URL for the device management server.
33 const char kDefaultDeviceManagementServerUrl
[] =
34 "https://m.google.com/devicemanagement/data/api";
37 void ReportRegexSuccessMetric(bool success
) {
38 UMA_HISTOGRAM_BOOLEAN("Enterprise.DomainWhitelistRegexSuccess", success
);
41 // Regexes that match many of the larger public email providers as we know
42 // these users are not from hosted enterprise domains. Keep this list in sync
43 // with the EnterpriseDomainRegex enum in histograms.xml (i.e. only add things
45 const wchar_t* const kNonManagedDomainPatterns
[] = {
49 L
"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk
54 L
"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw
58 // Returns true if |domain| matches the regex |pattern|.
59 bool MatchDomain(const base::string16
& domain
, const base::string16
& pattern
,
61 UErrorCode status
= U_ZERO_ERROR
;
62 const icu::UnicodeString
icu_pattern(pattern
.data(), pattern
.length());
63 icu::RegexMatcher
matcher(icu_pattern
, UREGEX_CASE_INSENSITIVE
, status
);
64 if (!U_SUCCESS(status
)) {
65 // http://crbug.com/365351 - if for some reason the matcher creation fails
66 // just return that the pattern doesn't match the domain. This is safe
67 // because the calling method (IsNonEnterpriseUser()) is just used to enable
68 // an optimization for non-enterprise users - better to skip the
69 // optimization than crash.
70 DLOG(ERROR
) << "Possible invalid domain pattern: " << pattern
71 << " - Error: " << status
;
72 ReportRegexSuccessMetric(false);
73 UMA_HISTOGRAM_ENUMERATION("Enterprise.DomainWhitelistRegexFailure",
74 index
, arraysize(kNonManagedDomainPatterns
));
75 UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.DomainWhitelistRegexFailureStatus",
79 ReportRegexSuccessMetric(true);
80 icu::UnicodeString
icu_input(domain
.data(), domain
.length());
81 matcher
.reset(icu_input
);
82 status
= U_ZERO_ERROR
;
83 UBool match
= matcher
.matches(status
);
84 DCHECK(U_SUCCESS(status
));
85 return !!match
; // !! == convert from UBool to bool.
90 BrowserPolicyConnector::BrowserPolicyConnector(
91 const HandlerListFactory
& handler_list_factory
)
92 : BrowserPolicyConnectorBase(handler_list_factory
) {
95 BrowserPolicyConnector::~BrowserPolicyConnector() {
98 void BrowserPolicyConnector::InitInternal(
99 PrefService
* local_state
,
100 scoped_ptr
<DeviceManagementService
> device_management_service
) {
101 DCHECK(!is_initialized());
103 device_management_service_
= device_management_service
.Pass();
105 policy_statistics_collector_
.reset(new policy::PolicyStatisticsCollector(
106 base::Bind(&GetChromePolicyDetails
), GetChromeSchema(),
107 GetPolicyService(), local_state
,
108 base::MessageLoop::current()->task_runner()));
109 policy_statistics_collector_
->Initialize();
111 InitPolicyProviders();
114 void BrowserPolicyConnector::Shutdown() {
115 BrowserPolicyConnectorBase::Shutdown();
116 device_management_service_
.reset();
119 void BrowserPolicyConnector::ScheduleServiceInitialization(
120 int64 delay_milliseconds
) {
121 // Skip device initialization if the BrowserPolicyConnector was never
122 // initialized (unit tests).
123 if (device_management_service_
)
124 device_management_service_
->ScheduleInitialization(delay_milliseconds
);
128 bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string
& username
) {
129 if (username
.empty() || username
.find('@') == std::string::npos
) {
130 // An empty username means incognito user in case of ChromiumOS and
131 // no logged-in user in case of Chromium (SigninService). Many tests use
132 // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
136 const base::string16 domain
= base::UTF8ToUTF16(
137 gaia::ExtractDomainName(gaia::CanonicalizeEmail(username
)));
138 for (size_t i
= 0; i
< arraysize(kNonManagedDomainPatterns
); i
++) {
139 base::string16 pattern
= base::WideToUTF16(kNonManagedDomainPatterns
[i
]);
140 if (MatchDomain(domain
, pattern
, i
))
147 std::string
BrowserPolicyConnector::GetDeviceManagementUrl() {
148 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
149 if (command_line
->HasSwitch(switches::kDeviceManagementUrl
))
150 return command_line
->GetSwitchValueASCII(switches::kDeviceManagementUrl
);
152 return kDefaultDeviceManagementServerUrl
;
156 void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple
* registry
) {
157 registry
->RegisterIntegerPref(
158 policy_prefs::kUserPolicyRefreshRate
,
159 CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs
);
163 } // namespace policy