1 // Copyright (c) 2012 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/extensions/api/storage/policy_value_store.h" 6 7 #include "base/logging.h" 8 #include "base/values.h" 9 #include "components/policy/core/common/policy_map.h" 10 #include "components/policy/core/common/policy_types.h" 11 #include "content/public/browser/browser_thread.h" 12 #include "extensions/browser/api/storage/settings_namespace.h" 13 #include "extensions/browser/value_store/value_store_change.h" 14 #include "extensions/browser/value_store/value_store_util.h" 15 16 using content::BrowserThread; 17 18 namespace util = value_store_util; 19 20 namespace extensions { 21 22 namespace { 23 24 scoped_ptr<ValueStore::Error> ReadOnlyError(scoped_ptr<std::string> key) { 25 return make_scoped_ptr(new ValueStore::Error( 26 ValueStore::READ_ONLY, "This is a read-only store.", key.Pass())); 27 } 28 29 } // namespace 30 31 PolicyValueStore::PolicyValueStore( 32 const std::string& extension_id, 33 const scoped_refptr<SettingsObserverList>& observers, 34 scoped_ptr<ValueStore> delegate) 35 : extension_id_(extension_id), 36 observers_(observers), 37 delegate_(delegate.Pass()) {} 38 39 PolicyValueStore::~PolicyValueStore() {} 40 41 void PolicyValueStore::SetCurrentPolicy(const policy::PolicyMap& policy) { 42 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 43 // Convert |policy| to a dictionary value. Only include mandatory policies 44 // for now. 45 base::DictionaryValue current_policy; 46 for (policy::PolicyMap::const_iterator it = policy.begin(); 47 it != policy.end(); ++it) { 48 if (it->second.level == policy::POLICY_LEVEL_MANDATORY) { 49 current_policy.SetWithoutPathExpansion( 50 it->first, it->second.value->DeepCopy()); 51 } 52 } 53 54 // Get the previous policies stored in the database. 55 // TODO(joaodasilva): it'd be better to have a less expensive way of 56 // determining which keys are currently stored, or of determining which keys 57 // must be removed. 58 base::DictionaryValue previous_policy; 59 ValueStore::ReadResult read_result = delegate_->Get(); 60 61 // If the database is corrupted, try to restore it. 62 // This may have the unfortunate side-effect of incorrectly informing the 63 // extension of a "new" key, which isn't new and was corrupted. Unfortunately, 64 // there's not always a way around this - if the database is corrupted, there 65 // may be no way of telling which keys were previously present. 66 if (read_result->IsCorrupted()) { 67 if (delegate_->Restore()) 68 read_result = delegate_->Get(); 69 } 70 71 if (read_result->HasError()) { 72 LOG(WARNING) << "Failed to read managed settings for extension " 73 << extension_id_ << ": " << read_result->error().message; 74 // Leave |previous_policy| empty, so that events are generated for every 75 // policy in |current_policy|. 76 } else { 77 read_result->settings().Swap(&previous_policy); 78 } 79 80 // Now get two lists of changes: changes after setting the current policies, 81 // and changes after removing old policies that aren't in |current_policy| 82 // anymore. 83 std::vector<std::string> removed_keys; 84 for (base::DictionaryValue::Iterator it(previous_policy); 85 !it.IsAtEnd(); it.Advance()) { 86 if (!current_policy.HasKey(it.key())) 87 removed_keys.push_back(it.key()); 88 } 89 90 ValueStoreChangeList changes; 91 92 WriteResult result = delegate_->Remove(removed_keys); 93 if (!result->HasError()) { 94 changes.insert( 95 changes.end(), result->changes().begin(), result->changes().end()); 96 } 97 98 // IGNORE_QUOTA because these settings aren't writable by the extension, and 99 // are configured by the domain administrator. 100 ValueStore::WriteOptions options = ValueStore::IGNORE_QUOTA; 101 result = delegate_->Set(options, current_policy); 102 if (!result->HasError()) { 103 changes.insert( 104 changes.end(), result->changes().begin(), result->changes().end()); 105 } 106 107 if (!changes.empty()) { 108 observers_->Notify( 109 &SettingsObserver::OnSettingsChanged, 110 extension_id_, 111 settings_namespace::MANAGED, 112 ValueStoreChange::ToJson(changes)); 113 } 114 } 115 116 void PolicyValueStore::DeleteStorage() { 117 // This is called from our owner, indicating that storage for this extension 118 // should be removed. 119 delegate_->Clear(); 120 } 121 122 size_t PolicyValueStore::GetBytesInUse(const std::string& key) { 123 // LeveldbValueStore doesn't implement this; and the underlying database 124 // isn't acccessible to the extension in any case; from the extension's 125 // perspective this is a read-only store. 126 return 0; 127 } 128 129 size_t PolicyValueStore::GetBytesInUse(const std::vector<std::string>& keys) { 130 // See note above. 131 return 0; 132 } 133 134 size_t PolicyValueStore::GetBytesInUse() { 135 // See note above. 136 return 0; 137 } 138 139 ValueStore::ReadResult PolicyValueStore::Get(const std::string& key) { 140 return delegate_->Get(key); 141 } 142 143 ValueStore::ReadResult PolicyValueStore::Get( 144 const std::vector<std::string>& keys) { 145 return delegate_->Get(keys); 146 } 147 148 ValueStore::ReadResult PolicyValueStore::Get() { 149 return delegate_->Get(); 150 } 151 152 ValueStore::WriteResult PolicyValueStore::Set( 153 WriteOptions options, const std::string& key, const base::Value& value) { 154 return MakeWriteResult(ReadOnlyError(util::NewKey(key))); 155 } 156 157 ValueStore::WriteResult PolicyValueStore::Set( 158 WriteOptions options, const base::DictionaryValue& settings) { 159 return MakeWriteResult(ReadOnlyError(util::NoKey())); 160 } 161 162 ValueStore::WriteResult PolicyValueStore::Remove(const std::string& key) { 163 return MakeWriteResult(ReadOnlyError(util::NewKey(key))); 164 } 165 166 ValueStore::WriteResult PolicyValueStore::Remove( 167 const std::vector<std::string>& keys) { 168 return MakeWriteResult(ReadOnlyError(util::NoKey())); 169 } 170 171 ValueStore::WriteResult PolicyValueStore::Clear() { 172 return MakeWriteResult(ReadOnlyError(util::NoKey())); 173 } 174 175 bool PolicyValueStore::Restore() { return delegate_->Restore(); } 176 177 bool PolicyValueStore::RestoreKey(const std::string& key) { 178 return delegate_->RestoreKey(key); 179 } 180 181 } // namespace extensions 182