| Index: remoting/host/policy_hack/policy_watcher.cc
|
| diff --git a/remoting/host/policy_hack/policy_watcher.cc b/remoting/host/policy_hack/policy_watcher.cc
|
| index 6d93ff9d2439d7c30329a1f32cea1d702d982a65..ff0da0e6215753a43618da8682e62042da1b2899 100644
|
| --- a/remoting/host/policy_hack/policy_watcher.cc
|
| +++ b/remoting/host/policy_hack/policy_watcher.cc
|
| @@ -9,10 +9,16 @@
|
|
|
| #include "base/bind.h"
|
| #include "base/compiler_specific.h"
|
| +#include "base/files/file_path.h"
|
| #include "base/location.h"
|
| -#include "base/memory/weak_ptr.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/values.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_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/dns_blackhole_checker.h"
|
|
|
| @@ -20,9 +26,22 @@
|
| #include "base/json/json_reader.h"
|
| #endif
|
|
|
| +#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
|
| +
|
| namespace remoting {
|
| namespace policy_hack {
|
|
|
| +namespace key = ::policy::key;
|
| +
|
| namespace {
|
|
|
| // Copies all policy values from one dictionary to another, using values from
|
| @@ -54,7 +73,7 @@ scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults(
|
| #if !defined(NDEBUG)
|
| // Replace values with those specified in DebugOverridePolicies, if present.
|
| std::string policy_overrides;
|
| - if (from->GetString(policy::key::kRemoteAccessHostDebugOverridePolicies,
|
| + if (from->GetString(key::kRemoteAccessHostDebugOverridePolicies,
|
| &policy_overrides)) {
|
| scoped_ptr<base::Value> value(base::JSONReader::Read(policy_overrides));
|
| const base::DictionaryValue* override_values;
|
| @@ -67,101 +86,55 @@ scoped_ptr<base::DictionaryValue> CopyGoodValuesAndAddDefaults(
|
| return to.Pass();
|
| }
|
|
|
| -} // namespace
|
| -
|
| -PolicyWatcher::PolicyWatcher(
|
| - const scoped_refptr<base::SingleThreadTaskRunner>& task_runner)
|
| - : task_runner_(task_runner),
|
| - transient_policy_error_retry_counter_(0),
|
| - old_policies_(new base::DictionaryValue()),
|
| - default_values_(new base::DictionaryValue()),
|
| - weak_factory_(this) {
|
| - // Initialize the default values for each policy.
|
| - default_values_->SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
|
| - true);
|
| - default_values_->SetBoolean(policy::key::kRemoteAccessHostRequireTwoFactor,
|
| - false);
|
| - default_values_->SetBoolean(policy::key::kRemoteAccessHostRequireCurtain,
|
| - false);
|
| - default_values_->SetBoolean(policy::key::kRemoteAccessHostMatchUsername,
|
| - false);
|
| - default_values_->SetString(policy::key::kRemoteAccessHostDomain,
|
| - std::string());
|
| - default_values_->SetString(policy::key::kRemoteAccessHostTalkGadgetPrefix,
|
| - kDefaultHostTalkGadgetPrefix);
|
| - default_values_->SetString(policy::key::kRemoteAccessHostTokenUrl,
|
| - std::string());
|
| - default_values_->SetString(policy::key::kRemoteAccessHostTokenValidationUrl,
|
| - std::string());
|
| - default_values_->SetString(
|
| - policy::key::kRemoteAccessHostTokenValidationCertificateIssuer,
|
| - std::string());
|
| - default_values_->SetBoolean(policy::key::kRemoteAccessHostAllowClientPairing,
|
| - true);
|
| - default_values_->SetBoolean(policy::key::kRemoteAccessHostAllowGnubbyAuth,
|
| - true);
|
| - default_values_->SetBoolean(
|
| - policy::key::kRemoteAccessHostAllowRelayedConnection, true);
|
| - default_values_->SetString(policy::key::kRemoteAccessHostUdpPortRange, "");
|
| -#if !defined(NDEBUG)
|
| - default_values_->SetString(
|
| - policy::key::kRemoteAccessHostDebugOverridePolicies, std::string());
|
| -#endif
|
| -
|
| - // Initialize the fall-back values to use for unreadable policies.
|
| - // For most policies these match the defaults.
|
| - bad_type_values_.reset(default_values_->DeepCopy());
|
| - bad_type_values_->SetBoolean(policy::key::kRemoteAccessHostFirewallTraversal,
|
| - false);
|
| - bad_type_values_->SetBoolean(
|
| - policy::key::kRemoteAccessHostAllowRelayedConnection, false);
|
| +policy::PolicyNamespace GetPolicyNamespace() {
|
| + return policy::PolicyNamespace(policy::POLICY_DOMAIN_CHROME, std::string());
|
| }
|
|
|
| -PolicyWatcher::~PolicyWatcher() {
|
| -}
|
| +} // namespace
|
|
|
| void PolicyWatcher::StartWatching(
|
| const PolicyUpdatedCallback& policy_updated_callback,
|
| const PolicyErrorCallback& policy_error_callback) {
|
| - if (!OnPolicyWatcherThread()) {
|
| - task_runner_->PostTask(FROM_HERE,
|
| - base::Bind(&PolicyWatcher::StartWatching,
|
| - base::Unretained(this),
|
| - policy_updated_callback,
|
| - policy_error_callback));
|
| + if (!OnPolicyServiceThread()) {
|
| + policy_service_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&PolicyWatcher::StartWatching, base::Unretained(this),
|
| + policy_updated_callback, policy_error_callback));
|
| return;
|
| }
|
|
|
| policy_updated_callback_ = policy_updated_callback;
|
| policy_error_callback_ = policy_error_callback;
|
| - StartWatchingInternal();
|
| +
|
| + // Listen for future policy changes.
|
| + policy_service_->AddObserver(policy::POLICY_DOMAIN_CHROME, this);
|
| +
|
| + // Process current policy state.
|
| + if (policy_service_->IsInitializationComplete(policy::POLICY_DOMAIN_CHROME)) {
|
| + OnPolicyServiceInitialized(policy::POLICY_DOMAIN_CHROME);
|
| + }
|
| }
|
|
|
| void PolicyWatcher::StopWatching(const base::Closure& stopped_callback) {
|
| - task_runner_->PostTaskAndReply(
|
| - FROM_HERE, base::Bind(&PolicyWatcher::StopWatchingOnPolicyWatcherThread,
|
| + policy_service_task_runner_->PostTaskAndReply(
|
| + FROM_HERE, base::Bind(&PolicyWatcher::StopWatchingOnPolicyServiceThread,
|
| base::Unretained(this)),
|
| stopped_callback);
|
| }
|
|
|
| -void PolicyWatcher::StopWatchingOnPolicyWatcherThread() {
|
| - StopWatchingInternal();
|
| - weak_factory_.InvalidateWeakPtrs();
|
| +void PolicyWatcher::StopWatchingOnPolicyServiceThread() {
|
| + policy_service_->RemoveObserver(policy::POLICY_DOMAIN_CHROME, this);
|
| policy_updated_callback_.Reset();
|
| policy_error_callback_.Reset();
|
| }
|
|
|
| -const base::DictionaryValue& PolicyWatcher::Defaults() const {
|
| - return *default_values_;
|
| -}
|
| -
|
| -bool PolicyWatcher::OnPolicyWatcherThread() const {
|
| - return task_runner_->BelongsToCurrentThread();
|
| +bool PolicyWatcher::OnPolicyServiceThread() const {
|
| + return policy_service_task_runner_->BelongsToCurrentThread();
|
| }
|
|
|
| void PolicyWatcher::UpdatePolicies(
|
| const base::DictionaryValue* new_policies_raw) {
|
| - DCHECK(OnPolicyWatcherThread());
|
| + DCHECK(OnPolicyServiceThread());
|
|
|
| transient_policy_error_retry_counter_ = 0;
|
|
|
| @@ -205,5 +178,143 @@ void PolicyWatcher::SignalTransientPolicyError() {
|
| }
|
| }
|
|
|
| +PolicyWatcher::PolicyWatcher(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>&
|
| + policy_service_task_runner,
|
| + policy::PolicyService* policy_service,
|
| + scoped_ptr<policy::PolicyService> owned_policy_service,
|
| + scoped_ptr<policy::ConfigurationPolicyProvider> owned_policy_provider,
|
| + scoped_ptr<policy::SchemaRegistry> owned_schema_registry)
|
| + : policy_service_task_runner_(policy_service_task_runner),
|
| + transient_policy_error_retry_counter_(0),
|
| + old_policies_(new base::DictionaryValue()),
|
| + default_values_(new base::DictionaryValue()),
|
| + policy_service_(policy_service),
|
| + owned_schema_registry_(owned_schema_registry.Pass()),
|
| + owned_policy_provider_(owned_policy_provider.Pass()),
|
| + owned_policy_service_(owned_policy_service.Pass()) {
|
| + // Initialize the default values for each policy.
|
| + default_values_->SetBoolean(key::kRemoteAccessHostFirewallTraversal, true);
|
| + default_values_->SetBoolean(key::kRemoteAccessHostRequireTwoFactor, false);
|
| + default_values_->SetBoolean(key::kRemoteAccessHostRequireCurtain, false);
|
| + default_values_->SetBoolean(key::kRemoteAccessHostMatchUsername, false);
|
| + default_values_->SetString(key::kRemoteAccessHostDomain, std::string());
|
| + default_values_->SetString(key::kRemoteAccessHostTalkGadgetPrefix,
|
| + kDefaultHostTalkGadgetPrefix);
|
| + default_values_->SetString(key::kRemoteAccessHostTokenUrl, std::string());
|
| + default_values_->SetString(key::kRemoteAccessHostTokenValidationUrl,
|
| + std::string());
|
| + default_values_->SetString(
|
| + key::kRemoteAccessHostTokenValidationCertificateIssuer, std::string());
|
| + default_values_->SetBoolean(key::kRemoteAccessHostAllowClientPairing, true);
|
| + default_values_->SetBoolean(key::kRemoteAccessHostAllowGnubbyAuth, true);
|
| + default_values_->SetBoolean(key::kRemoteAccessHostAllowRelayedConnection,
|
| + true);
|
| + default_values_->SetString(key::kRemoteAccessHostUdpPortRange, "");
|
| +#if !defined(NDEBUG)
|
| + default_values_->SetString(key::kRemoteAccessHostDebugOverridePolicies,
|
| + std::string());
|
| +#endif
|
| +
|
| + // Initialize the fall-back values to use for unreadable policies.
|
| + // For most policies these match the defaults.
|
| + bad_type_values_.reset(default_values_->DeepCopy());
|
| + bad_type_values_->SetBoolean(key::kRemoteAccessHostFirewallTraversal, false);
|
| + bad_type_values_->SetBoolean(key::kRemoteAccessHostAllowRelayedConnection,
|
| + false);
|
| +}
|
| +
|
| +PolicyWatcher::~PolicyWatcher() {
|
| + if (owned_policy_provider_) {
|
| + owned_policy_provider_->Shutdown();
|
| + }
|
| +}
|
| +
|
| +void PolicyWatcher::OnPolicyUpdated(const policy::PolicyNamespace& ns,
|
| + const policy::PolicyMap& previous,
|
| + const policy::PolicyMap& current) {
|
| + scoped_ptr<base::DictionaryValue> policy_dict(new base::DictionaryValue());
|
| + for (auto 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 PolicyWatcher::OnPolicyServiceInitialized(policy::PolicyDomain domain) {
|
| + policy::PolicyNamespace ns = GetPolicyNamespace();
|
| + const policy::PolicyMap& current = policy_service_->GetPolicies(ns);
|
| + OnPolicyUpdated(ns, current, current);
|
| +}
|
| +
|
| +scoped_ptr<PolicyWatcher> PolicyWatcher::CreateFromPolicyLoader(
|
| + const scoped_refptr<base::SingleThreadTaskRunner>&
|
| + policy_service_task_runner,
|
| + scoped_ptr<policy::AsyncPolicyLoader> async_policy_loader) {
|
| + // TODO(lukasza): Schema below should ideally only cover Chromoting-specific
|
| + // policies (expecting perf and maintanability improvement, but no functional
|
| + // impact).
|
| + policy::Schema schema = policy::Schema::Wrap(policy::GetChromeSchemaData());
|
| +
|
| + scoped_ptr<policy::SchemaRegistry> schema_registry(
|
| + new policy::SchemaRegistry());
|
| + schema_registry->RegisterComponent(GetPolicyNamespace(), schema);
|
| +
|
| + scoped_ptr<policy::AsyncPolicyProvider> policy_provider(
|
| + new policy::AsyncPolicyProvider(schema_registry.get(),
|
| + async_policy_loader.Pass()));
|
| + policy_provider->Init(schema_registry.get());
|
| +
|
| + policy::PolicyServiceImpl::Providers providers;
|
| + providers.push_back(policy_provider.get());
|
| + scoped_ptr<policy::PolicyService> policy_service(
|
| + new policy::PolicyServiceImpl(providers));
|
| +
|
| + policy::PolicyService* borrowed_policy_service = policy_service.get();
|
| + return make_scoped_ptr(new PolicyWatcher(
|
| + policy_service_task_runner, borrowed_policy_service,
|
| + policy_service.Pass(), policy_provider.Pass(), schema_registry.Pass()));
|
| +}
|
| +
|
| +scoped_ptr<PolicyWatcher> PolicyWatcher::Create(
|
| + policy::PolicyService* policy_service,
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& network_task_runner) {
|
| +#if defined(OS_CHROMEOS)
|
| + DCHECK(policy_service);
|
| + return make_scoped_ptr(
|
| + new PolicyWatcher(content::BrowserThread::GetMessageLoopProxyForThread(
|
| + content::BrowserThread::UI),
|
| + policy_service, nullptr, nullptr, nullptr));
|
| +#elif defined(OS_WIN)
|
| + DCHECK(!policy_service);
|
| + // Always read the Chrome policies (even on Chromium) so that policy
|
| + // enforcement can't be bypassed by running Chromium.
|
| + // Note that this comment applies to all of Win/Mac/Posix branches below.
|
| + static const wchar_t kRegistryKey[] = L"SOFTWARE\\Policies\\Google\\Chrome";
|
| + return PolicyWatcher::CreateFromPolicyLoader(
|
| + network_task_runner,
|
| + policy::PolicyLoaderWin::Create(network_task_runner, kRegistryKey));
|
| +#elif defined(OS_MACOSX)
|
| + CFStringRef bundle_id = CFSTR("com.google.Chrome");
|
| + DCHECK(!policy_service);
|
| + return PolicyWatcher::CreateFromPolicyLoader(
|
| + network_task_runner,
|
| + make_scoped_ptr(new policy::PolicyLoaderMac(
|
| + network_task_runner,
|
| + policy::PolicyLoaderMac::GetManagedPolicyPath(bundle_id),
|
| + new MacPreferences(), bundle_id)));
|
| +#elif defined(OS_POSIX) && !defined(OS_ANDROID)
|
| + DCHECK(!policy_service);
|
| + static const base::FilePath::CharType kPolicyDir[] =
|
| + FILE_PATH_LITERAL("/etc/opt/chrome/policies");
|
| + return PolicyWatcher::CreateFromPolicyLoader(
|
| + network_task_runner, make_scoped_ptr(new policy::ConfigDirPolicyLoader(
|
| + network_task_runner, base::FilePath(kPolicyDir),
|
| + policy::POLICY_SCOPE_MACHINE)));
|
| +#else
|
| +#error OS that is not yet supported by PolicyWatcher code.
|
| +#endif
|
| +}
|
| +
|
| } // namespace policy_hack
|
| } // namespace remoting
|
|
|