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