190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/policy/policy_domain_descriptor.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/logging.h"
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/stl_util.h"
990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "base/values.h"
1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/policy/policy_bundle.h"
1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/policy/policy_map.h"
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/common/policy/policy_schema.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace policy {
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
1890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool Matches(const PolicySchema* schema, const base::Value& value) {
1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!schema) {
2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // Schema not found, invalid entry.
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!value.IsType(schema->type()))
2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const base::DictionaryValue* dict = NULL;
2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const base::ListValue* list = NULL;
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (value.GetAsDictionary(&dict)) {
3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         it.Advance()) {
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!Matches(schema->GetSchemaForProperty(it.key()), it.value()))
3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else if (value.GetAsList(&list)) {
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (base::ListValue::const_iterator it = list->begin();
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         it != list->end(); ++it) {
3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!*it || !Matches(schema->GetSchemaForItems(), **it))
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        return false;
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return true;
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PolicyDomainDescriptor::PolicyDomainDescriptor(PolicyDomain domain)
4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : domain_(domain) {}
5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PolicyDomainDescriptor::RegisterComponent(
5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const std::string& component_id,
5390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    scoped_ptr<PolicySchema> schema) {
5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const PolicySchema*& entry = schema_map_[component_id];
5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  delete entry;
5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  entry = schema.release();
5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void PolicyDomainDescriptor::FilterBundle(PolicyBundle* bundle) const {
6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Chrome policies are not filtered, so that typos appear in about:policy.
6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_NE(POLICY_DOMAIN_CHROME, domain_);
6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (PolicyBundle::iterator it_bundle = bundle->begin();
6490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it_bundle != bundle->end(); ++it_bundle) {
6590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const PolicyNamespace& ns = it_bundle->first;
6690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (ns.domain != domain_)
6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    SchemaMap::const_iterator it_schema = schema_map_.find(ns.component_id);
7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (it_schema == schema_map_.end()) {
7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      // Component ID not found.
7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      it_bundle->second->Clear();
7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // TODO(joaodasilva): if a component is registered but doesn't have a schema
7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // then its policies aren't filtered. This behavior is enabled for M29 to
7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // allow a graceful update of the Legacy Browser Support extension; it'll
7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // be removed for M30. http://crbug.com/240704
8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!it_schema->second)
8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    const PolicySchema* component_schema = it_schema->second;
8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PolicyMap* map = it_bundle->second;
8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    for (PolicyMap::const_iterator it_map = map->begin();
8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)         it_map != map->end();) {
8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const std::string& policy_name = it_map->first;
8890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const base::Value* policy_value = it_map->second.value;
8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      const PolicySchema* policy_schema =
9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          component_schema->GetSchemaForProperty(policy_name);
9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      ++it_map;
9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!policy_value || !Matches(policy_schema, *policy_value))
9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        map->Erase(policy_name);
9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)PolicyDomainDescriptor::~PolicyDomainDescriptor() {
9990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  STLDeleteValues(&schema_map_);
10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
10290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}  // namespace policy
103