Index: remoting/host/policy_hack/policy_service_watcher.cc |
diff --git a/remoting/host/policy_hack/policy_service_watcher.cc b/remoting/host/policy_hack/policy_service_watcher.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..bdb68e502e7de2e0252c96d2b5faec89d6b2689d |
--- /dev/null |
+++ b/remoting/host/policy_hack/policy_service_watcher.cc |
@@ -0,0 +1,221 @@ |
+// Copyright 2014 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "base/files/file_path.h" |
+#include "base/single_thread_task_runner.h" |
+#include "components/policy/core/common/async_policy_loader.h" |
+#include "components/policy/core/common/async_policy_provider.h" |
+#include "components/policy/core/common/policy_namespace.h" |
+#include "components/policy/core/common/policy_service.h" |
+#include "components/policy/core/common/policy_service_impl.h" |
+#include "components/policy/core/common/schema.h" |
+#include "components/policy/core/common/schema_registry.h" |
+#include "policy/policy_constants.h" |
+#include "remoting/host/policy_hack/policy_watcher.h" |
+ |
+#if defined(OS_CHROMEOS) |
+#include "content/public/browser/browser_thread.h" |
+#elif defined(OS_WIN) |
+#include "components/policy/core/common/policy_loader_win.h" |
+#elif defined(OS_MACOSX) |
+#include "components/policy/core/common/policy_loader_mac.h" |
+#include "components/policy/core/common/preferences_mac.h" |
+#elif defined(OS_POSIX) && !defined(OS_ANDROID) |
+#include "components/policy/core/common/config_dir_policy_loader.h" |
+#endif |
+ |
+using namespace policy; |
+ |
+namespace remoting { |
+namespace policy_hack { |
+ |
+bool GetManagedPrefsDir(base::FilePath* result); |
+ |
+namespace { |
+ |
+// PolicyServiceWatcher is a concrete implementation of PolicyWatcher that wraps |
+// an instance of PolicyService. |
Mattias Nissler (ping if slow)
2015/01/06 09:06:11
Given that this is now the only implementation of
Łukasz Anforowicz
2015/01/07 17:54:14
I am not sure if I fully understand (my C++ is rus
Mattias Nissler (ping if slow)
2015/01/08 09:58:36
That is what I meant.
|
+class PolicyServiceWatcher : public PolicyWatcher, |
+ public PolicyService::Observer { |
+ public: |
+ // Constructor for the case when |policy_service| is borrowed. |
Mattias Nissler (ping if slow)
2015/01/06 09:06:12
It'd be nice to document what |task_runner| is use
Łukasz Anforowicz
2015/01/07 17:54:14
Good point.
I tried adding comments to construc
|
+ PolicyServiceWatcher( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
+ PolicyService* policy_service); |
+ |
+ // Constructor for the case when |policy_service| is owned. |
+ PolicyServiceWatcher( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
+ scoped_ptr<PolicyService> owned_policy_service, |
+ scoped_ptr<ConfigurationPolicyProvider> owned_policy_provider, |
+ scoped_ptr<SchemaRegistry> owned_schema_registry); |
+ |
+ ~PolicyServiceWatcher() override; |
+ |
+ // PolicyService::Observer interface. |
+ void OnPolicyUpdated(const PolicyNamespace& ns, |
+ const PolicyMap& previous, |
+ const PolicyMap& current) override; |
+ |
+ static PolicyNamespace GetPolicyNamespace() { |
+ return PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()); |
+ } |
+ |
+ protected: |
+ // PolicyWatcher interface. |
+ void Reload() override; |
+ void StartWatchingInternal() override; |
+ void StopWatchingInternal() override; |
+ |
+ private: |
+ PolicyService* policy_service_; |
+ |
+ // Order of fields below is important to ensure destruction takes object |
+ // dependencies into account: |
+ // - |owned_policy_service_| uses |owned_policy_provider_| |
+ // - |owned_policy_provider_| uses |owned_schema_registry_| |
+ scoped_ptr<SchemaRegistry> owned_schema_registry_; |
+ scoped_ptr<ConfigurationPolicyProvider> owned_policy_provider_; |
+ scoped_ptr<PolicyService> owned_policy_service_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(PolicyServiceWatcher); |
+}; |
+ |
+PolicyServiceWatcher::PolicyServiceWatcher( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
+ PolicyService* policy_service) |
+ : PolicyWatcher(task_runner) { |
+ policy_service_ = policy_service; |
+} |
+ |
+PolicyServiceWatcher::PolicyServiceWatcher( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
+ scoped_ptr<PolicyService> owned_policy_service, |
+ scoped_ptr<ConfigurationPolicyProvider> owned_policy_provider, |
+ scoped_ptr<SchemaRegistry> owned_schema_registry) |
+ : PolicyWatcher(task_runner), |
+ owned_schema_registry_(owned_schema_registry.Pass()), |
+ owned_policy_provider_(owned_policy_provider.Pass()), |
+ owned_policy_service_(owned_policy_service.Pass()) { |
+ policy_service_ = owned_policy_service_.get(); |
+} |
+ |
+PolicyServiceWatcher::~PolicyServiceWatcher() { |
+ if (owned_policy_provider_) { |
+ owned_policy_provider_->Shutdown(); |
+ } |
+} |
+ |
+void PolicyServiceWatcher::OnPolicyUpdated(const PolicyNamespace& ns, |
+ const PolicyMap& previous, |
+ const PolicyMap& current) { |
+ scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue()); |
+ for (PolicyMap::const_iterator it = current.begin(); it != current.end(); |
+ it++) { |
+ // TODO(lukasza): Use policy::Schema::Normalize for schema verification. |
+ policy_dict->Set(it->first, it->second.value->DeepCopy()); |
+ } |
+ UpdatePolicies(policy_dict.get()); |
+} |
+ |
+void PolicyServiceWatcher::Reload() { |
Mattias Nissler (ping if slow)
2015/01/06 09:06:12
What are the desired semantics for Reload()? This
Łukasz Anforowicz
2015/01/07 17:54:14
Presence of Reload method is an artifact from the
Mattias Nissler (ping if slow)
2015/01/08 09:58:36
OK, thanks for the explanation. Your conclusion re
Łukasz Anforowicz
2015/01/08 23:09:26
Thanks for pointing this out. This is useful to k
|
+ PolicyNamespace ns = GetPolicyNamespace(); |
+ const PolicyMap& current = policy_service_->GetPolicies(ns); |
+ OnPolicyUpdated(ns, current, current); |
+}; |
+ |
+void PolicyServiceWatcher::StartWatchingInternal() { |
+ policy_service_->AddObserver(POLICY_DOMAIN_CHROME, this); |
+ Reload(); |
+}; |
+ |
+void PolicyServiceWatcher::StopWatchingInternal() { |
+ policy_service_->RemoveObserver(POLICY_DOMAIN_CHROME, this); |
+}; |
+ |
+#if defined(OS_MACOSX) |
+ |
+// This function is based on GetManagedPolicyPath from |
+// chrome/browser/policy/chrome_browser_policy_connector.cc |
Mattias Nissler (ping if slow)
2015/01/06 09:06:11
How about moving this as a static helper to policy
Łukasz Anforowicz
2015/01/07 17:54:14
It probably makes sense and I am trying to do this
|
+base::FilePath GetManagedPolicyPath() { |
+ // This constructs the path to the plist file in which Mac OS X stores the |
+ // managed preference for the application. This is undocumented and therefore |
+ // fragile, but if it doesn't work out, AsyncPolicyLoader has a task that |
+ // polls periodically in order to reload managed preferences later even if we |
+ // missed the change. |
+ base::FilePath path; |
+ if (!GetManagedPrefsDir(&path)) |
+ return base::FilePath(); |
+ |
+ return path.Append("com.google.Chrome.plist"); |
+} |
+ |
+#endif // defined(OS_MACOSX) |
+ |
+#if !defined(OS_CHROMEOS) |
+ |
+scoped_ptr<PolicyServiceWatcher> CreateFromPolicyLoader( |
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
+ scoped_ptr<AsyncPolicyLoader> async_policy_loader) { |
+ scoped_ptr<SchemaRegistry> schema_registry(new SchemaRegistry()); |
+ schema_registry->RegisterComponent(PolicyServiceWatcher::GetPolicyNamespace(), |
+ Schema::Wrap(GetChromeSchemaData())); |
Mattias Nissler (ping if slow)
2015/01/06 09:06:12
Side note relating to the email thread: You're con
Łukasz Anforowicz
2015/01/07 17:54:14
Ack, although I am not sure about details of what
Mattias Nissler (ping if slow)
2015/01/08 09:58:36
That works, but given that the policy_templates.js
|
+ |
+ scoped_ptr<AsyncPolicyProvider> policy_provider(new AsyncPolicyProvider( |
+ schema_registry.get(), async_policy_loader.Pass())); |
+ policy_provider->Init(schema_registry.get()); |
+ |
+ PolicyServiceImpl::Providers providers; |
+ providers.push_back(policy_provider.get()); |
+ scoped_ptr<PolicyService> policy_service(new PolicyServiceImpl(providers)); |
+ |
+ return make_scoped_ptr( |
+ new PolicyServiceWatcher(task_runner, policy_service.Pass(), |
+ policy_provider.Pass(), schema_registry.Pass())); |
+} |
+ |
+#endif |
+ |
+} // anonymous namespace |
+ |
+// This function is based on CreatePlatformProvider from |
+// src/chrome/browser/policy/chrome_browser_policy_connector.cc. |
Mattias Nissler (ping if slow)
2015/01/06 09:06:12
nit: This comment will get less and less useful ov
Łukasz Anforowicz
2015/01/07 17:54:14
Done.
|
+scoped_ptr<PolicyWatcher> PolicyWatcher::Create( |
+ policy::PolicyService* policy_service, |
+ const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) { |
+#if defined(OS_CHROMEOS) |
+ DCHECK(policy_service != nullptr); |
+ return make_scoped_ptr(new PolicyServiceWatcher( |
+ content::BrowserThread::GetMessageLoopProxyForThread( |
+ content::BrowserThread::UI), |
+ policy_service)); |
+#elif defined(OS_WIN) |
+ DCHECK(policy_service == nullptr); |
+ static const wchar_t kRegistryKey[] = L"SOFTWARE\\Policies\\Google\\Chrome"; |
+ return CreateFromPolicyLoader( |
+ task_runner, scoped_ptr<AsyncPolicyLoader>( |
+ PolicyLoaderWin::Create(task_runner, kRegistryKey))); |
+#elif defined(OS_MACOSX) |
+ DCHECK(policy_service == nullptr); |
+ return CreateFromPolicyLoader( |
+ task_runner, make_scoped_ptr(new PolicyLoaderMac( |
+ task_runner, GetManagedPolicyPath(), |
+ new MacPreferences(), CFSTR("com.google.Chrome")))); |
+#elif defined(OS_POSIX) && !defined(OS_ANDROID) |
+ DCHECK(policy_service == nullptr); |
+ static const base::FilePath::CharType kPolicyDir[] = |
+ // Always read the Chrome policies (even on Chromium) so that policy |
+ // enforcement can't be bypassed by running Chromium. |
Mattias Nissler (ping if slow)
2015/01/06 09:06:11
nit: This comment should go before line 207.
Łukasz Anforowicz
2015/01/07 17:54:14
Done (I was just copying the formatting from polic
|
+ FILE_PATH_LITERAL("/etc/opt/chrome/policies"); |
Mattias Nissler (ping if slow)
2015/01/06 09:06:12
I don't think the reasoning in the comment makes s
Łukasz Anforowicz
2015/01/07 17:54:14
Ack and we should definitely discuss this (maybe y
Mattias Nissler (ping if slow)
2015/01/08 09:58:36
OK, fair enough.
|
+ return CreateFromPolicyLoader( |
+ task_runner, |
+ make_scoped_ptr(new ConfigDirPolicyLoader( |
+ task_runner, base::FilePath(kPolicyDir), POLICY_SCOPE_MACHINE))); |
+#else |
+#error OS that is not yet supported by PolicyWatcher code. |
+#endif |
+} |
+ |
+} // namespace policy_hack |
+} // namespace remoting |