Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / policy / core / browser / browser_policy_connector.cc
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.
4
5 #include "components/policy/core/browser/browser_policy_connector.h"
6
7 #include <algorithm>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/logging.h"
12 #include "base/message_loop/message_loop.h"
13 #include "base/message_loop/message_loop_proxy.h"
14 #include "base/metrics/histogram.h"
15 #include "base/metrics/sparse_histogram.h"
16 #include "base/prefs/pref_registry_simple.h"
17 #include "base/strings/string16.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "components/policy/core/common/cloud/cloud_policy_refresh_scheduler.h"
20 #include "components/policy/core/common/cloud/device_management_service.h"
21 #include "components/policy/core/common/configuration_policy_provider.h"
22 #include "components/policy/core/common/policy_namespace.h"
23 #include "components/policy/core/common/policy_pref_names.h"
24 #include "components/policy/core/common/policy_service_impl.h"
25 #include "components/policy/core/common/policy_statistics_collector.h"
26 #include "components/policy/core/common/policy_switches.h"
27 #include "google_apis/gaia/gaia_auth_util.h"
28 #include "net/url_request/url_request_context_getter.h"
29 #include "policy/policy_constants.h"
30 #include "third_party/icu/source/i18n/unicode/regex.h"
31
32 namespace policy {
33
34 namespace {
35
36 // The URL for the device management server.
37 const char kDefaultDeviceManagementServerUrl[] =
38     "https://m.google.com/devicemanagement/data/api";
39
40 // Used in BrowserPolicyConnector::SetPolicyProviderForTesting.
41 bool g_created_policy_service = false;
42 ConfigurationPolicyProvider* g_testing_provider = NULL;
43
44 void ReportRegexSuccessMetric(bool success) {
45   UMA_HISTOGRAM_BOOLEAN("Enterprise.DomainWhitelistRegexSuccess", success);
46 }
47
48 // Regexes that match many of the larger public email providers as we know
49 // these users are not from hosted enterprise domains. Keep this list in sync
50 // with the EnterpriseDomainRegex enum in histograms.xml (i.e. only add things
51 // at the end).
52 const wchar_t* const kNonManagedDomainPatterns[] = {
53   L"aol\\.com",
54   L"googlemail\\.com",
55   L"gmail\\.com",
56   L"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk
57   L"live\\.com",
58   L"mail\\.ru",
59   L"msn\\.com",
60   L"qq\\.com",
61   L"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw
62   L"yandex\\.ru",
63 };
64
65 // Returns true if |domain| matches the regex |pattern|.
66 bool MatchDomain(const base::string16& domain, const base::string16& pattern,
67                  size_t index) {
68   UErrorCode status = U_ZERO_ERROR;
69   const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
70   icu::RegexMatcher matcher(icu_pattern, UREGEX_CASE_INSENSITIVE, status);
71   if (!U_SUCCESS(status)) {
72     // http://crbug.com/365351 - if for some reason the matcher creation fails
73     // just return that the pattern doesn't match the domain. This is safe
74     // because the calling method (IsNonEnterpriseUser()) is just used to enable
75     // an optimization for non-enterprise users - better to skip the
76     // optimization than crash.
77     DLOG(ERROR) << "Possible invalid domain pattern: " << pattern
78                 << " - Error: " << status;
79     ReportRegexSuccessMetric(false);
80     UMA_HISTOGRAM_ENUMERATION("Enterprise.DomainWhitelistRegexFailure",
81                               index, arraysize(kNonManagedDomainPatterns));
82     UMA_HISTOGRAM_SPARSE_SLOWLY("Enterprise.DomainWhitelistRegexFailureStatus",
83                                 status);
84     return false;
85   }
86   ReportRegexSuccessMetric(true);
87   icu::UnicodeString icu_input(domain.data(), domain.length());
88   matcher.reset(icu_input);
89   status = U_ZERO_ERROR;
90   UBool match = matcher.matches(status);
91   DCHECK(U_SUCCESS(status));
92   return !!match;  // !! == convert from UBool to bool.
93 }
94
95 }  // namespace
96
97 BrowserPolicyConnector::BrowserPolicyConnector(
98     const HandlerListFactory& handler_list_factory)
99     : is_initialized_(false),
100       platform_policy_provider_(NULL) {
101   // GetPolicyService() must be ready after the constructor is done.
102   // The connector is created very early during startup, when the browser
103   // threads aren't running yet; initialize components that need local_state,
104   // the system request context or other threads (e.g. FILE) at Init().
105
106   // Initialize the SchemaRegistry with the Chrome schema before creating any
107   // of the policy providers in subclasses.
108   chrome_schema_ = Schema::Wrap(GetChromeSchemaData());
109   handler_list_ = handler_list_factory.Run(chrome_schema_);
110   schema_registry_.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""),
111                                      chrome_schema_);
112 }
113
114 BrowserPolicyConnector::~BrowserPolicyConnector() {
115   if (is_initialized()) {
116     // Shutdown() wasn't invoked by our owner after having called Init().
117     // This usually means it's an early shutdown and
118     // BrowserProcessImpl::StartTearDown() wasn't invoked.
119     // Cleanup properly in those cases and avoid crashing the ToastCrasher test.
120     Shutdown();
121   }
122 }
123
124 void BrowserPolicyConnector::Init(
125     PrefService* local_state,
126     scoped_refptr<net::URLRequestContextGetter> request_context,
127     scoped_ptr<DeviceManagementService> device_management_service) {
128   DCHECK(!is_initialized());
129
130   device_management_service_ = device_management_service.Pass();
131
132   if (g_testing_provider)
133     g_testing_provider->Init(GetSchemaRegistry());
134   for (size_t i = 0; i < policy_providers_.size(); ++i)
135     policy_providers_[i]->Init(GetSchemaRegistry());
136
137   policy_statistics_collector_.reset(
138       new policy::PolicyStatisticsCollector(
139           base::Bind(&GetChromePolicyDetails),
140           GetChromeSchema(),
141           GetPolicyService(),
142           local_state,
143           base::MessageLoop::current()->message_loop_proxy()));
144   policy_statistics_collector_->Initialize();
145
146   is_initialized_ = true;
147 }
148
149 void BrowserPolicyConnector::Shutdown() {
150   is_initialized_ = false;
151   if (g_testing_provider)
152     g_testing_provider->Shutdown();
153   for (size_t i = 0; i < policy_providers_.size(); ++i)
154     policy_providers_[i]->Shutdown();
155   // Drop g_testing_provider so that tests executed with --single_process can
156   // call SetPolicyProviderForTesting() again. It is still owned by the test.
157   g_testing_provider = NULL;
158   g_created_policy_service = false;
159   device_management_service_.reset();
160 }
161
162 PolicyService* BrowserPolicyConnector::GetPolicyService() {
163   if (!policy_service_) {
164     g_created_policy_service = true;
165     std::vector<ConfigurationPolicyProvider*> providers;
166     if (g_testing_provider) {
167       providers.push_back(g_testing_provider);
168     } else {
169       providers.resize(policy_providers_.size());
170       std::copy(policy_providers_.begin(),
171                 policy_providers_.end(),
172                 providers.begin());
173     }
174     policy_service_.reset(new PolicyServiceImpl(providers));
175   }
176   return policy_service_.get();
177 }
178
179 ConfigurationPolicyProvider* BrowserPolicyConnector::GetPlatformProvider() {
180   if (g_testing_provider)
181     return g_testing_provider;
182   return platform_policy_provider_;
183 }
184
185 const Schema& BrowserPolicyConnector::GetChromeSchema() const {
186   return chrome_schema_;
187 }
188
189 CombinedSchemaRegistry* BrowserPolicyConnector::GetSchemaRegistry() {
190   return &schema_registry_;
191 }
192
193 void BrowserPolicyConnector::ScheduleServiceInitialization(
194     int64 delay_milliseconds) {
195   // Skip device initialization if the BrowserPolicyConnector was never
196   // initialized (unit tests).
197   if (device_management_service_)
198     device_management_service_->ScheduleInitialization(delay_milliseconds);
199 }
200
201 const ConfigurationPolicyHandlerList*
202     BrowserPolicyConnector::GetHandlerList() const {
203   return handler_list_.get();
204 }
205
206 // static
207 void BrowserPolicyConnector::SetPolicyProviderForTesting(
208     ConfigurationPolicyProvider* provider) {
209   // If this function is used by a test then it must be called before the
210   // browser is created, and GetPolicyService() gets called.
211   CHECK(!g_created_policy_service);
212   DCHECK(!g_testing_provider);
213   g_testing_provider = provider;
214 }
215
216 // static
217 bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) {
218   if (username.empty() || username.find('@') == std::string::npos) {
219     // An empty username means incognito user in case of ChromiumOS and
220     // no logged-in user in case of Chromium (SigninService). Many tests use
221     // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
222     // users.
223     return true;
224   }
225   const base::string16 domain = base::UTF8ToUTF16(
226       gaia::ExtractDomainName(gaia::CanonicalizeEmail(username)));
227   for (size_t i = 0; i < arraysize(kNonManagedDomainPatterns); i++) {
228     base::string16 pattern = base::WideToUTF16(kNonManagedDomainPatterns[i]);
229     if (MatchDomain(domain, pattern, i))
230       return true;
231   }
232   return false;
233 }
234
235 // static
236 std::string BrowserPolicyConnector::GetDeviceManagementUrl() {
237   CommandLine* command_line = CommandLine::ForCurrentProcess();
238   if (command_line->HasSwitch(switches::kDeviceManagementUrl))
239     return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl);
240   else
241     return kDefaultDeviceManagementServerUrl;
242 }
243
244 // static
245 void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) {
246   registry->RegisterIntegerPref(
247       policy_prefs::kUserPolicyRefreshRate,
248       CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
249 }
250
251 void BrowserPolicyConnector::AddPolicyProvider(
252     scoped_ptr<ConfigurationPolicyProvider> provider) {
253   policy_providers_.push_back(provider.release());
254 }
255
256 void BrowserPolicyConnector::SetPlatformPolicyProvider(
257     scoped_ptr<ConfigurationPolicyProvider> provider) {
258   CHECK(!platform_policy_provider_);
259   platform_policy_provider_ = provider.get();
260   AddPolicyProvider(provider.Pass());
261 }
262
263 }  // namespace policy