Chromium Code Reviews| Index: chrome/browser/policy/policy_loader_win.cc |
| diff --git a/chrome/browser/policy/policy_loader_win.cc b/chrome/browser/policy/policy_loader_win.cc |
| index 8d89206a399c381c504453f271307e2ae673ff27..97250864a58102f30bd0c113f1572edc2debee13 100644 |
| --- a/chrome/browser/policy/policy_loader_win.cc |
| +++ b/chrome/browser/policy/policy_loader_win.cc |
| @@ -20,6 +20,7 @@ |
| #include "base/basictypes.h" |
| #include "base/file_util.h" |
| #include "base/json/json_reader.h" |
| +#include "base/json/json_writer.h" |
| #include "base/lazy_instance.h" |
| #include "base/logging.h" |
| #include "base/scoped_native_library.h" |
| @@ -27,6 +28,7 @@ |
| #include "base/stl_util.h" |
| #include "base/strings/string16.h" |
| #include "base/strings/string_util.h" |
| +#include "base/values.h" |
| #include "chrome/browser/policy/policy_load_status.h" |
| #include "chrome/browser/policy/preg_parser_win.h" |
| #include "components/json_schema/json_schema_constants.h" |
| @@ -47,9 +49,49 @@ const char kKeyRecommended[] = "recommended"; |
| const char kKeySchema[] = "schema"; |
| const char kKeyThirdParty[] = "3rdparty"; |
| +// The Legacy Browser Support was the first user of the policy-for-extensions |
| +// API, and relied on behavior that will be phased out. If this extension is |
| +// present then its policies will be loaded in a special way. |
| +// TODO(joaodasilva): remove this for M35. http://crbug.com/325349 |
| +const char kLegacyBrowserSupportExtensionId[] = |
| + "heildphpnddilhkemkielfhnkaagiabh"; |
| + |
| // The GUID of the registry settings group policy extension. |
| GUID kRegistrySettingsCSEGUID = REGISTRY_EXTENSION_GUID; |
| +// If the LBS extension is found and contains a schema in the registry then this |
| +// function is used to patch it, and make it compliant. The fix is to |
| +// add an "items" attribute to lists that don't declare it. |
| +std::string PatchSchema(const std::string& schema) { |
| + base::JSONParserOptions options = base::JSON_PARSE_RFC; |
| + scoped_ptr<base::Value> json(base::JSONReader::Read(schema, options)); |
| + base::DictionaryValue* dict = NULL; |
| + base::DictionaryValue* properties = NULL; |
| + if (!json || |
| + !json->GetAsDictionary(&dict) || |
| + !dict->GetDictionary(schema::kProperties, &properties)) { |
| + return schema; |
| + } |
| + |
| + for (base::DictionaryValue::Iterator it(*properties); |
| + !it.IsAtEnd(); it.Advance()) { |
| + base::DictionaryValue* policy_schema = NULL; |
| + std::string type; |
| + if (properties->GetDictionary(it.key(), &policy_schema) && |
| + policy_schema->GetString(schema::kType, &type) && |
| + type == schema::kArray && |
| + !policy_schema->HasKey(schema::kItems)) { |
| + scoped_ptr<base::DictionaryValue> items(new base::DictionaryValue()); |
| + items->SetString(schema::kType, schema::kString); |
| + policy_schema->Set(schema::kItems, items.release()); |
| + } |
| + } |
| + |
| + std::string serialized; |
| + base::JSONWriter::Write(json.get(), &serialized); |
| + return serialized; |
| +} |
| + |
| // A helper class encapsulating run-time-linked function calls to Wow64 APIs. |
| class Wow64Functions { |
| public: |
| @@ -164,32 +206,12 @@ class WinGPOListProvider : public AppliedGPOListProvider { |
| static base::LazyInstance<WinGPOListProvider> g_win_gpo_list_provider = |
| LAZY_INSTANCE_INITIALIZER; |
| -std::string GetSchemaTypeForValueType(base::Value::Type value_type) { |
| - switch (value_type) { |
| - case base::Value::TYPE_DICTIONARY: |
| - return json_schema_constants::kObject; |
| - case base::Value::TYPE_INTEGER: |
| - return json_schema_constants::kInteger; |
| - case base::Value::TYPE_LIST: |
| - return json_schema_constants::kArray; |
| - case base::Value::TYPE_BOOLEAN: |
| - return json_schema_constants::kBoolean; |
| - case base::Value::TYPE_STRING: |
| - return json_schema_constants::kString; |
| - default: |
| - break; |
| - } |
| - |
| - NOTREACHED() << "Unsupported policy value type " << value_type; |
| - return json_schema_constants::kNull; |
| -} |
| - |
| // Parses |gpo_dict| according to |schema| and writes the resulting policy |
| // settings to |policy| for the given |scope| and |level|. |
| void ParsePolicy(const RegistryDict* gpo_dict, |
| PolicyLevel level, |
| PolicyScope scope, |
| - const base::DictionaryValue* schema, |
| + const Schema& schema, |
| PolicyMap* policy) { |
| if (!gpo_dict) |
| return; |
| @@ -263,9 +285,6 @@ scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { |
| if (is_initialized_) |
| SetupWatches(); |
| - if (chrome_policy_schema_.empty()) |
| - BuildChromePolicySchema(); |
| - |
| // Policy scope and corresponding hive. |
| static const struct { |
| PolicyScope scope; |
| @@ -326,36 +345,6 @@ scoped_ptr<PolicyBundle> PolicyLoaderWin::Load() { |
| return bundle.Pass(); |
| } |
| -void PolicyLoaderWin::BuildChromePolicySchema() { |
| - // TODO(joaodasilva): use the Schema directly instead of building this |
| - // DictionaryValue. |
| - scoped_ptr<base::DictionaryValue> properties(new base::DictionaryValue()); |
| - const Schema* chrome_schema = |
| - schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); |
| - for (Schema::Iterator it = chrome_schema->GetPropertiesIterator(); |
| - !it.IsAtEnd(); it.Advance()) { |
| - const std::string schema_type = |
| - GetSchemaTypeForValueType(it.schema().type()); |
| - scoped_ptr<base::DictionaryValue> entry_schema(new base::DictionaryValue()); |
| - entry_schema->SetStringWithoutPathExpansion(json_schema_constants::kType, |
| - schema_type); |
| - |
| - if (it.schema().type() == base::Value::TYPE_LIST) { |
| - scoped_ptr<base::DictionaryValue> items_schema( |
| - new base::DictionaryValue()); |
| - items_schema->SetStringWithoutPathExpansion( |
| - json_schema_constants::kType, json_schema_constants::kString); |
| - entry_schema->SetWithoutPathExpansion(json_schema_constants::kItems, |
| - items_schema.release()); |
| - } |
| - properties->SetWithoutPathExpansion(it.key(), entry_schema.release()); |
| - } |
| - chrome_policy_schema_.SetStringWithoutPathExpansion( |
| - json_schema_constants::kType, json_schema_constants::kObject); |
| - chrome_policy_schema_.SetWithoutPathExpansion( |
| - json_schema_constants::kProperties, properties.release()); |
| -} |
| - |
| bool PolicyLoaderWin::ReadPRegFile(const base::FilePath& preg_file, |
| RegistryDict* policy, |
| PolicyLoadStatusSample* status) { |
| @@ -456,7 +445,9 @@ void PolicyLoaderWin::LoadChromePolicy(const RegistryDict* gpo_dict, |
| PolicyScope scope, |
| PolicyMap* chrome_policy_map) { |
| PolicyMap policy; |
| - ParsePolicy(gpo_dict, level, scope, &chrome_policy_schema_, &policy); |
| + const Schema* chrome_schema = |
| + schema_map()->GetSchema(PolicyNamespace(POLICY_DOMAIN_CHROME, "")); |
| + ParsePolicy(gpo_dict, level, scope, *chrome_schema, &policy); |
| chrome_policy_map->MergeFrom(policy); |
| } |
| @@ -491,16 +482,26 @@ void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, |
| domain_dict->keys().begin()); |
| component != domain_dict->keys().end(); |
| ++component) { |
| - // Load the schema. |
| - const base::DictionaryValue* schema_dict = NULL; |
| - scoped_ptr<base::Value> schema; |
| - std::string schema_json; |
| - const base::Value* schema_value = component->second->GetValue(kKeySchema); |
| - if (schema_value && schema_value->GetAsString(&schema_json)) { |
| - schema.reset(base::JSONReader::Read(schema_json)); |
| - if (!schema || !schema->GetAsDictionary(&schema_dict)) { |
| - LOG(WARNING) << "Failed to parse 3rd-part policy schema for " |
| - << domain << "/" << component->first; |
| + const PolicyNamespace policy_namespace(domain, component->first); |
| + |
| + const Schema* schema_from_map = schema_map()->GetSchema(policy_namespace); |
| + if (!schema_from_map) { |
| + // This extension isn't installed or doesn't support policies. |
| + continue; |
| + } |
| + Schema schema = *schema_from_map; |
| + |
| + if (!schema.valid() && |
| + policy_namespace.domain == POLICY_DOMAIN_EXTENSIONS && |
| + policy_namespace.component_id == kLegacyBrowserSupportExtensionId) { |
| + // TODO(joaodasilva): remove this special treatment for LBS by M35. |
| + std::string schema_json; |
| + const base::Value* value = component->second->GetValue(kKeySchema); |
| + if (value && value->GetAsString(&schema_json)) { |
| + std::string error; |
| + schema = Schema::Parse(PatchSchema(schema_json), &error); |
| + if (!schema.valid()) |
| + LOG(WARNING) << "Invalid schema in the registry for LBS: " << error; |
| } |
| } |
| @@ -512,8 +513,7 @@ void PolicyLoaderWin::Load3rdPartyPolicy(const RegistryDict* gpo_dict, |
| continue; |
| PolicyMap policy; |
| - ParsePolicy(policy_dict, kLevels[j].level, scope, schema_dict, &policy); |
| - PolicyNamespace policy_namespace(domain, component->first); |
| + ParsePolicy(policy_dict, kLevels[j].level, scope, schema, &policy); |
|
Joao da Silva
2013/12/05 18:12:08
Just a side comment: at this stage, |schema| is al
Mattias Nissler (ping if slow)
2013/12/06 10:25:31
I guess I'd feel better if we enforced adherence t
Joao da Silva
2013/12/06 17:25:16
That is already the case. If a schema is not on th
Mattias Nissler (ping if slow)
2013/12/09 14:07:12
OK, thanks for explaining. This stuff is quite sub
|
| bundle->Get(policy_namespace).MergeFrom(policy); |
| } |
| } |