1// Copyright (c) 2011 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/extension_pref_value_map.h"
6
7#include "base/stl_util-inl.h"
8#include "base/values.h"
9#include "chrome/browser/prefs/pref_value_map.h"
10
11struct ExtensionPrefValueMap::ExtensionEntry {
12  // Installation time of the extension.
13  base::Time install_time;
14  // Whether extension is enabled in the profile.
15  bool enabled;
16  // Regular preferences.
17  PrefValueMap reg_preferences;
18  // Incognito preferences, empty for regular ExtensionPrefStore.
19  PrefValueMap inc_preferences;
20};
21
22ExtensionPrefValueMap::ExtensionPrefValueMap() {
23}
24
25ExtensionPrefValueMap::~ExtensionPrefValueMap() {
26  NotifyOfDestruction();
27  STLDeleteValues(&entries_);
28  entries_.clear();
29}
30
31void ExtensionPrefValueMap::SetExtensionPref(const std::string& ext_id,
32                                             const std::string& key,
33                                             bool incognito,
34                                             Value* value) {
35  PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, incognito);
36
37  if (prefs->SetValue(key, value))
38    NotifyPrefValueChanged(key);
39}
40
41void ExtensionPrefValueMap::RemoveExtensionPref(const std::string& ext_id,
42                                                const std::string& key,
43                                                bool incognito) {
44  PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, incognito);
45  if (prefs->RemoveValue(key))
46    NotifyPrefValueChanged(key);
47}
48
49bool ExtensionPrefValueMap::CanExtensionControlPref(
50    const std::string& extension_id,
51    const std::string& pref_key,
52    bool incognito) const {
53  ExtensionEntryMap::const_iterator ext = entries_.find(extension_id);
54  if (ext == entries_.end()) {
55    NOTREACHED();
56    return false;
57  }
58
59  ExtensionEntryMap::const_iterator winner =
60      GetEffectivePrefValueController(pref_key, incognito, NULL);
61  if (winner == entries_.end())
62    return true;
63
64  return winner->second->install_time <= ext->second->install_time;
65}
66
67bool ExtensionPrefValueMap::DoesExtensionControlPref(
68    const std::string& extension_id,
69    const std::string& pref_key,
70    bool incognito) const {
71  ExtensionEntryMap::const_iterator winner =
72      GetEffectivePrefValueController(pref_key, incognito, NULL);
73  if (winner == entries_.end())
74    return false;
75  return winner->first == extension_id;
76}
77
78void ExtensionPrefValueMap::RegisterExtension(const std::string& ext_id,
79                                              const base::Time& install_time,
80                                              bool is_enabled) {
81  if (entries_.find(ext_id) != entries_.end())
82    UnregisterExtension(ext_id);
83  entries_[ext_id] = new ExtensionEntry;
84  entries_[ext_id]->install_time = install_time;
85  entries_[ext_id]->enabled = is_enabled;
86}
87
88void ExtensionPrefValueMap::UnregisterExtension(const std::string& ext_id) {
89  ExtensionEntryMap::iterator i = entries_.find(ext_id);
90  if (i == entries_.end())
91    return;
92  std::set<std::string> keys;  // keys set by this extension
93  GetExtensionControlledKeys(*(i->second), &keys);
94
95  delete i->second;
96  entries_.erase(i);
97
98  NotifyPrefValueChanged(keys);
99}
100
101void ExtensionPrefValueMap::SetExtensionState(const std::string& ext_id,
102                                              bool is_enabled) {
103  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
104  CHECK(i != entries_.end());
105  if (i->second->enabled == is_enabled)
106    return;
107  std::set<std::string> keys;  // keys set by this extension
108  GetExtensionControlledKeys(*(i->second), &keys);
109  i->second->enabled = is_enabled;
110  NotifyPrefValueChanged(keys);
111}
112
113PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
114    const std::string& ext_id,
115    bool incognito) {
116  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
117  CHECK(i != entries_.end());
118  return incognito ? &(i->second->inc_preferences)
119                   : &(i->second->reg_preferences);
120}
121
122const PrefValueMap* ExtensionPrefValueMap::GetExtensionPrefValueMap(
123    const std::string& ext_id,
124    bool incognito) const {
125  ExtensionEntryMap::const_iterator i = entries_.find(ext_id);
126  CHECK(i != entries_.end());
127  return incognito ? &(i->second->inc_preferences)
128                   : &(i->second->reg_preferences);
129}
130
131void ExtensionPrefValueMap::GetExtensionControlledKeys(
132    const ExtensionEntry& entry,
133    std::set<std::string>* out) const {
134  PrefValueMap::const_iterator i;
135
136  const PrefValueMap& reg_prefs = entry.reg_preferences;
137  for (i = reg_prefs.begin(); i != reg_prefs.end(); ++i)
138    out->insert(i->first);
139
140  const PrefValueMap& inc_prefs = entry.inc_preferences;
141  for (i = inc_prefs.begin(); i != inc_prefs.end(); ++i)
142    out->insert(i->first);
143}
144
145const Value* ExtensionPrefValueMap::GetEffectivePrefValue(
146    const std::string& key,
147    bool incognito,
148    bool* from_incognito) const {
149  ExtensionEntryMap::const_iterator winner =
150      GetEffectivePrefValueController(key, incognito, from_incognito);
151  if (winner == entries_.end())
152    return NULL;
153
154  const Value* value = NULL;
155  const std::string& ext_id = winner->first;
156  if (incognito)
157    GetExtensionPrefValueMap(ext_id, true)->GetValue(key, &value);
158  if (!value)
159    GetExtensionPrefValueMap(ext_id, false)->GetValue(key, &value);
160  return value;
161}
162
163ExtensionPrefValueMap::ExtensionEntryMap::const_iterator
164ExtensionPrefValueMap::GetEffectivePrefValueController(
165    const std::string& key,
166    bool incognito,
167    bool* from_incognito) const {
168  ExtensionEntryMap::const_iterator winner = entries_.end();
169  base::Time winners_install_time;
170
171  ExtensionEntryMap::const_iterator i;
172  for (i = entries_.begin(); i != entries_.end(); ++i) {
173    const std::string& ext_id = i->first;
174    const base::Time& install_time = i->second->install_time;
175    const bool enabled = i->second->enabled;
176
177    if (!enabled)
178      continue;
179    if (install_time < winners_install_time)
180      continue;
181
182    const Value* value = NULL;
183    const PrefValueMap* prefs = GetExtensionPrefValueMap(ext_id, false);
184    if (prefs->GetValue(key, &value)) {
185      winner = i;
186      winners_install_time = install_time;
187      if (from_incognito)
188        *from_incognito = false;
189    }
190
191    if (!incognito)
192      continue;
193
194    prefs = GetExtensionPrefValueMap(ext_id, true);
195    if (prefs->GetValue(key, &value)) {
196      winner = i;
197      winners_install_time = install_time;
198      if (from_incognito)
199        *from_incognito = true;
200    }
201  }
202  return winner;
203}
204
205void ExtensionPrefValueMap::AddObserver(
206    ExtensionPrefValueMap::Observer* observer) {
207  observers_.AddObserver(observer);
208
209  // Collect all currently used keys and notify the new observer.
210  std::set<std::string> keys;
211  ExtensionEntryMap::const_iterator i;
212  for (i = entries_.begin(); i != entries_.end(); ++i)
213    GetExtensionControlledKeys(*(i->second), &keys);
214
215  std::set<std::string>::const_iterator j;
216  for (j = keys.begin(); j != keys.end(); ++j)
217    observer->OnPrefValueChanged(*j);
218}
219
220void ExtensionPrefValueMap::RemoveObserver(
221    ExtensionPrefValueMap::Observer* observer) {
222  observers_.RemoveObserver(observer);
223}
224
225void ExtensionPrefValueMap::NotifyInitializationCompleted() {
226  FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
227                    OnInitializationCompleted());
228}
229
230void ExtensionPrefValueMap::NotifyPrefValueChanged(
231    const std::set<std::string>& keys) {
232  std::set<std::string>::const_iterator i;
233  for (i = keys.begin(); i != keys.end(); ++i)
234    NotifyPrefValueChanged(*i);
235}
236
237void ExtensionPrefValueMap::NotifyPrefValueChanged(const std::string& key) {
238  FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
239                    OnPrefValueChanged(key));
240}
241
242void ExtensionPrefValueMap::NotifyOfDestruction() {
243  FOR_EACH_OBSERVER(ExtensionPrefValueMap::Observer, observers_,
244                    OnExtensionPrefValueMapDestruction());
245}
246