| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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/declarative/rules_cache_delegate.h" | |
| 6 | |
| 7 #include "chrome/browser/chrome_notification_types.h" | |
| 8 #include "chrome/browser/extensions/api/declarative/rules_registry.h" | |
| 9 #include "chrome/browser/extensions/extension_service.h" | |
| 10 #include "chrome/browser/extensions/extension_util.h" | |
| 11 #include "content/public/browser/browser_context.h" | |
| 12 #include "content/public/browser/notification_details.h" | |
| 13 #include "content/public/browser/notification_source.h" | |
| 14 #include "extensions/browser/extension_prefs.h" | |
| 15 #include "extensions/browser/extension_registry.h" | |
| 16 #include "extensions/browser/extension_system.h" | |
| 17 #include "extensions/browser/info_map.h" | |
| 18 #include "extensions/browser/state_store.h" | |
| 19 #include "extensions/common/permissions/permissions_data.h" | |
| 20 | |
| 21 namespace { | |
| 22 | |
| 23 // Returns the key to use for storing declarative rules in the state store. | |
| 24 std::string GetDeclarativeRuleStorageKey(const std::string& event_name, | |
| 25 bool incognito) { | |
| 26 if (incognito) | |
| 27 return "declarative_rules.incognito." + event_name; | |
| 28 else | |
| 29 return "declarative_rules." + event_name; | |
| 30 } | |
| 31 | |
| 32 | |
| 33 } // namespace | |
| 34 | |
| 35 namespace extensions { | |
| 36 | |
| 37 // RulesCacheDelegate | |
| 38 | |
| 39 const char RulesCacheDelegate::kRulesStoredKey[] = | |
| 40 "has_declarative_rules"; | |
| 41 | |
| 42 RulesCacheDelegate::RulesCacheDelegate(bool log_storage_init_delay) | |
| 43 : browser_context_(NULL), | |
| 44 log_storage_init_delay_(log_storage_init_delay), | |
| 45 notified_registry_(false), | |
| 46 weak_ptr_factory_(this) { | |
| 47 } | |
| 48 | |
| 49 RulesCacheDelegate::~RulesCacheDelegate() {} | |
| 50 | |
| 51 // Returns the key to use for storing whether the rules have been stored. | |
| 52 // static | |
| 53 std::string RulesCacheDelegate::GetRulesStoredKey(const std::string& event_name, | |
| 54 bool incognito) { | |
| 55 std::string result(kRulesStoredKey); | |
| 56 result += incognito ? ".incognito." : "."; | |
| 57 return result + event_name; | |
| 58 } | |
| 59 | |
| 60 // This is called from the constructor of RulesRegistry, so it is | |
| 61 // important that it both | |
| 62 // 1. calls no (in particular virtual) methods of the rules registry, and | |
| 63 // 2. does not create scoped_refptr holding the registry. (A short-lived | |
| 64 // scoped_refptr might delete the rules registry before it is constructed.) | |
| 65 void RulesCacheDelegate::Init(RulesRegistry* registry) { | |
| 66 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 67 | |
| 68 // WARNING: The first use of |registry_| will bind it to the calling thread | |
| 69 // so don't use this here. | |
| 70 registry_ = registry->GetWeakPtr(); | |
| 71 | |
| 72 browser_context_ = registry->browser_context(); | |
| 73 storage_key_ = | |
| 74 GetDeclarativeRuleStorageKey(registry->event_name(), | |
| 75 browser_context_->IsOffTheRecord()); | |
| 76 rules_stored_key_ = GetRulesStoredKey(registry->event_name(), | |
| 77 browser_context_->IsOffTheRecord()); | |
| 78 rules_registry_thread_ = registry->owner_thread(); | |
| 79 | |
| 80 ExtensionSystem& system = *ExtensionSystem::Get(browser_context_); | |
| 81 StateStore* store = system.rules_store(); | |
| 82 if (store) | |
| 83 store->RegisterKey(storage_key_); | |
| 84 | |
| 85 if (browser_context_->IsOffTheRecord()) | |
| 86 log_storage_init_delay_ = false; | |
| 87 | |
| 88 system.ready().Post( | |
| 89 FROM_HERE, | |
| 90 base::Bind(&RulesCacheDelegate::ReadRulesForInstalledExtensions, | |
| 91 weak_ptr_factory_.GetWeakPtr())); | |
| 92 system.ready().Post(FROM_HERE, | |
| 93 base::Bind(&RulesCacheDelegate::CheckIfReady, | |
| 94 weak_ptr_factory_.GetWeakPtr())); | |
| 95 } | |
| 96 | |
| 97 void RulesCacheDelegate::WriteToStorage(const std::string& extension_id, | |
| 98 scoped_ptr<base::Value> value) { | |
| 99 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 100 if (!browser_context_) | |
| 101 return; | |
| 102 | |
| 103 const base::ListValue* rules = NULL; | |
| 104 CHECK(value->GetAsList(&rules)); | |
| 105 bool rules_stored_previously = GetDeclarativeRulesStored(extension_id); | |
| 106 bool store_rules = !rules->empty(); | |
| 107 SetDeclarativeRulesStored(extension_id, store_rules); | |
| 108 if (!rules_stored_previously && !store_rules) | |
| 109 return; | |
| 110 | |
| 111 StateStore* store = ExtensionSystem::Get(browser_context_)->rules_store(); | |
| 112 if (store) | |
| 113 store->SetExtensionValue(extension_id, storage_key_, value.Pass()); | |
| 114 } | |
| 115 | |
| 116 void RulesCacheDelegate::CheckIfReady() { | |
| 117 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 118 if (notified_registry_ || !waiting_for_extensions_.empty()) | |
| 119 return; | |
| 120 | |
| 121 content::BrowserThread::PostTask( | |
| 122 rules_registry_thread_, | |
| 123 FROM_HERE, | |
| 124 base::Bind( | |
| 125 &RulesRegistry::MarkReady, registry_, storage_init_time_)); | |
| 126 notified_registry_ = true; | |
| 127 } | |
| 128 | |
| 129 void RulesCacheDelegate::ReadRulesForInstalledExtensions() { | |
| 130 ExtensionSystem& system = *ExtensionSystem::Get(browser_context_); | |
| 131 ExtensionService* extension_service = system.extension_service(); | |
| 132 DCHECK(extension_service); | |
| 133 // In an OTR context, we start on top of a normal context already, so the | |
| 134 // extension service should be ready. | |
| 135 DCHECK(!browser_context_->IsOffTheRecord() || extension_service->is_ready()); | |
| 136 if (extension_service->is_ready()) { | |
| 137 const ExtensionSet* extensions = extension_service->extensions(); | |
| 138 for (ExtensionSet::const_iterator i = extensions->begin(); | |
| 139 i != extensions->end(); | |
| 140 ++i) { | |
| 141 bool needs_apis_storing_rules = | |
| 142 (*i)->permissions_data()->HasAPIPermission( | |
| 143 APIPermission::kDeclarativeContent) || | |
| 144 (*i)->permissions_data()->HasAPIPermission( | |
| 145 APIPermission::kDeclarativeWebRequest); | |
| 146 bool respects_off_the_record = | |
| 147 !(browser_context_->IsOffTheRecord()) || | |
| 148 util::IsIncognitoEnabled((*i)->id(), browser_context_); | |
| 149 if (needs_apis_storing_rules && respects_off_the_record) | |
| 150 ReadFromStorage((*i)->id()); | |
| 151 } | |
| 152 } | |
| 153 } | |
| 154 | |
| 155 void RulesCacheDelegate::ReadFromStorage(const std::string& extension_id) { | |
| 156 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 157 if (!browser_context_) | |
| 158 return; | |
| 159 | |
| 160 if (log_storage_init_delay_ && storage_init_time_.is_null()) | |
| 161 storage_init_time_ = base::Time::Now(); | |
| 162 | |
| 163 if (!GetDeclarativeRulesStored(extension_id)) { | |
| 164 ExtensionSystem::Get(browser_context_)->ready().Post( | |
| 165 FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady, | |
| 166 weak_ptr_factory_.GetWeakPtr())); | |
| 167 return; | |
| 168 } | |
| 169 | |
| 170 StateStore* store = ExtensionSystem::Get(browser_context_)->rules_store(); | |
| 171 if (!store) | |
| 172 return; | |
| 173 waiting_for_extensions_.insert(extension_id); | |
| 174 store->GetExtensionValue( | |
| 175 extension_id, | |
| 176 storage_key_, | |
| 177 base::Bind(&RulesCacheDelegate::ReadFromStorageCallback, | |
| 178 weak_ptr_factory_.GetWeakPtr(), | |
| 179 extension_id)); | |
| 180 } | |
| 181 | |
| 182 void RulesCacheDelegate::ReadFromStorageCallback( | |
| 183 const std::string& extension_id, | |
| 184 scoped_ptr<base::Value> value) { | |
| 185 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
| 186 content::BrowserThread::PostTask( | |
| 187 rules_registry_thread_, | |
| 188 FROM_HERE, | |
| 189 base::Bind(&RulesRegistry::DeserializeAndAddRules, | |
| 190 registry_, | |
| 191 extension_id, | |
| 192 base::Passed(&value))); | |
| 193 | |
| 194 waiting_for_extensions_.erase(extension_id); | |
| 195 | |
| 196 if (waiting_for_extensions_.empty()) | |
| 197 ExtensionSystem::Get(browser_context_)->ready().Post( | |
| 198 FROM_HERE, base::Bind(&RulesCacheDelegate::CheckIfReady, | |
| 199 weak_ptr_factory_.GetWeakPtr())); | |
| 200 } | |
| 201 | |
| 202 bool RulesCacheDelegate::GetDeclarativeRulesStored( | |
| 203 const std::string& extension_id) const { | |
| 204 CHECK(browser_context_); | |
| 205 const ExtensionScopedPrefs* extension_prefs = | |
| 206 ExtensionPrefs::Get(browser_context_); | |
| 207 | |
| 208 bool rules_stored = true; | |
| 209 if (extension_prefs->ReadPrefAsBoolean( | |
| 210 extension_id, rules_stored_key_, &rules_stored)) | |
| 211 return rules_stored; | |
| 212 | |
| 213 // Safe default -- if we don't know that the rules are not stored, we force | |
| 214 // a read by returning true. | |
| 215 return true; | |
| 216 } | |
| 217 | |
| 218 void RulesCacheDelegate::SetDeclarativeRulesStored( | |
| 219 const std::string& extension_id, | |
| 220 bool rules_stored) { | |
| 221 CHECK(browser_context_); | |
| 222 DCHECK(ExtensionRegistry::Get(browser_context_) | |
| 223 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING)); | |
| 224 | |
| 225 ExtensionScopedPrefs* extension_prefs = ExtensionPrefs::Get(browser_context_); | |
| 226 extension_prefs->UpdateExtensionPref( | |
| 227 extension_id, | |
| 228 rules_stored_key_, | |
| 229 new base::FundamentalValue(rules_stored)); | |
| 230 } | |
| 231 | |
| 232 } // namespace extensions | |
| OLD | NEW |