diff options
author | joaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-25 13:19:08 +0000 |
---|---|---|
committer | joaodasilva@chromium.org <joaodasilva@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-09-25 13:19:08 +0000 |
commit | bad38cb105657bee72df7f78bb44e9e75f9ec18c (patch) | |
tree | f631962771627a5e696a888280d03d05c22a36ad | |
parent | 42887efa99e289a175fb019ae96bffada8118cdd (diff) | |
download | chromium_src-bad38cb105657bee72df7f78bb44e9e75f9ec18c.zip chromium_src-bad38cb105657bee72df7f78bb44e9e75f9ec18c.tar.gz chromium_src-bad38cb105657bee72df7f78bb44e9e75f9ec18c.tar.bz2 |
Refactored users of PolicySchema to use the new policy::Schema class.
PolicySchema was used to contain the JSON schema describing the valid values for
each known policy. This is now done by the policy::Schema class, which supports
loading the Chrome policy schema at startup without having to parse a JSON blob.
BUG=270667
R=bartfab@chromium.org, dubroy@chromium.org, joi@chromium.org, kalman@chromium.org
Review URL: https://codereview.chromium.org/24367003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@225181 0039d316-1c4b-4281-b951-d872f2087c98
18 files changed, 140 insertions, 578 deletions
diff --git a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc index 13a5fde..9301bda 100644 --- a/chrome/browser/extensions/api/storage/managed_value_store_cache.cc +++ b/chrome/browser/extensions/api/storage/managed_value_store_cache.cc @@ -27,7 +27,7 @@ #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_set.h" #include "chrome/common/extensions/permissions/api_permission.h" -#include "components/policy/core/common/policy_schema.h" +#include "components/policy/core/common/schema.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h" @@ -137,10 +137,10 @@ void ManagedValueStoreCache::ExtensionTracker::LoadSchemas( std::string schema_file; if (!(*it)->manifest()->GetString( manifest_keys::kStorageManagedSchema, &schema_file)) { - // TODO(joaodasilva): Remove this for M30. http://crbug.com/240704 + // TODO(joaodasilva): Remove this for M32. http://crbug.com/240704 if ((*it)->HasAPIPermission(APIPermission::kStorage)) { descriptor->RegisterComponent((*it)->id(), - scoped_ptr<policy::PolicySchema>()); + scoped_ptr<policy::SchemaOwner>()); } else { NOTREACHED(); } @@ -149,7 +149,7 @@ void ManagedValueStoreCache::ExtensionTracker::LoadSchemas( // The extension should have been validated, so assume the schema exists // and is valid. std::string error; - scoped_ptr<policy::PolicySchema> schema = + scoped_ptr<policy::SchemaOwner> schema = StorageSchemaManifestHandler::GetSchema(it->get(), &error); CHECK(schema) << error; descriptor->RegisterComponent((*it)->id(), schema.Pass()); diff --git a/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc b/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc index d01b453..b29d8b6 100644 --- a/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc +++ b/chrome/browser/policy/cloud/component_cloud_policy_service_unittest.cc @@ -24,7 +24,7 @@ #include "chrome/browser/policy/policy_types.h" #include "chrome/browser/policy/proto/cloud/chrome_extension_policy.pb.h" #include "chrome/browser/policy/proto/cloud/device_management_backend.pb.h" -#include "components/policy/core/common/policy_schema.h" +#include "components/policy/core/common/schema.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_browser_thread.h" #include "net/url_request/test_url_fetcher_factory.h" @@ -61,7 +61,6 @@ const char kTestPolicy[] = const char kTestSchema[] = "{" - " \"$schema\": \"http://json-schema.org/draft-03/schema#\"," " \"type\": \"object\"," " \"properties\": {" " \"Name\": { \"type\": \"string\" }," @@ -194,9 +193,9 @@ class ComponentCloudPolicyServiceTest : public testing::Test { return builder_.GetBlob(); } - scoped_ptr<PolicySchema> CreateTestSchema() { + scoped_ptr<SchemaOwner> CreateTestSchema() { std::string error; - scoped_ptr<PolicySchema> schema = PolicySchema::Parse(kTestSchema, &error); + scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse(kTestSchema, &error); EXPECT_TRUE(schema) << error; return schema.Pass(); } diff --git a/chrome/browser/policy/policy_domain_descriptor.cc b/chrome/browser/policy/policy_domain_descriptor.cc index c841a55..f054710 100644 --- a/chrome/browser/policy/policy_domain_descriptor.cc +++ b/chrome/browser/policy/policy_domain_descriptor.cc @@ -9,19 +9,18 @@ #include "base/values.h" #include "chrome/browser/policy/policy_bundle.h" #include "chrome/browser/policy/policy_map.h" -#include "components/policy/core/common/policy_schema.h" namespace policy { namespace { -bool Matches(const PolicySchema* schema, const base::Value& value) { - if (!schema) { +bool Matches(Schema schema, const base::Value& value) { + if (!schema.valid()) { // Schema not found, invalid entry. return false; } - if (!value.IsType(schema->type())) + if (!value.IsType(schema.type())) return false; const base::DictionaryValue* dict = NULL; @@ -29,13 +28,13 @@ bool Matches(const PolicySchema* schema, const base::Value& value) { if (value.GetAsDictionary(&dict)) { for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd(); it.Advance()) { - if (!Matches(schema->GetSchemaForProperty(it.key()), it.value())) + if (!Matches(schema.GetProperty(it.key()), it.value())) return false; } } else if (value.GetAsList(&list)) { for (base::ListValue::const_iterator it = list->begin(); it != list->end(); ++it) { - if (!*it || !Matches(schema->GetSchemaForItems(), **it)) + if (!*it || !Matches(schema.GetItems(), **it)) return false; } } @@ -50,10 +49,11 @@ PolicyDomainDescriptor::PolicyDomainDescriptor(PolicyDomain domain) void PolicyDomainDescriptor::RegisterComponent( const std::string& component_id, - scoped_ptr<PolicySchema> schema) { - const PolicySchema*& entry = schema_map_[component_id]; + scoped_ptr<SchemaOwner> schema) { + SchemaOwner*& entry = schema_owner_map_[component_id]; delete entry; entry = schema.release(); + schema_map_[component_id] = entry ? entry->schema() : Schema(); } void PolicyDomainDescriptor::FilterBundle(PolicyBundle* bundle) const { @@ -76,18 +76,17 @@ void PolicyDomainDescriptor::FilterBundle(PolicyBundle* bundle) const { // TODO(joaodasilva): if a component is registered but doesn't have a schema // then its policies aren't filtered. This behavior is enabled for M29 to // allow a graceful update of the Legacy Browser Support extension; it'll - // be removed for M30. http://crbug.com/240704 - if (!it_schema->second) + // be removed for M32. http://crbug.com/240704 + Schema schema = it_schema->second; + if (!schema.valid()) continue; - const PolicySchema* component_schema = it_schema->second; PolicyMap* map = it_bundle->second; for (PolicyMap::const_iterator it_map = map->begin(); it_map != map->end();) { const std::string& policy_name = it_map->first; const base::Value* policy_value = it_map->second.value; - const PolicySchema* policy_schema = - component_schema->GetSchemaForProperty(policy_name); + Schema policy_schema = schema.GetProperty(policy_name); ++it_map; if (!policy_value || !Matches(policy_schema, *policy_value)) map->Erase(policy_name); @@ -96,7 +95,7 @@ void PolicyDomainDescriptor::FilterBundle(PolicyBundle* bundle) const { } PolicyDomainDescriptor::~PolicyDomainDescriptor() { - STLDeleteValues(&schema_map_); + STLDeleteValues(&schema_owner_map_); } } // namespace policy diff --git a/chrome/browser/policy/policy_domain_descriptor.h b/chrome/browser/policy/policy_domain_descriptor.h index daa3d56..2106633 100644 --- a/chrome/browser/policy/policy_domain_descriptor.h +++ b/chrome/browser/policy/policy_domain_descriptor.h @@ -12,18 +12,18 @@ #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" #include "chrome/browser/policy/policy_service.h" +#include "components/policy/core/common/schema.h" namespace policy { class PolicyBundle; -class PolicySchema; // For each policy domain, this class keeps the complete list of valid -// components for that domain, and the PolicySchema for each component. +// components for that domain, and the Schema for each component. class PolicyDomainDescriptor : public base::RefCountedThreadSafe<PolicyDomainDescriptor> { public: - typedef std::map<std::string, const PolicySchema*> SchemaMap; + typedef std::map<std::string, Schema> SchemaMap; explicit PolicyDomainDescriptor(PolicyDomain domain); @@ -34,17 +34,21 @@ class PolicyDomainDescriptor // |schema|. This registration overrides any previously set schema for this // component. void RegisterComponent(const std::string& component_id, - scoped_ptr<PolicySchema> schema); + scoped_ptr<SchemaOwner> schema); // Removes all the policies in |bundle| that don't match this descriptor. // Policies of domains other than |domain_| are ignored. void FilterBundle(PolicyBundle* bundle) const; private: + typedef std::map<std::string, SchemaOwner*> SchemaOwnerMap; + friend class base::RefCountedThreadSafe<PolicyDomainDescriptor>; + ~PolicyDomainDescriptor(); PolicyDomain domain_; + SchemaOwnerMap schema_owner_map_; SchemaMap schema_map_; DISALLOW_COPY_AND_ASSIGN(PolicyDomainDescriptor); diff --git a/chrome/browser/policy/policy_domain_descriptor_unittest.cc b/chrome/browser/policy/policy_domain_descriptor_unittest.cc index 9a03f8e..4ef89fc 100644 --- a/chrome/browser/policy/policy_domain_descriptor_unittest.cc +++ b/chrome/browser/policy/policy_domain_descriptor_unittest.cc @@ -13,7 +13,6 @@ #include "chrome/browser/policy/external_data_manager.h" #include "chrome/browser/policy/policy_bundle.h" #include "chrome/browser/policy/policy_map.h" -#include "components/policy/core/common/policy_schema.h" #include "testing/gtest/include/gtest/gtest.h" namespace policy { @@ -37,9 +36,8 @@ TEST_F(PolicyDomainDescriptorTest, FilterBundle) { EXPECT_TRUE(descriptor->components().empty()); std::string error; - scoped_ptr<PolicySchema> schema = PolicySchema::Parse( + scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse( "{" - " \"$schema\":\"http://json-schema.org/draft-03/schema#\"," " \"type\":\"object\"," " \"properties\": {" " \"Array\": {" @@ -147,4 +145,74 @@ TEST_F(PolicyDomainDescriptorTest, FilterBundle) { EXPECT_TRUE(bundle.Equals(empty_bundle)); } +TEST_F(PolicyDomainDescriptorTest, LegacyComponents) { + scoped_refptr<PolicyDomainDescriptor> descriptor = + new PolicyDomainDescriptor(POLICY_DOMAIN_EXTENSIONS); + EXPECT_EQ(POLICY_DOMAIN_EXTENSIONS, descriptor->domain()); + EXPECT_TRUE(descriptor->components().empty()); + + std::string error; + scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse( + "{" + " \"type\":\"object\"," + " \"properties\": {" + " \"String\": { \"type\": \"string\" }" + " }" + "}", &error); + ASSERT_TRUE(schema) << error; + + descriptor->RegisterComponent("with-schema", schema.Pass()); + descriptor->RegisterComponent("without-schema", scoped_ptr<SchemaOwner>()); + + EXPECT_EQ(2u, descriptor->components().size()); + + // |bundle| contains policies loaded by a policy provider. + PolicyBundle bundle; + + // Known components with schemas are filtered. + PolicyNamespace extension_ns(POLICY_DOMAIN_EXTENSIONS, "with-schema"); + bundle.Get(extension_ns).Set("String", + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue("value 1"), + NULL); + + // Known components without a schema are not filtered. + PolicyNamespace without_schema_ns(POLICY_DOMAIN_EXTENSIONS, "without-schema"); + bundle.Get(without_schema_ns).Set("Schemaless", + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue("value 2"), + NULL); + + // Other namespaces aren't filtered. + PolicyNamespace chrome_ns(POLICY_DOMAIN_CHROME, ""); + bundle.Get(chrome_ns).Set("ChromePolicy", + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue("value 3"), + NULL); + + PolicyBundle expected_bundle; + expected_bundle.MergeFrom(bundle); + + // Unknown policies of known components with a schema are removed. + bundle.Get(extension_ns).Set("Surprise", + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue("value 4"), + NULL); + + // Unknown components are removed. + PolicyNamespace unknown_ns(POLICY_DOMAIN_EXTENSIONS, "unknown"); + bundle.Get(unknown_ns).Set("Surprise", + POLICY_LEVEL_MANDATORY, + POLICY_SCOPE_USER, + base::Value::CreateStringValue("value 5"), + NULL); + + descriptor->FilterBundle(&bundle); + EXPECT_TRUE(bundle.Equals(expected_bundle)); +} + } // namespace policy diff --git a/chrome/browser/policy/policy_loader_mac.cc b/chrome/browser/policy/policy_loader_mac.cc index 29774f0..2d8e220 100644 --- a/chrome/browser/policy/policy_loader_mac.cc +++ b/chrome/browser/policy/policy_loader_mac.cc @@ -21,7 +21,7 @@ #include "chrome/browser/policy/policy_load_status.h" #include "chrome/browser/policy/policy_map.h" #include "chrome/browser/policy/preferences_mac.h" -#include "components/policy/core/common/policy_schema.h" +#include "components/policy/core/common/schema.h" #include "policy/policy_constants.h" using base::mac::CFCast; @@ -210,29 +210,22 @@ void PolicyLoaderMac::LoadPolicyForDomain( void PolicyLoaderMac::LoadPolicyForComponent( const std::string& bundle_id_string, - const PolicySchema* schema, + Schema schema, PolicyMap* policy) { // TODO(joaodasilva): extensions may be registered in a PolicyDomainDescriptor - // without a PolicySchema, to allow a graceful update of the Legacy Browser - // Support extension on Windows. Remove this temporary check once that support - // is removed. - if (!schema) + // without a schema, to allow a graceful update of the Legacy Browser Support + // extension on Windows. Remove this check once that support is removed. + if (!schema.valid()) return; base::ScopedCFTypeRef<CFStringRef> bundle_id( base::SysUTF8ToCFStringRef(bundle_id_string)); preferences_->AppSynchronize(bundle_id); - const PolicySchemaMap* map = schema->GetProperties(); - if (!map) { - NOTREACHED(); - return; - } - - for (PolicySchemaMap::const_iterator it = map->begin(); - it != map->end(); ++it) { + for (Schema::Iterator it = schema.GetPropertiesIterator(); + !it.IsAtEnd(); it.Advance()) { base::ScopedCFTypeRef<CFStringRef> pref_name( - base::SysUTF8ToCFStringRef(it->first)); + base::SysUTF8ToCFStringRef(it.key())); base::ScopedCFTypeRef<CFPropertyListRef> value( preferences_->CopyAppValue(pref_name, bundle_id)); if (!value.get()) @@ -242,9 +235,10 @@ void PolicyLoaderMac::LoadPolicyForComponent( PolicyLevel level = forced ? POLICY_LEVEL_MANDATORY : POLICY_LEVEL_RECOMMENDED; scoped_ptr<base::Value> policy_value(CreateValueFromProperty(value)); - if (policy_value) - policy->Set(it->first, level, POLICY_SCOPE_USER, + if (policy_value) { + policy->Set(it.key(), level, POLICY_SCOPE_USER, policy_value.release(), NULL); + } } } diff --git a/chrome/browser/policy/policy_loader_mac.h b/chrome/browser/policy/policy_loader_mac.h index 104ec90..68da9e4 100644 --- a/chrome/browser/policy/policy_loader_mac.h +++ b/chrome/browser/policy/policy_loader_mac.h @@ -25,7 +25,7 @@ namespace policy { class PolicyDomainDescriptor; class PolicyMap; -class PolicySchema; +class Schema; struct PolicyDefinitionList; // A policy loader that loads policies from the Mac preferences system, and @@ -63,7 +63,7 @@ class PolicyLoaderMac : public AsyncPolicyLoader { // Loads the policies described in |schema| from the bundle identified by // |bundle_id_string|, and stores them in |policy|. void LoadPolicyForComponent(const std::string& bundle_id_string, - const PolicySchema* schema, + Schema schema, PolicyMap* policy); // List of recognized policies. diff --git a/chrome/browser/policy/policy_service_impl_unittest.cc b/chrome/browser/policy/policy_service_impl_unittest.cc index c34cb2b..c7854d5 100644 --- a/chrome/browser/policy/policy_service_impl_unittest.cc +++ b/chrome/browser/policy/policy_service_impl_unittest.cc @@ -15,7 +15,7 @@ #include "chrome/browser/policy/mock_configuration_policy_provider.h" #include "chrome/browser/policy/mock_policy_service.h" #include "chrome/browser/policy/policy_domain_descriptor.h" -#include "components/policy/core/common/policy_schema.h" +#include "components/policy/core/common/schema.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -627,9 +627,8 @@ TEST_F(PolicyServiceTest, RegisterPolicyDomain) { // Register another namespace. std::string error; - scoped_ptr<PolicySchema> schema = PolicySchema::Parse( + scoped_ptr<SchemaOwner> schema = SchemaOwner::Parse( "{" - " \"$schema\":\"http://json-schema.org/draft-03/schema#\"," " \"type\":\"object\"," " \"properties\": {" " \"Boolean\": { \"type\": \"boolean\" }," diff --git a/chrome/browser/ui/webui/policy_ui.cc b/chrome/browser/ui/webui/policy_ui.cc index fa9ed74..7e00861 100644 --- a/chrome/browser/ui/webui/policy_ui.cc +++ b/chrome/browser/ui/webui/policy_ui.cc @@ -64,7 +64,7 @@ #include "chrome/browser/policy/policy_domain_descriptor.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension_set.h" -#include "components/policy/core/common/policy_schema.h" +#include "components/policy/core/common/schema.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_constants.h" #endif @@ -579,11 +579,11 @@ void PolicyUIHandler::SendPolicyNames() const { if (schema != schema_map.end()) { // Get policy names from the extension's policy schema. // Store in a map, not an array, for faster lookup on JS side. - const policy::PolicySchemaMap* policies = schema->second->GetProperties(); - policy::PolicySchemaMap::const_iterator it_policies; - for (it_policies = policies->begin(); it_policies != policies->end(); - ++it_policies) { - policy_names->SetBoolean(it_policies->first, true); + policy::Schema policy_schema = schema->second; + for (policy::Schema::Iterator it_policies = + policy_schema.GetPropertiesIterator(); + !it_policies.IsAtEnd(); it_policies.Advance()) { + policy_names->SetBoolean(it_policies.key(), true); } } extension_value->Set("policyNames", policy_names); diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc index 28c8557..d95a967 100644 --- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc +++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.cc @@ -15,7 +15,7 @@ #include "base/strings/utf_string_conversions.h" #include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/permissions/api_permission.h" -#include "components/policy/core/common/policy_schema.h" +#include "components/policy/core/common/schema.h" #include "extensions/common/install_warning.h" #include "extensions/common/manifest.h" #include "extensions/common/manifest_constants.h" @@ -29,13 +29,13 @@ StorageSchemaManifestHandler::StorageSchemaManifestHandler() {} StorageSchemaManifestHandler::~StorageSchemaManifestHandler() {} // static -scoped_ptr<policy::PolicySchema> StorageSchemaManifestHandler::GetSchema( +scoped_ptr<policy::SchemaOwner> StorageSchemaManifestHandler::GetSchema( const Extension* extension, std::string* error) { if (!extension->HasAPIPermission(APIPermission::kStorage)) { *error = base::StringPrintf("The storage permission is required to use %s", kStorageManagedSchema); - return scoped_ptr<policy::PolicySchema>(); + return scoped_ptr<policy::SchemaOwner>(); } std::string path; extension->manifest()->GetString(kStorageManagedSchema, &path); @@ -43,20 +43,20 @@ scoped_ptr<policy::PolicySchema> StorageSchemaManifestHandler::GetSchema( if (file.IsAbsolute() || file.ReferencesParent()) { *error = base::StringPrintf("%s must be a relative path without ..", kStorageManagedSchema); - return scoped_ptr<policy::PolicySchema>(); + return scoped_ptr<policy::SchemaOwner>(); } file = extension->path().AppendASCII(path); if (!base::PathExists(file)) { *error = base::StringPrintf("File does not exist: %s", file.value().c_str()); - return scoped_ptr<policy::PolicySchema>(); + return scoped_ptr<policy::SchemaOwner>(); } std::string content; if (!base::ReadFileToString(file, &content)) { *error = base::StringPrintf("Can't read %s", file.value().c_str()); - return scoped_ptr<policy::PolicySchema>(); + return scoped_ptr<policy::SchemaOwner>(); } - return policy::PolicySchema::Parse(content, error); + return policy::SchemaOwner::Parse(content, error); } bool StorageSchemaManifestHandler::Parse(Extension* extension, diff --git a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h index c988362..d2406d6 100644 --- a/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h +++ b/chrome/common/extensions/api/storage/storage_schema_manifest_handler.h @@ -9,7 +9,7 @@ #include "chrome/common/extensions/manifest_handler.h" namespace policy { -class PolicySchema; +class SchemaOwner; } namespace extensions { @@ -24,8 +24,8 @@ class StorageSchemaManifestHandler : public ManifestHandler { // If the schema is invalid then NULL is returned, and the failure reason // is stored in |error|. // This function does file I/O and must be called on a thread that allows I/O. - static scoped_ptr<policy::PolicySchema> GetSchema(const Extension* extension, - std::string* error); + static scoped_ptr<policy::SchemaOwner> GetSchema(const Extension* extension, + std::string* error); private: // ManifestHandler implementation: diff --git a/components/components_tests.gypi b/components/components_tests.gypi index 491e214..94b8700 100644 --- a/components/components_tests.gypi +++ b/components/components_tests.gypi @@ -116,7 +116,6 @@ }], ['configuration_policy==1', { 'sources': [ - 'policy/core/common/policy_schema_unittest.cc', 'policy/core/common/schema_unittest.cc', ], }], diff --git a/components/policy.gypi b/components/policy.gypi index 7471212..8dd3bb1 100644 --- a/components/policy.gypi +++ b/components/policy.gypi @@ -22,8 +22,6 @@ 'sources': [ 'policy/core/common/policy_pref_names.cc', 'policy/core/common/policy_pref_names.h', - 'policy/core/common/policy_schema.cc', - 'policy/core/common/policy_schema.h', 'policy/core/common/schema.cc', 'policy/core/common/schema.h', 'policy/core/common/schema_internal.h', diff --git a/components/policy/core/common/policy_schema.cc b/components/policy/core/common/policy_schema.cc deleted file mode 100644 index 8c3145c..0000000 --- a/components/policy/core/common/policy_schema.cc +++ /dev/null @@ -1,244 +0,0 @@ -// Copyright 2013 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 "components/policy/core/common/policy_schema.h" - -#include "base/compiler_specific.h" -#include "base/logging.h" -#include "base/stl_util.h" -#include "components/json_schema/json_schema_constants.h" -#include "components/json_schema/json_schema_validator.h" - -namespace policy { - -namespace { - -const char kJSONSchemaVersion[] = "http://json-schema.org/draft-03/schema#"; - -// Describes the properties of a TYPE_DICTIONARY policy schema. -class DictionaryPolicySchema : public PolicySchema { - public: - static scoped_ptr<PolicySchema> Parse(const base::DictionaryValue& schema, - std::string* error); - - virtual ~DictionaryPolicySchema(); - - virtual const PolicySchemaMap* GetProperties() const OVERRIDE; - virtual const PolicySchema* GetSchemaForAdditionalProperties() const OVERRIDE; - - private: - DictionaryPolicySchema(); - - PolicySchemaMap properties_; - scoped_ptr<PolicySchema> additional_properties_; - - DISALLOW_COPY_AND_ASSIGN(DictionaryPolicySchema); -}; - -// Describes the items of a TYPE_LIST policy schema. -class ListPolicySchema : public PolicySchema { - public: - static scoped_ptr<PolicySchema> Parse(const base::DictionaryValue& schema, - std::string* error); - - virtual ~ListPolicySchema(); - - virtual const PolicySchema* GetSchemaForItems() const OVERRIDE; - - private: - ListPolicySchema(); - - scoped_ptr<PolicySchema> items_schema_; - - DISALLOW_COPY_AND_ASSIGN(ListPolicySchema); -}; - -bool SchemaTypeToValueType(const std::string& type_string, - base::Value::Type* type) { - // Note: "any" is not an accepted type. - static const struct { - const char* schema_type; - base::Value::Type value_type; - } kSchemaToValueTypeMap[] = { - { json_schema_constants::kArray, base::Value::TYPE_LIST }, - { json_schema_constants::kBoolean, base::Value::TYPE_BOOLEAN }, - { json_schema_constants::kInteger, base::Value::TYPE_INTEGER }, - { json_schema_constants::kNull, base::Value::TYPE_NULL }, - { json_schema_constants::kNumber, base::Value::TYPE_DOUBLE }, - { json_schema_constants::kObject, base::Value::TYPE_DICTIONARY }, - { json_schema_constants::kString, base::Value::TYPE_STRING }, - }; - for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kSchemaToValueTypeMap); ++i) { - if (kSchemaToValueTypeMap[i].schema_type == type_string) { - *type = kSchemaToValueTypeMap[i].value_type; - return true; - } - } - return false; -} - -scoped_ptr<PolicySchema> ParseSchema(const base::DictionaryValue& schema, - std::string* error) { - std::string type_string; - if (!schema.GetString(json_schema_constants::kType, &type_string)) { - *error = "The schema type must be declared."; - return scoped_ptr<PolicySchema>(); - } - - base::Value::Type type = base::Value::TYPE_NULL; - if (!SchemaTypeToValueType(type_string, &type)) { - *error = "The \"any\" type can't be used."; - return scoped_ptr<PolicySchema>(); - } - - switch (type) { - case base::Value::TYPE_DICTIONARY: - return DictionaryPolicySchema::Parse(schema, error); - case base::Value::TYPE_LIST: - return ListPolicySchema::Parse(schema, error); - default: - return make_scoped_ptr(new PolicySchema(type)); - } -} - -DictionaryPolicySchema::DictionaryPolicySchema() - : PolicySchema(base::Value::TYPE_DICTIONARY) {} - -DictionaryPolicySchema::~DictionaryPolicySchema() { - STLDeleteValues(&properties_); -} - -const PolicySchemaMap* DictionaryPolicySchema::GetProperties() const { - return &properties_; -} - -const PolicySchema* - DictionaryPolicySchema::GetSchemaForAdditionalProperties() const { - return additional_properties_.get(); -} - -// static -scoped_ptr<PolicySchema> DictionaryPolicySchema::Parse( - const base::DictionaryValue& schema, - std::string* error) { - scoped_ptr<DictionaryPolicySchema> dict_schema(new DictionaryPolicySchema()); - - const base::DictionaryValue* dict = NULL; - const base::DictionaryValue* properties = NULL; - if (schema.GetDictionary(json_schema_constants::kProperties, &properties)) { - for (base::DictionaryValue::Iterator it(*properties); - !it.IsAtEnd(); it.Advance()) { - // This should have been verified by the JSONSchemaValidator. - CHECK(it.value().GetAsDictionary(&dict)); - scoped_ptr<PolicySchema> sub_schema = ParseSchema(*dict, error); - if (!sub_schema) - return scoped_ptr<PolicySchema>(); - dict_schema->properties_[it.key()] = sub_schema.release(); - } - } - - if (schema.GetDictionary(json_schema_constants::kAdditionalProperties, - &dict)) { - scoped_ptr<PolicySchema> sub_schema = ParseSchema(*dict, error); - if (!sub_schema) - return scoped_ptr<PolicySchema>(); - dict_schema->additional_properties_ = sub_schema.Pass(); - } - - return dict_schema.PassAs<PolicySchema>(); -} - -ListPolicySchema::ListPolicySchema() - : PolicySchema(base::Value::TYPE_LIST) {} - -ListPolicySchema::~ListPolicySchema() {} - -const PolicySchema* ListPolicySchema::GetSchemaForItems() const { - return items_schema_.get(); -} - -scoped_ptr<PolicySchema> ListPolicySchema::Parse( - const base::DictionaryValue& schema, - std::string* error) { - const base::DictionaryValue* dict = NULL; - if (!schema.GetDictionary(json_schema_constants::kItems, &dict)) { - *error = "Arrays must declare a single schema for their items."; - return scoped_ptr<PolicySchema>(); - } - scoped_ptr<PolicySchema> items_schema = ParseSchema(*dict, error); - if (!items_schema) - return scoped_ptr<PolicySchema>(); - - scoped_ptr<ListPolicySchema> list_schema(new ListPolicySchema()); - list_schema->items_schema_ = items_schema.Pass(); - return list_schema.PassAs<PolicySchema>(); -} - -} // namespace - -PolicySchema::PolicySchema(base::Value::Type type) - : type_(type) {} - -PolicySchema::~PolicySchema() {} - -const PolicySchemaMap* PolicySchema::GetProperties() const { - NOTREACHED(); - return NULL; -} - -const PolicySchema* PolicySchema::GetSchemaForAdditionalProperties() const { - NOTREACHED(); - return NULL; -} - -const PolicySchema* PolicySchema::GetSchemaForProperty( - const std::string& key) const { - const PolicySchemaMap* properties = GetProperties(); - PolicySchemaMap::const_iterator it = properties->find(key); - return it == properties->end() ? GetSchemaForAdditionalProperties() - : it->second; -} - -const PolicySchema* PolicySchema::GetSchemaForItems() const { - NOTREACHED(); - return NULL; -} - -// static -scoped_ptr<PolicySchema> PolicySchema::Parse(const std::string& content, - std::string* error) { - // Validate as a generic JSON schema. - scoped_ptr<base::DictionaryValue> dict = - JSONSchemaValidator::IsValidSchema(content, error); - if (!dict) - return scoped_ptr<PolicySchema>(); - - // Validate the schema version. - std::string string_value; - if (!dict->GetString(json_schema_constants::kSchema, &string_value) || - string_value != kJSONSchemaVersion) { - *error = "Must declare JSON Schema v3 version in \"$schema\"."; - return scoped_ptr<PolicySchema>(); - } - - // Validate the main type. - if (!dict->GetString(json_schema_constants::kType, &string_value) || - string_value != json_schema_constants::kObject) { - *error = - "The main schema must have a type attribute with \"object\" value."; - return scoped_ptr<PolicySchema>(); - } - - // Checks for invalid attributes at the top-level. - if (dict->HasKey(json_schema_constants::kAdditionalProperties) || - dict->HasKey(json_schema_constants::kPatternProperties)) { - *error = "\"additionalProperties\" and \"patternProperties\" are not " - "supported at the main schema."; - return scoped_ptr<PolicySchema>(); - } - - return ParseSchema(*dict, error); -} - -} // namespace policy diff --git a/components/policy/core/common/policy_schema.h b/components/policy/core/common/policy_schema.h deleted file mode 100644 index c48ee6f..0000000 --- a/components/policy/core/common/policy_schema.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2013 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. - -#ifndef COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEMA_H_ -#define COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEMA_H_ - -#include <map> -#include <string> - -#include "base/basictypes.h" -#include "base/memory/scoped_ptr.h" -#include "base/values.h" -#include "components/policy/policy_export.h" - -namespace policy { - -class PolicySchema; -typedef std::map<std::string, PolicySchema*> PolicySchemaMap; - -// Maps known policy keys to their expected types, and recursively describes -// the known keys within dictionary or list types. -class POLICY_EXPORT PolicySchema { - public: - - // Parses |schema| as a JSON v3 schema, and additionally verifies that: - // - the version is JSON schema v3; - // - the top-level entry is of type "object"; - // - the top-level object doesn't contain "additionalProperties" nor - // "patternProperties"; - // - each "property" maps to a schema with one "type"; - // - the type "any" is not used. - // If all the checks pass then the parsed PolicySchema is returned; otherwise - // returns NULL. - static scoped_ptr<PolicySchema> Parse(const std::string& schema, - std::string* error); - - explicit PolicySchema(base::Value::Type type); - virtual ~PolicySchema(); - - // Returns the expected type for this policy. At the top-level PolicySchema - // this is always TYPE_DICTIONARY. - base::Value::Type type() const { return type_; } - - // It is invalid to call these methods when type() is not TYPE_DICTIONARY. - // - // GetProperties() returns a map of the known property names to their schemas; - // the map is never NULL. - // GetSchemaForAdditionalProperties() returns the schema that should be used - // for keys not found in the map, and may be NULL. - // GetSchemaForProperty() is a utility method that combines both, returning - // the mapped schema if found in GetProperties(), otherwise returning - // GetSchemaForAdditionalProperties(). - virtual const PolicySchemaMap* GetProperties() const; - virtual const PolicySchema* GetSchemaForAdditionalProperties() const; - const PolicySchema* GetSchemaForProperty(const std::string& key) const; - - // It is invalid to call this method when type() is not TYPE_LIST. - // Returns the type of the entries of this "array", which is never NULL. - virtual const PolicySchema* GetSchemaForItems() const; - - private: - const base::Value::Type type_; - - DISALLOW_COPY_AND_ASSIGN(PolicySchema); -}; - -} // namespace policy - -#endif // COMPONENTS_POLICY_CORE_COMMON_POLICY_SCHEMA_H_ diff --git a/components/policy/core/common/policy_schema_unittest.cc b/components/policy/core/common/policy_schema_unittest.cc deleted file mode 100644 index bfbdd65..0000000 --- a/components/policy/core/common/policy_schema_unittest.cc +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright 2013 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 "components/policy/core/common/policy_schema.h" - -#include "testing/gtest/include/gtest/gtest.h" - -namespace policy { - -namespace { - -#define SCHEMA_VERSION "\"$schema\":\"http://json-schema.org/draft-03/schema#\"" -#define OBJECT_TYPE "\"type\":\"object\"" - -bool ParseFails(const std::string& content) { - std::string error; - scoped_ptr<PolicySchema> schema = PolicySchema::Parse(content, &error); - EXPECT_TRUE(schema || !error.empty()); - return !schema; -} - -} // namespace - -TEST(PolicySchemaTest, MinimalSchema) { - EXPECT_FALSE(ParseFails( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE - "}")); -} - -TEST(PolicySchemaTest, InvalidSchemas) { - EXPECT_TRUE(ParseFails("")); - EXPECT_TRUE(ParseFails("omg")); - EXPECT_TRUE(ParseFails("\"omg\"")); - EXPECT_TRUE(ParseFails("123")); - EXPECT_TRUE(ParseFails("[]")); - EXPECT_TRUE(ParseFails("null")); - EXPECT_TRUE(ParseFails("{}")); - EXPECT_TRUE(ParseFails("{" SCHEMA_VERSION "}")); - EXPECT_TRUE(ParseFails("{" OBJECT_TYPE "}")); - - EXPECT_TRUE(ParseFails( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE "," - "\"additionalProperties\": { \"type\":\"object\" }" - "}")); - - EXPECT_TRUE(ParseFails( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE "," - "\"patternProperties\": { \"a+b*\": { \"type\": \"object\" } }" - "}")); - - EXPECT_TRUE(ParseFails( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE "," - "\"properties\": { \"Policy\": { \"type\": \"bogus\" } }" - "}")); - - EXPECT_TRUE(ParseFails( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE "," - "\"properties\": { \"Policy\": { \"type\": [\"string\", \"number\"] } }" - "}")); - - EXPECT_TRUE(ParseFails( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE "," - "\"properties\": { \"Policy\": { \"type\": \"any\" } }" - "}")); -} - -TEST(PolicySchemaTest, ValidSchema) { - std::string error; - scoped_ptr<PolicySchema> schema = PolicySchema::Parse( - "{" - SCHEMA_VERSION "," - OBJECT_TYPE "," - "\"properties\": {" - " \"Boolean\": { \"type\": \"boolean\" }," - " \"Integer\": { \"type\": \"integer\" }," - " \"Null\": { \"type\": \"null\" }," - " \"Number\": { \"type\": \"number\" }," - " \"String\": { \"type\": \"string\" }," - " \"Array\": {" - " \"type\": \"array\"," - " \"items\": { \"type\": \"string\" }" - " }," - " \"ArrayOfObjects\": {" - " \"type\": \"array\"," - " \"items\": {" - " \"type\": \"object\"," - " \"properties\": {" - " \"one\": { \"type\": \"string\" }," - " \"two\": { \"type\": \"integer\" }" - " }" - " }" - " }," - " \"ArrayOfArray\": {" - " \"type\": \"array\"," - " \"items\": {" - " \"type\": \"array\"," - " \"items\": { \"type\": \"string\" }" - " }" - " }," - " \"Object\": {" - " \"type\": \"object\"," - " \"properties\": {" - " \"one\": { \"type\": \"boolean\" }," - " \"two\": { \"type\": \"integer\" }" - " }," - " \"additionalProperties\": { \"type\": \"string\" }" - " }" - "}" - "}", &error); - ASSERT_TRUE(schema) << error; - - ASSERT_EQ(base::Value::TYPE_DICTIONARY, schema->type()); - EXPECT_FALSE(schema->GetSchemaForProperty("invalid")); - - const PolicySchema* sub = schema->GetSchemaForProperty("Boolean"); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_BOOLEAN, sub->type()); - - sub = schema->GetSchemaForProperty("Integer"); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_INTEGER, sub->type()); - - sub = schema->GetSchemaForProperty("Null"); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_NULL, sub->type()); - - sub = schema->GetSchemaForProperty("Number"); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_DOUBLE, sub->type()); - sub = schema->GetSchemaForProperty("String"); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_STRING, sub->type()); - - sub = schema->GetSchemaForProperty("Array"); - ASSERT_TRUE(sub); - ASSERT_EQ(base::Value::TYPE_LIST, sub->type()); - sub = sub->GetSchemaForItems(); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_STRING, sub->type()); - - sub = schema->GetSchemaForProperty("ArrayOfObjects"); - ASSERT_TRUE(sub); - ASSERT_EQ(base::Value::TYPE_LIST, sub->type()); - sub = sub->GetSchemaForItems(); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_DICTIONARY, sub->type()); - const PolicySchema* subsub = sub->GetSchemaForProperty("one"); - ASSERT_TRUE(subsub); - EXPECT_EQ(base::Value::TYPE_STRING, subsub->type()); - subsub = sub->GetSchemaForProperty("two"); - ASSERT_TRUE(subsub); - EXPECT_EQ(base::Value::TYPE_INTEGER, subsub->type()); - subsub = sub->GetSchemaForProperty("invalid"); - EXPECT_FALSE(subsub); - - sub = schema->GetSchemaForProperty("ArrayOfArray"); - ASSERT_TRUE(sub); - ASSERT_EQ(base::Value::TYPE_LIST, sub->type()); - sub = sub->GetSchemaForItems(); - ASSERT_TRUE(sub); - ASSERT_EQ(base::Value::TYPE_LIST, sub->type()); - sub = sub->GetSchemaForItems(); - ASSERT_TRUE(sub); - EXPECT_EQ(base::Value::TYPE_STRING, sub->type()); - - sub = schema->GetSchemaForProperty("Object"); - ASSERT_TRUE(sub); - ASSERT_EQ(base::Value::TYPE_DICTIONARY, sub->type()); - subsub = sub->GetSchemaForProperty("one"); - ASSERT_TRUE(subsub); - EXPECT_EQ(base::Value::TYPE_BOOLEAN, subsub->type()); - subsub = sub->GetSchemaForProperty("two"); - ASSERT_TRUE(subsub); - EXPECT_EQ(base::Value::TYPE_INTEGER, subsub->type()); - subsub = sub->GetSchemaForProperty("undeclared"); - ASSERT_TRUE(subsub); - EXPECT_EQ(base::Value::TYPE_STRING, subsub->type()); -} - -} // namespace policy diff --git a/components/policy/core/common/schema.cc b/components/policy/core/common/schema.cc index cbfde46..b3e63d7 100644 --- a/components/policy/core/common/schema.cc +++ b/components/policy/core/common/schema.cc @@ -74,6 +74,8 @@ Schema Schema::Iterator::schema() const { return Schema(it_->schema); } +Schema::Schema() : schema_(NULL) {} + Schema::Schema(const internal::SchemaNode* schema) : schema_(schema) {} Schema::Schema(const Schema& schema) : schema_(schema.schema_) {} @@ -112,7 +114,7 @@ Schema Schema::GetKnownProperty(const std::string& key) const { properties_node->begin, properties_node->end, key, CompareKeys); if (it != properties_node->end && it->key == key) return Schema(it->schema); - return Schema(NULL); + return Schema(); } Schema Schema::GetAdditionalProperties() const { diff --git a/components/policy/core/common/schema.h b/components/policy/core/common/schema.h index a81b7ad..7a734bf 100644 --- a/components/policy/core/common/schema.h +++ b/components/policy/core/common/schema.h @@ -30,7 +30,14 @@ struct POLICY_EXPORT PropertiesNode; // Use the SchemaOwner class to parse a schema and get Schema objects. class POLICY_EXPORT Schema { public: + // Builds an empty, invalid schema. + Schema(); + + // Builds a schema pointing to the inner structure of |schema|. If |schema| + // is NULL then this Schema instance will be invalid. + // Does not take ownership of |schema|. explicit Schema(const internal::SchemaNode* schema); + Schema(const Schema& schema); Schema& operator=(const Schema& schema); |