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