| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/extensions/api/content_settings/content_settings_store.
h" | 5 #include "chrome/browser/extensions/api/content_settings/content_settings_store.
h" |
| 6 | 6 |
| 7 #include <algorithm> |
| 7 #include <memory> | 8 #include <memory> |
| 8 #include <set> | 9 #include <set> |
| 9 #include <utility> | 10 #include <utility> |
| 10 #include <vector> | |
| 11 | 11 |
| 12 #include "base/debug/alias.h" | 12 #include "base/debug/alias.h" |
| 13 #include "base/logging.h" | 13 #include "base/logging.h" |
| 14 #include "base/memory/ptr_util.h" | 14 #include "base/memory/ptr_util.h" |
| 15 #include "base/stl_util.h" | |
| 16 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 17 #include "base/values.h" | 16 #include "base/values.h" |
| 18 #include "chrome/browser/extensions/api/content_settings/content_settings_api_co
nstants.h" | 17 #include "chrome/browser/extensions/api/content_settings/content_settings_api_co
nstants.h" |
| 19 #include "chrome/browser/extensions/api/content_settings/content_settings_helper
s.h" | 18 #include "chrome/browser/extensions/api/content_settings/content_settings_helper
s.h" |
| 20 #include "components/content_settings/core/browser/content_settings_origin_ident
ifier_value_map.h" | 19 #include "components/content_settings/core/browser/content_settings_origin_ident
ifier_value_map.h" |
| 21 #include "components/content_settings/core/browser/content_settings_rule.h" | 20 #include "components/content_settings/core/browser/content_settings_rule.h" |
| 22 #include "components/content_settings/core/browser/content_settings_utils.h" | 21 #include "components/content_settings/core/browser/content_settings_utils.h" |
| 23 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 24 | 23 |
| 25 using content::BrowserThread; | 24 using content::BrowserThread; |
| 26 using content_settings::ConcatenationIterator; | 25 using content_settings::ConcatenationIterator; |
| 27 using content_settings::Rule; | 26 using content_settings::Rule; |
| 28 using content_settings::RuleIterator; | 27 using content_settings::RuleIterator; |
| 29 using content_settings::OriginIdentifierValueMap; | 28 using content_settings::OriginIdentifierValueMap; |
| 30 using content_settings::ResourceIdentifier; | 29 using content_settings::ResourceIdentifier; |
| 31 using content_settings::ValueToContentSetting; | 30 using content_settings::ValueToContentSetting; |
| 32 | 31 |
| 33 namespace extensions { | 32 namespace extensions { |
| 34 | 33 |
| 35 namespace helpers = content_settings_helpers; | 34 namespace helpers = content_settings_helpers; |
| 36 namespace keys = content_settings_api_constants; | 35 namespace keys = content_settings_api_constants; |
| 37 | 36 |
| 38 struct ContentSettingsStore::ExtensionEntry { | 37 struct ContentSettingsStore::ExtensionEntry { |
| 39 // Extension id | 38 // Extension id. |
| 40 std::string id; | 39 std::string id; |
| 40 // Installation time. |
| 41 base::Time install_time; |
| 41 // Whether extension is enabled in the profile. | 42 // Whether extension is enabled in the profile. |
| 42 bool enabled; | 43 bool enabled; |
| 43 // Content settings. | 44 // Content settings. |
| 44 OriginIdentifierValueMap settings; | 45 OriginIdentifierValueMap settings; |
| 45 // Persistent incognito content settings. | 46 // Persistent incognito content settings. |
| 46 OriginIdentifierValueMap incognito_persistent_settings; | 47 OriginIdentifierValueMap incognito_persistent_settings; |
| 47 // Session-only incognito content settings. | 48 // Session-only incognito content settings. |
| 48 OriginIdentifierValueMap incognito_session_only_settings; | 49 OriginIdentifierValueMap incognito_session_only_settings; |
| 49 }; | 50 }; |
| 50 | 51 |
| 51 ContentSettingsStore::ContentSettingsStore() { | 52 ContentSettingsStore::ContentSettingsStore() { |
| 52 DCHECK(OnCorrectThread()); | 53 DCHECK(OnCorrectThread()); |
| 53 } | 54 } |
| 54 | 55 |
| 55 ContentSettingsStore::~ContentSettingsStore() { | 56 ContentSettingsStore::~ContentSettingsStore() { |
| 56 base::STLDeleteValues(&entries_); | |
| 57 } | 57 } |
| 58 | 58 |
| 59 std::unique_ptr<RuleIterator> ContentSettingsStore::GetRuleIterator( | 59 std::unique_ptr<RuleIterator> ContentSettingsStore::GetRuleIterator( |
| 60 ContentSettingsType type, | 60 ContentSettingsType type, |
| 61 const content_settings::ResourceIdentifier& identifier, | 61 const content_settings::ResourceIdentifier& identifier, |
| 62 bool incognito) const { | 62 bool incognito) const { |
| 63 std::vector<std::unique_ptr<RuleIterator>> iterators; | 63 std::vector<std::unique_ptr<RuleIterator>> iterators; |
| 64 // Iterate the extensions based on install time (last installed extensions | |
| 65 // first). | |
| 66 ExtensionEntryMap::const_reverse_iterator entry_it; | |
| 67 | 64 |
| 68 // The individual |RuleIterators| shouldn't lock; pass |lock_| to the | 65 // The individual |RuleIterators| shouldn't lock; pass |lock_| to the |
| 69 // |ConcatenationIterator| in a locked state. | 66 // |ConcatenationIterator| in a locked state. |
| 70 std::unique_ptr<base::AutoLock> auto_lock(new base::AutoLock(lock_)); | 67 std::unique_ptr<base::AutoLock> auto_lock(new base::AutoLock(lock_)); |
| 71 | 68 |
| 72 for (entry_it = entries_.rbegin(); entry_it != entries_.rend(); ++entry_it) { | 69 // Iterate the extensions based on install time (most-recently installed |
| 73 auto* entry = entry_it->second; | 70 // items first). |
| 71 for (const auto& entry : entries_) { |
| 74 if (!entry->enabled) | 72 if (!entry->enabled) |
| 75 continue; | 73 continue; |
| 76 | 74 |
| 77 std::unique_ptr<RuleIterator> rule_it; | 75 std::unique_ptr<RuleIterator> rule_it; |
| 78 if (incognito) { | 76 if (incognito) { |
| 79 rule_it = entry->incognito_session_only_settings.GetRuleIterator( | 77 rule_it = entry->incognito_session_only_settings.GetRuleIterator( |
| 80 type, identifier, nullptr); | 78 type, identifier, nullptr); |
| 81 if (rule_it) | 79 if (rule_it) |
| 82 iterators.push_back(std::move(rule_it)); | 80 iterators.push_back(std::move(rule_it)); |
| 83 rule_it = entry->incognito_persistent_settings.GetRuleIterator( | 81 rule_it = entry->incognito_persistent_settings.GetRuleIterator( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 121 // be masked by another extension.) | 119 // be masked by another extension.) |
| 122 NotifyOfContentSettingChanged(ext_id, | 120 NotifyOfContentSettingChanged(ext_id, |
| 123 scope != kExtensionPrefsScopeRegular); | 121 scope != kExtensionPrefsScopeRegular); |
| 124 } | 122 } |
| 125 | 123 |
| 126 void ContentSettingsStore::RegisterExtension( | 124 void ContentSettingsStore::RegisterExtension( |
| 127 const std::string& ext_id, | 125 const std::string& ext_id, |
| 128 const base::Time& install_time, | 126 const base::Time& install_time, |
| 129 bool is_enabled) { | 127 bool is_enabled) { |
| 130 base::AutoLock lock(lock_); | 128 base::AutoLock lock(lock_); |
| 131 ExtensionEntryMap::iterator i = FindEntry(ext_id); | 129 auto i = FindIterator(ext_id); |
| 132 ExtensionEntry* entry; | 130 ExtensionEntry* entry = nullptr; |
| 133 if (i != entries_.end()) { | 131 if (i != entries_.end()) { |
| 134 entry = i->second; | 132 entry = i->get(); |
| 135 } else { | 133 } else { |
| 136 entry = new ExtensionEntry; | 134 entry = new ExtensionEntry; |
| 137 entries_.insert(std::make_pair(install_time, entry)); | 135 entry->install_time = install_time; |
| 136 |
| 137 // Insert in reverse-chronological order to maintain the invariant. |
| 138 auto unique_entry = base::WrapUnique(entry); |
| 139 auto location = |
| 140 std::upper_bound(entries_.begin(), entries_.end(), unique_entry, |
| 141 [](const std::unique_ptr<ExtensionEntry>& a, |
| 142 const std::unique_ptr<ExtensionEntry>& b) { |
| 143 return a->install_time > b->install_time; |
| 144 }); |
| 145 entries_.insert(location, std::move(unique_entry)); |
| 138 } | 146 } |
| 139 | 147 |
| 140 entry->id = ext_id; | 148 entry->id = ext_id; |
| 141 entry->enabled = is_enabled; | 149 entry->enabled = is_enabled; |
| 142 } | 150 } |
| 143 | 151 |
| 144 void ContentSettingsStore::UnregisterExtension( | 152 void ContentSettingsStore::UnregisterExtension( |
| 145 const std::string& ext_id) { | 153 const std::string& ext_id) { |
| 146 bool notify = false; | 154 bool notify = false; |
| 147 bool notify_incognito = false; | 155 bool notify_incognito = false; |
| 148 { | 156 { |
| 149 base::AutoLock lock(lock_); | 157 base::AutoLock lock(lock_); |
| 150 ExtensionEntryMap::iterator i = FindEntry(ext_id); | 158 auto i = FindIterator(ext_id); |
| 151 if (i == entries_.end()) | 159 if (i == entries_.end()) |
| 152 return; | 160 return; |
| 153 notify = !i->second->settings.empty(); | 161 notify = !(*i)->settings.empty(); |
| 154 notify_incognito = !i->second->incognito_persistent_settings.empty() || | 162 notify_incognito = !(*i)->incognito_persistent_settings.empty() || |
| 155 !i->second->incognito_session_only_settings.empty(); | 163 !(*i)->incognito_session_only_settings.empty(); |
| 156 | 164 |
| 157 delete i->second; | |
| 158 entries_.erase(i); | 165 entries_.erase(i); |
| 159 } | 166 } |
| 160 if (notify) | 167 if (notify) |
| 161 NotifyOfContentSettingChanged(ext_id, false); | 168 NotifyOfContentSettingChanged(ext_id, false); |
| 162 if (notify_incognito) | 169 if (notify_incognito) |
| 163 NotifyOfContentSettingChanged(ext_id, true); | 170 NotifyOfContentSettingChanged(ext_id, true); |
| 164 } | 171 } |
| 165 | 172 |
| 166 void ContentSettingsStore::SetExtensionState( | 173 void ContentSettingsStore::SetExtensionState( |
| 167 const std::string& ext_id, bool is_enabled) { | 174 const std::string& ext_id, bool is_enabled) { |
| 168 bool notify = false; | 175 bool notify = false; |
| 169 bool notify_incognito = false; | 176 bool notify_incognito = false; |
| 170 { | 177 { |
| 171 base::AutoLock lock(lock_); | 178 base::AutoLock lock(lock_); |
| 172 ExtensionEntryMap::const_iterator i = FindEntry(ext_id); | 179 ExtensionEntry* entry = FindEntry(ext_id); |
| 173 if (i == entries_.end()) | 180 if (!entry) |
| 174 return; | 181 return; |
| 175 notify = !i->second->settings.empty(); | |
| 176 notify_incognito = !i->second->incognito_persistent_settings.empty() || | |
| 177 !i->second->incognito_session_only_settings.empty(); | |
| 178 | 182 |
| 179 i->second->enabled = is_enabled; | 183 notify = !entry->settings.empty(); |
| 184 notify_incognito = !entry->incognito_persistent_settings.empty() || |
| 185 !entry->incognito_session_only_settings.empty(); |
| 186 |
| 187 entry->enabled = is_enabled; |
| 180 } | 188 } |
| 181 if (notify) | 189 if (notify) |
| 182 NotifyOfContentSettingChanged(ext_id, false); | 190 NotifyOfContentSettingChanged(ext_id, false); |
| 183 if (notify_incognito) | 191 if (notify_incognito) |
| 184 NotifyOfContentSettingChanged(ext_id, true); | 192 NotifyOfContentSettingChanged(ext_id, true); |
| 185 } | 193 } |
| 186 | 194 |
| 187 OriginIdentifierValueMap* ContentSettingsStore::GetValueMap( | 195 OriginIdentifierValueMap* ContentSettingsStore::GetValueMap( |
| 188 const std::string& ext_id, | 196 const std::string& ext_id, |
| 189 ExtensionPrefsScope scope) { | 197 ExtensionPrefsScope scope) { |
| 190 ExtensionEntryMap::const_iterator i = FindEntry(ext_id); | 198 const OriginIdentifierValueMap* result = |
| 191 if (i != entries_.end()) { | 199 static_cast<const ContentSettingsStore*>(this)->GetValueMap(ext_id, |
| 192 switch (scope) { | 200 scope); |
| 193 case kExtensionPrefsScopeRegular: | 201 return const_cast<OriginIdentifierValueMap*>(result); |
| 194 return &(i->second->settings); | |
| 195 case kExtensionPrefsScopeRegularOnly: | |
| 196 // TODO(bauerb): Implement regular-only content settings. | |
| 197 NOTREACHED(); | |
| 198 return NULL; | |
| 199 case kExtensionPrefsScopeIncognitoPersistent: | |
| 200 return &(i->second->incognito_persistent_settings); | |
| 201 case kExtensionPrefsScopeIncognitoSessionOnly: | |
| 202 return &(i->second->incognito_session_only_settings); | |
| 203 } | |
| 204 } | |
| 205 return NULL; | |
| 206 } | 202 } |
| 207 | 203 |
| 208 const OriginIdentifierValueMap* ContentSettingsStore::GetValueMap( | 204 const OriginIdentifierValueMap* ContentSettingsStore::GetValueMap( |
| 209 const std::string& ext_id, | 205 const std::string& ext_id, |
| 210 ExtensionPrefsScope scope) const { | 206 ExtensionPrefsScope scope) const { |
| 211 ExtensionEntryMap::const_iterator i = FindEntry(ext_id); | 207 ExtensionEntry* entry = FindEntry(ext_id); |
| 212 if (i == entries_.end()) | 208 if (!entry) |
| 213 return NULL; | 209 return nullptr; |
| 214 | 210 |
| 215 switch (scope) { | 211 switch (scope) { |
| 216 case kExtensionPrefsScopeRegular: | 212 case kExtensionPrefsScopeRegular: |
| 217 return &(i->second->settings); | 213 return &(entry->settings); |
| 218 case kExtensionPrefsScopeRegularOnly: | 214 case kExtensionPrefsScopeRegularOnly: |
| 219 // TODO(bauerb): Implement regular-only content settings. | 215 // TODO(bauerb): Implement regular-only content settings. |
| 220 NOTREACHED(); | 216 NOTREACHED(); |
| 221 return NULL; | 217 return nullptr; |
| 222 case kExtensionPrefsScopeIncognitoPersistent: | 218 case kExtensionPrefsScopeIncognitoPersistent: |
| 223 return &(i->second->incognito_persistent_settings); | 219 return &(entry->incognito_persistent_settings); |
| 224 case kExtensionPrefsScopeIncognitoSessionOnly: | 220 case kExtensionPrefsScopeIncognitoSessionOnly: |
| 225 return &(i->second->incognito_session_only_settings); | 221 return &(entry->incognito_session_only_settings); |
| 226 } | 222 } |
| 227 | 223 |
| 228 NOTREACHED(); | 224 NOTREACHED(); |
| 229 return NULL; | 225 return nullptr; |
| 230 } | 226 } |
| 231 | 227 |
| 232 void ContentSettingsStore::ClearContentSettingsForExtension( | 228 void ContentSettingsStore::ClearContentSettingsForExtension( |
| 233 const std::string& ext_id, | 229 const std::string& ext_id, |
| 234 ExtensionPrefsScope scope) { | 230 ExtensionPrefsScope scope) { |
| 235 bool notify = false; | 231 bool notify = false; |
| 236 { | 232 { |
| 237 base::AutoLock lock(lock_); | 233 base::AutoLock lock(lock_); |
| 238 OriginIdentifierValueMap* map = GetValueMap(ext_id, scope); | 234 OriginIdentifierValueMap* map = GetValueMap(ext_id, scope); |
| 239 if (!map) { | 235 if (!map) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 for (auto& observer : observers_) | 364 for (auto& observer : observers_) |
| 369 observer.OnContentSettingChanged(extension_id, incognito); | 365 observer.OnContentSettingChanged(extension_id, incognito); |
| 370 } | 366 } |
| 371 | 367 |
| 372 bool ContentSettingsStore::OnCorrectThread() { | 368 bool ContentSettingsStore::OnCorrectThread() { |
| 373 // If there is no UI thread, we're most likely in a unit test. | 369 // If there is no UI thread, we're most likely in a unit test. |
| 374 return !BrowserThread::IsThreadInitialized(BrowserThread::UI) || | 370 return !BrowserThread::IsThreadInitialized(BrowserThread::UI) || |
| 375 BrowserThread::CurrentlyOn(BrowserThread::UI); | 371 BrowserThread::CurrentlyOn(BrowserThread::UI); |
| 376 } | 372 } |
| 377 | 373 |
| 378 ContentSettingsStore::ExtensionEntryMap::iterator | 374 ContentSettingsStore::ExtensionEntry* ContentSettingsStore::FindEntry( |
| 379 ContentSettingsStore::FindEntry(const std::string& ext_id) { | 375 const std::string& ext_id) const { |
| 380 ExtensionEntryMap::iterator i; | 376 auto iter = |
| 381 for (i = entries_.begin(); i != entries_.end(); ++i) { | 377 std::find_if(entries_.begin(), entries_.end(), |
| 382 if (i->second->id == ext_id) | 378 [ext_id](const std::unique_ptr<ExtensionEntry>& entry) { |
| 383 return i; | 379 return entry->id == ext_id; |
| 384 } | 380 }); |
| 385 return entries_.end(); | 381 return iter == entries_.end() ? nullptr : iter->get(); |
| 386 } | 382 } |
| 387 | 383 |
| 388 ContentSettingsStore::ExtensionEntryMap::const_iterator | 384 ContentSettingsStore::ExtensionEntries::iterator |
| 389 ContentSettingsStore::FindEntry(const std::string& ext_id) const { | 385 ContentSettingsStore::FindIterator(const std::string& ext_id) { |
| 390 ExtensionEntryMap::const_iterator i; | 386 return std::find_if(entries_.begin(), entries_.end(), |
| 391 for (i = entries_.begin(); i != entries_.end(); ++i) { | 387 [ext_id](const std::unique_ptr<ExtensionEntry>& entry) { |
| 392 if (i->second->id == ext_id) | 388 return entry->id == ext_id; |
| 393 return i; | 389 }); |
| 394 } | |
| 395 return entries_.end(); | |
| 396 } | 390 } |
| 397 | 391 |
| 398 } // namespace extensions | 392 } // namespace extensions |
| OLD | NEW |