• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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_service_impl.h"
23 #include "components/policy/core/common/policy_statistics_collector.h"
24 #include "components/policy/core/common/policy_switches.h"
25 #include "google_apis/gaia/gaia_auth_util.h"
26 #include "net/url_request/url_request_context_getter.h"
27 #include "policy/policy_constants.h"
28 #include "third_party/icu/source/i18n/unicode/regex.h"
29 
30 namespace policy {
31 
32 namespace {
33 
34 // The URL for the device management server.
35 const char kDefaultDeviceManagementServerUrl[] =
36     "https://m.google.com/devicemanagement/data/api";
37 
38 // Used in BrowserPolicyConnector::SetPolicyProviderForTesting.
39 bool g_created_policy_service = false;
40 ConfigurationPolicyProvider* g_testing_provider = NULL;
41 
42 // Returns true if |domain| matches the regex |pattern|.
MatchDomain(const base::string16 & domain,const base::string16 & pattern)43 bool MatchDomain(const base::string16& domain, const base::string16& pattern) {
44   UErrorCode status = U_ZERO_ERROR;
45   const icu::UnicodeString icu_pattern(pattern.data(), pattern.length());
46   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 
BrowserPolicyConnector(const HandlerListFactory & handler_list_factory)58 BrowserPolicyConnector::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 
~BrowserPolicyConnector()75 BrowserPolicyConnector::~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 
Init(PrefService * local_state,scoped_refptr<net::URLRequestContextGetter> request_context,scoped_ptr<DeviceManagementService> device_management_service)85 void 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 
Shutdown()110 void 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   g_created_policy_service = false;
120   device_management_service_.reset();
121 }
122 
GetPolicyService()123 PolicyService* BrowserPolicyConnector::GetPolicyService() {
124   if (!policy_service_) {
125     g_created_policy_service = true;
126     std::vector<ConfigurationPolicyProvider*> providers;
127     if (g_testing_provider) {
128       providers.push_back(g_testing_provider);
129     } else {
130       providers.resize(policy_providers_.size());
131       std::copy(policy_providers_.begin(),
132                 policy_providers_.end(),
133                 providers.begin());
134     }
135     policy_service_.reset(new PolicyServiceImpl(providers));
136   }
137   return policy_service_.get();
138 }
139 
GetPlatformProvider()140 ConfigurationPolicyProvider* BrowserPolicyConnector::GetPlatformProvider() {
141   if (g_testing_provider)
142     return g_testing_provider;
143   return platform_policy_provider_;
144 }
145 
GetChromeSchema() const146 const Schema& BrowserPolicyConnector::GetChromeSchema() const {
147   return chrome_schema_;
148 }
149 
GetSchemaRegistry()150 CombinedSchemaRegistry* BrowserPolicyConnector::GetSchemaRegistry() {
151   return &schema_registry_;
152 }
153 
ScheduleServiceInitialization(int64 delay_milliseconds)154 void BrowserPolicyConnector::ScheduleServiceInitialization(
155     int64 delay_milliseconds) {
156   // Skip device initialization if the BrowserPolicyConnector was never
157   // initialized (unit tests).
158   if (device_management_service_)
159     device_management_service_->ScheduleInitialization(delay_milliseconds);
160 }
161 
162 const ConfigurationPolicyHandlerList*
GetHandlerList() const163     BrowserPolicyConnector::GetHandlerList() const {
164   return handler_list_.get();
165 }
166 
167 // static
SetPolicyProviderForTesting(ConfigurationPolicyProvider * provider)168 void BrowserPolicyConnector::SetPolicyProviderForTesting(
169     ConfigurationPolicyProvider* provider) {
170   // If this function is used by a test then it must be called before the
171   // browser is created, and GetPolicyService() gets called.
172   CHECK(!g_created_policy_service);
173   DCHECK(!g_testing_provider);
174   g_testing_provider = provider;
175 }
176 
177 // static
IsNonEnterpriseUser(const std::string & username)178 bool BrowserPolicyConnector::IsNonEnterpriseUser(const std::string& username) {
179   if (username.empty() || username.find('@') == std::string::npos) {
180     // An empty username means incognito user in case of ChromiumOS and
181     // no logged-in user in case of Chromium (SigninService). Many tests use
182     // nonsense email addresses (e.g. 'test') so treat those as non-enterprise
183     // users.
184     return true;
185   }
186 
187   // Exclude many of the larger public email providers as we know these users
188   // are not from hosted enterprise domains.
189   static const wchar_t* kNonManagedDomainPatterns[] = {
190     L"aol\\.com",
191     L"googlemail\\.com",
192     L"gmail\\.com",
193     L"hotmail(\\.co|\\.com|)\\.[^.]+", // hotmail.com, hotmail.it, hotmail.co.uk
194     L"live\\.com",
195     L"mail\\.ru",
196     L"msn\\.com",
197     L"qq\\.com",
198     L"yahoo(\\.co|\\.com|)\\.[^.]+", // yahoo.com, yahoo.co.uk, yahoo.com.tw
199     L"yandex\\.ru",
200   };
201   const base::string16 domain = base::UTF8ToUTF16(
202       gaia::ExtractDomainName(gaia::CanonicalizeEmail(username)));
203   for (size_t i = 0; i < arraysize(kNonManagedDomainPatterns); i++) {
204     base::string16 pattern = base::WideToUTF16(kNonManagedDomainPatterns[i]);
205     if (MatchDomain(domain, pattern))
206       return true;
207   }
208   return false;
209 }
210 
211 // static
GetDeviceManagementUrl()212 std::string BrowserPolicyConnector::GetDeviceManagementUrl() {
213   CommandLine* command_line = CommandLine::ForCurrentProcess();
214   if (command_line->HasSwitch(switches::kDeviceManagementUrl))
215     return command_line->GetSwitchValueASCII(switches::kDeviceManagementUrl);
216   else
217     return kDefaultDeviceManagementServerUrl;
218 }
219 
220 // static
RegisterPrefs(PrefRegistrySimple * registry)221 void BrowserPolicyConnector::RegisterPrefs(PrefRegistrySimple* registry) {
222   registry->RegisterIntegerPref(
223       policy_prefs::kUserPolicyRefreshRate,
224       CloudPolicyRefreshScheduler::kDefaultRefreshDelayMs);
225 }
226 
AddPolicyProvider(scoped_ptr<ConfigurationPolicyProvider> provider)227 void BrowserPolicyConnector::AddPolicyProvider(
228     scoped_ptr<ConfigurationPolicyProvider> provider) {
229   policy_providers_.push_back(provider.release());
230 }
231 
SetPlatformPolicyProvider(scoped_ptr<ConfigurationPolicyProvider> provider)232 void BrowserPolicyConnector::SetPlatformPolicyProvider(
233     scoped_ptr<ConfigurationPolicyProvider> provider) {
234   CHECK(!platform_policy_provider_);
235   platform_policy_provider_ = provider.get();
236   AddPolicyProvider(provider.Pass());
237 }
238 
239 }  // namespace policy
240