- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / storage / storage_api.cc
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/storage_api.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/values.h"
13 #include "chrome/browser/extensions/api/storage/settings_frontend.h"
14 #include "chrome/browser/extensions/extension_service.h"
15 #include "chrome/browser/extensions/extensions_quota_service.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/common/extensions/api/storage.h"
18 #include "content/public/browser/browser_thread.h"
19
20 namespace extensions {
21
22 using content::BrowserThread;
23
24 // SettingsFunction
25
26 SettingsFunction::SettingsFunction()
27     : settings_namespace_(settings_namespace::INVALID) {}
28
29 SettingsFunction::~SettingsFunction() {}
30
31 bool SettingsFunction::ShouldSkipQuotaLimiting() const {
32   // Only apply quota if this is for sync storage.
33   std::string settings_namespace_string;
34   if (!args_->GetString(0, &settings_namespace_string)) {
35     // This should be EXTENSION_FUNCTION_VALIDATE(false) but there is no way
36     // to signify that from this function. It will be caught in RunImpl().
37     return false;
38   }
39   return settings_namespace_string != "sync";
40 }
41
42 bool SettingsFunction::RunImpl() {
43   std::string settings_namespace_string;
44   EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &settings_namespace_string));
45   args_->Remove(0, NULL);
46   settings_namespace_ =
47       settings_namespace::FromString(settings_namespace_string);
48   EXTENSION_FUNCTION_VALIDATE(
49       settings_namespace_ != settings_namespace::INVALID);
50
51   SettingsFrontend* frontend =
52       GetProfile()->GetExtensionService()->settings_frontend();
53   if (!frontend->IsStorageEnabled(settings_namespace_)) {
54     error_ = base::StringPrintf(
55         "\"%s\" is not available in this instance of Chrome",
56         settings_namespace_string.c_str());
57     return false;
58   }
59
60   observers_ = frontend->GetObservers();
61   frontend->RunWithStorage(
62       extension_id(),
63       settings_namespace_,
64       base::Bind(&SettingsFunction::AsyncRunWithStorage, this));
65   return true;
66 }
67
68 void SettingsFunction::AsyncRunWithStorage(ValueStore* storage) {
69   bool success = RunWithStorage(storage);
70   BrowserThread::PostTask(
71       BrowserThread::UI,
72       FROM_HERE,
73       base::Bind(&SettingsFunction::SendResponse, this, success));
74 }
75
76 bool SettingsFunction::UseReadResult(ValueStore::ReadResult read_result) {
77   if (read_result->HasError()) {
78     error_ = read_result->error().message;
79     return false;
80   }
81
82   base::DictionaryValue* result = new base::DictionaryValue();
83   result->Swap(&read_result->settings());
84   SetResult(result);
85   return true;
86 }
87
88 bool SettingsFunction::UseWriteResult(ValueStore::WriteResult result) {
89   if (result->HasError()) {
90     error_ = result->error().message;
91     return false;
92   }
93
94   if (!result->changes().empty()) {
95     observers_->Notify(
96         &SettingsObserver::OnSettingsChanged,
97         extension_id(),
98         settings_namespace_,
99         ValueStoreChange::ToJson(result->changes()));
100   }
101
102   return true;
103 }
104
105 // Concrete settings functions
106
107 namespace {
108
109 // Adds all StringValues from a ListValue to a vector of strings.
110 void AddAllStringValues(const base::ListValue& from,
111                         std::vector<std::string>* to) {
112   DCHECK(to->empty());
113   std::string as_string;
114   for (base::ListValue::const_iterator it = from.begin();
115        it != from.end(); ++it) {
116     if ((*it)->GetAsString(&as_string)) {
117       to->push_back(as_string);
118     }
119   }
120 }
121
122 // Gets the keys of a DictionaryValue.
123 std::vector<std::string> GetKeys(const base::DictionaryValue& dict) {
124   std::vector<std::string> keys;
125   for (base::DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
126     keys.push_back(it.key());
127   }
128   return keys;
129 }
130
131 // Creates quota heuristics for settings modification.
132 void GetModificationQuotaLimitHeuristics(QuotaLimitHeuristics* heuristics) {
133   QuotaLimitHeuristic::Config longLimitConfig = {
134     // See storage.json for current value.
135     api::storage::sync::MAX_WRITE_OPERATIONS_PER_HOUR,
136     base::TimeDelta::FromHours(1)
137   };
138   heuristics->push_back(
139       new ExtensionsQuotaService::TimedLimit(
140           longLimitConfig,
141           new QuotaLimitHeuristic::SingletonBucketMapper(),
142           "MAX_WRITE_OPERATIONS_PER_HOUR"));
143
144   // A max of 10 operations per minute, sustained over 10 minutes.
145   QuotaLimitHeuristic::Config shortLimitConfig = {
146     // See storage.json for current value.
147     api::storage::sync::MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE,
148     base::TimeDelta::FromMinutes(1)
149   };
150   heuristics->push_back(
151       new ExtensionsQuotaService::SustainedLimit(
152           base::TimeDelta::FromMinutes(10),
153           shortLimitConfig,
154           new QuotaLimitHeuristic::SingletonBucketMapper(),
155           "MAX_SUSTAINED_WRITE_OPERATIONS_PER_MINUTE"));
156 };
157
158 }  // namespace
159
160 bool StorageStorageAreaGetFunction::RunWithStorage(ValueStore* storage) {
161   base::Value* input = NULL;
162   EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
163
164   switch (input->GetType()) {
165     case base::Value::TYPE_NULL:
166       return UseReadResult(storage->Get());
167
168     case base::Value::TYPE_STRING: {
169       std::string as_string;
170       input->GetAsString(&as_string);
171       return UseReadResult(storage->Get(as_string));
172     }
173
174     case base::Value::TYPE_LIST: {
175       std::vector<std::string> as_string_list;
176       AddAllStringValues(*static_cast<base::ListValue*>(input),
177                          &as_string_list);
178       return UseReadResult(storage->Get(as_string_list));
179     }
180
181     case base::Value::TYPE_DICTIONARY: {
182       base::DictionaryValue* as_dict = static_cast<base::DictionaryValue*>(input);
183       ValueStore::ReadResult result = storage->Get(GetKeys(*as_dict));
184       if (result->HasError()) {
185         return UseReadResult(result.Pass());
186       }
187
188       base::DictionaryValue* with_default_values = as_dict->DeepCopy();
189       with_default_values->MergeDictionary(&result->settings());
190       return UseReadResult(
191           ValueStore::MakeReadResult(make_scoped_ptr(with_default_values)));
192     }
193
194     default:
195       EXTENSION_FUNCTION_VALIDATE(false);
196       return false;
197   }
198 }
199
200 bool StorageStorageAreaGetBytesInUseFunction::RunWithStorage(
201     ValueStore* storage) {
202   base::Value* input = NULL;
203   EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
204
205   size_t bytes_in_use = 0;
206
207   switch (input->GetType()) {
208     case base::Value::TYPE_NULL:
209       bytes_in_use = storage->GetBytesInUse();
210       break;
211
212     case base::Value::TYPE_STRING: {
213       std::string as_string;
214       input->GetAsString(&as_string);
215       bytes_in_use = storage->GetBytesInUse(as_string);
216       break;
217     }
218
219     case base::Value::TYPE_LIST: {
220       std::vector<std::string> as_string_list;
221       AddAllStringValues(*static_cast<base::ListValue*>(input),
222                          &as_string_list);
223       bytes_in_use = storage->GetBytesInUse(as_string_list);
224       break;
225     }
226
227     default:
228       EXTENSION_FUNCTION_VALIDATE(false);
229       return false;
230   }
231
232   SetResult(new base::FundamentalValue(static_cast<int>(bytes_in_use)));
233   return true;
234 }
235
236 bool StorageStorageAreaSetFunction::RunWithStorage(ValueStore* storage) {
237   base::DictionaryValue* input = NULL;
238   EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &input));
239   return UseWriteResult(storage->Set(ValueStore::DEFAULTS, *input));
240 }
241
242 void StorageStorageAreaSetFunction::GetQuotaLimitHeuristics(
243     QuotaLimitHeuristics* heuristics) const {
244   GetModificationQuotaLimitHeuristics(heuristics);
245 }
246
247 bool StorageStorageAreaRemoveFunction::RunWithStorage(ValueStore* storage) {
248   base::Value* input = NULL;
249   EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input));
250
251   switch (input->GetType()) {
252     case base::Value::TYPE_STRING: {
253       std::string as_string;
254       input->GetAsString(&as_string);
255       return UseWriteResult(storage->Remove(as_string));
256     }
257
258     case base::Value::TYPE_LIST: {
259       std::vector<std::string> as_string_list;
260       AddAllStringValues(*static_cast<base::ListValue*>(input),
261                          &as_string_list);
262       return UseWriteResult(storage->Remove(as_string_list));
263     }
264
265     default:
266       EXTENSION_FUNCTION_VALIDATE(false);
267       return false;
268   };
269 }
270
271 void StorageStorageAreaRemoveFunction::GetQuotaLimitHeuristics(
272     QuotaLimitHeuristics* heuristics) const {
273   GetModificationQuotaLimitHeuristics(heuristics);
274 }
275
276 bool StorageStorageAreaClearFunction::RunWithStorage(ValueStore* storage) {
277   return UseWriteResult(storage->Clear());
278 }
279
280 void StorageStorageAreaClearFunction::GetQuotaLimitHeuristics(
281     QuotaLimitHeuristics* heuristics) const {
282   GetModificationQuotaLimitHeuristics(heuristics);
283 }
284
285 }  // namespace extensions