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