15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/config_dir_policy_loader.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <set> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/files/file_enumerator.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_file_value_serializer.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/json/json_reader.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/platform_file.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "components/policy/core/common/policy_bundle.h" 21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "components/policy/core/common/policy_load_status.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace policy { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Subdirectories that contain the mandatory and recommended policies. 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kMandatoryConfigDir[] = 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) FILE_PATH_LITERAL("managed"); 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const base::FilePath::CharType kRecommendedConfigDir[] = 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL("recommended"); 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)PolicyLoadStatus JsonErrorToPolicyLoadStatus(int status) { 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) switch (status) { 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case JSONFileValueSerializer::JSON_ACCESS_DENIED: 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case JSONFileValueSerializer::JSON_CANNOT_READ_FILE: 37c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case JSONFileValueSerializer::JSON_FILE_LOCKED: 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return POLICY_LOAD_STATUS_READ_ERROR; 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case JSONFileValueSerializer::JSON_NO_SUCH_FILE: 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return POLICY_LOAD_STATUS_MISSING; 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_INVALID_ESCAPE: 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_SYNTAX_ERROR: 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_UNEXPECTED_TOKEN: 44c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_TRAILING_COMMA: 45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_TOO_MUCH_NESTING: 46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT: 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_UNSUPPORTED_ENCODING: 48c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_UNQUOTED_DICTIONARY_KEY: 49c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return POLICY_LOAD_STATUS_PARSE_ERROR; 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) case base::JSONReader::JSON_NO_ERROR: 51c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED(); 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return POLICY_LOAD_STATUS_STARTED; 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NOTREACHED() << "Invalid status " << status; 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return POLICY_LOAD_STATUS_PARSE_ERROR; 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)ConfigDirPolicyLoader::ConfigDirPolicyLoader( 613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) scoped_refptr<base::SequencedTaskRunner> task_runner, 623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const base::FilePath& config_dir, 633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) PolicyScope scope) 643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) : AsyncPolicyLoader(task_runner), config_dir_(config_dir), scope_(scope) {} 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ConfigDirPolicyLoader::~ConfigDirPolicyLoader() {} 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 683551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ConfigDirPolicyLoader::InitOnBackgroundThread() { 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePathWatcher::Callback callback = 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&ConfigDirPolicyLoader::OnFileUpdated, base::Unretained(this)); 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) mandatory_watcher_.Watch(config_dir_.Append(kMandatoryConfigDir), false, 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback); 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) recommended_watcher_.Watch(config_dir_.Append(kRecommendedConfigDir), false, 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback); 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<PolicyBundle> ConfigDirPolicyLoader::Load() { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<PolicyBundle> bundle(new PolicyBundle()); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadFromPath(config_dir_.Append(kMandatoryConfigDir), 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) POLICY_LEVEL_MANDATORY, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bundle.get()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadFromPath(config_dir_.Append(kRecommendedConfigDir), 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) POLICY_LEVEL_RECOMMENDED, 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bundle.get()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return bundle.Pass(); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::Time ConfigDirPolicyLoader::LastModificationTime() { 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const base::FilePath::CharType* kConfigDirSuffixes[] = { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kMandatoryConfigDir, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kRecommendedConfigDir, 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Time last_modification = base::Time(); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::PlatformFileInfo info; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(kConfigDirSuffixes); ++i) { 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path(config_dir_.Append(kConfigDirSuffixes[i])); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Skip if the file doesn't exist, or it isn't a directory. 101a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!base::GetFileInfo(path, &info) || !info.is_directory) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enumerate the files and find the most recent modification timestamp. 105868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator file_enumerator(path, false, 106868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::FILES); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (base::FilePath config_file = file_enumerator.Next(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !config_file.empty(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) config_file = file_enumerator.Next()) { 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (base::GetFileInfo(config_file, &info) && !info.is_directory) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_modification = std::max(last_modification, info.last_modified); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return last_modification; 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ConfigDirPolicyLoader::LoadFromPath(const base::FilePath& path, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyLevel level, 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle* bundle) { 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enumerate the files and sort them lexicographically. 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::set<base::FilePath> files; 123868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator file_enumerator(path, false, 124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) base::FileEnumerator::FILES); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (base::FilePath config_file_path = file_enumerator.Next(); 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !config_file_path.empty(); config_file_path = file_enumerator.Next()) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) files.insert(config_file_path); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PolicyLoadStatusSample status; 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (files.empty()) { 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) status.Add(POLICY_LOAD_STATUS_NO_POLICY); 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start with an empty dictionary and merge the files' contents. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The files are processed in reverse order because |MergeFrom| gives priority 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to existing keys, but the ConfigDirPolicyProvider gives priority to the 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // last file in lexicographic order. 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (std::set<base::FilePath>::reverse_iterator config_file_iter = 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) files.rbegin(); config_file_iter != files.rend(); 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++config_file_iter) { 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JSONFileValueSerializer deserializer(*config_file_iter); 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializer.set_allow_trailing_comma(true); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int error_code = 0; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_msg; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<base::Value> value( 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deserializer.Deserialize(&error_code, &error_msg)); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.get()) { 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Failed to read configuration file " 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << config_file_iter->value() << ": " << error_msg; 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) status.Add(JsonErrorToPolicyLoadStatus(error_code)); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* dictionary_value = NULL; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value->GetAsDictionary(&dictionary_value)) { 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Expected JSON dictionary in configuration file " 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << config_file_iter->value(); 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) status.Add(POLICY_LOAD_STATUS_PARSE_ERROR); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Detach the "3rdparty" node. 1633240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_ptr<base::Value> third_party; 1643240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch if (dictionary_value->Remove("3rdparty", &third_party)) 1653240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch Merge3rdPartyPolicy(third_party.get(), level, bundle); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add chrome policy. 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyMap policy_map; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy_map.LoadFrom(dictionary_value, level, scope_); 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .MergeFrom(policy_map); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ConfigDirPolicyLoader::Merge3rdPartyPolicy( 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::Value* policies, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyLevel level, 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyBundle* bundle) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first-level entries in |policies| are PolicyDomains. The second-level 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // entries are component IDs, and the third-level entries are the policies 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // for that domain/component namespace. 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* domains_dictionary; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policies->GetAsDictionary(&domains_dictionary)) { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "3rdparty value is not a dictionary!"; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Helper to lookup a domain given its string name. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::map<std::string, PolicyDomain> supported_domains; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) supported_domains["extensions"] = POLICY_DOMAIN_EXTENSIONS; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (base::DictionaryValue::Iterator domains_it(*domains_dictionary); 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !domains_it.IsAtEnd(); domains_it.Advance()) { 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ContainsKey(supported_domains, domains_it.key())) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unsupported 3rd party policy domain: " 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << domains_it.key(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* components_dictionary; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!domains_it.value().GetAsDictionary(&components_dictionary)) { 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "3rdparty/" << domains_it.key() 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " value is not a dictionary!"; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyDomain domain = supported_domains[domains_it.key()]; 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (base::DictionaryValue::Iterator components_it(*components_dictionary); 210c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !components_it.IsAtEnd(); components_it.Advance()) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::DictionaryValue* policy_dictionary; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!components_it.value().GetAsDictionary(&policy_dictionary)) { 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "3rdparty/" << domains_it.key() << "/" 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << components_it.key() << " value is not a dictionary!"; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PolicyMap policy; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) policy.LoadFrom(policy_dictionary, level, scope_); 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bundle->Get(PolicyNamespace(domain, components_it.key())) 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) .MergeFrom(policy); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ConfigDirPolicyLoader::OnFileUpdated(const base::FilePath& path, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool error) { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!error) 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Reload(false); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace policy 233