1// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/policy/config_dir_policy_provider.h"
6
7#include <set>
8
9#include "base/file_util.h"
10#include "base/values.h"
11#include "content/common/json_value_serializer.h"
12
13namespace policy {
14
15ConfigDirPolicyProviderDelegate::ConfigDirPolicyProviderDelegate(
16    const FilePath& config_dir)
17    : FileBasedPolicyProvider::ProviderDelegate(config_dir) {
18}
19
20DictionaryValue* ConfigDirPolicyProviderDelegate::Load() {
21  // Enumerate the files and sort them lexicographically.
22  std::set<FilePath> files;
23  file_util::FileEnumerator file_enumerator(config_file_path(), false,
24                                            file_util::FileEnumerator::FILES);
25  for (FilePath config_file_path = file_enumerator.Next();
26       !config_file_path.empty(); config_file_path = file_enumerator.Next())
27    files.insert(config_file_path);
28
29  // Start with an empty dictionary and merge the files' contents.
30  DictionaryValue* policy = new DictionaryValue;
31  for (std::set<FilePath>::iterator config_file_iter = files.begin();
32       config_file_iter != files.end(); ++config_file_iter) {
33    JSONFileValueSerializer deserializer(*config_file_iter);
34    int error_code = 0;
35    std::string error_msg;
36    scoped_ptr<Value> value(deserializer.Deserialize(&error_code, &error_msg));
37    if (!value.get()) {
38      LOG(WARNING) << "Failed to read configuration file "
39                   << config_file_iter->value() << ": " << error_msg;
40      continue;
41    }
42    if (!value->IsType(Value::TYPE_DICTIONARY)) {
43      LOG(WARNING) << "Expected JSON dictionary in configuration file "
44                   << config_file_iter->value();
45      continue;
46    }
47    policy->MergeDictionary(static_cast<DictionaryValue*>(value.get()));
48  }
49
50  return policy;
51}
52
53base::Time ConfigDirPolicyProviderDelegate::GetLastModification() {
54  base::Time last_modification = base::Time();
55  base::PlatformFileInfo file_info;
56
57  // If the path does not exist or points to a directory, it's safe to load.
58  if (!file_util::GetFileInfo(config_file_path(), &file_info) ||
59      !file_info.is_directory) {
60    return last_modification;
61  }
62
63  // Enumerate the files and find the most recent modification timestamp.
64  file_util::FileEnumerator file_enumerator(config_file_path(),
65                                            false,
66                                            file_util::FileEnumerator::FILES);
67  for (FilePath config_file = file_enumerator.Next();
68       !config_file.empty();
69       config_file = file_enumerator.Next()) {
70    if (file_util::GetFileInfo(config_file, &file_info) &&
71        !file_info.is_directory) {
72      last_modification = std::max(last_modification, file_info.last_modified);
73    }
74  }
75
76  return last_modification;
77}
78
79ConfigDirPolicyProvider::ConfigDirPolicyProvider(
80    const ConfigurationPolicyProvider::PolicyDefinitionList* policy_list,
81    const FilePath& config_dir)
82    : FileBasedPolicyProvider(
83        policy_list,
84        new ConfigDirPolicyProviderDelegate(config_dir)) {
85}
86
87}  // namespace policy
88