Respond with QuotaExceededError when IndexedDB has no disk space on open.
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_callbacks.cc
blob46270db75311620877979a1bec17e1464fc9b51e
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.
5 #include "content/browser/indexed_db/indexed_db_callbacks.h"
7 #include <algorithm>
9 #include "content/browser/indexed_db/indexed_db_connection.h"
10 #include "content/browser/indexed_db/indexed_db_cursor.h"
11 #include "content/browser/indexed_db/indexed_db_database_callbacks.h"
12 #include "content/browser/indexed_db/indexed_db_database_error.h"
13 #include "content/browser/indexed_db/indexed_db_metadata.h"
14 #include "content/common/indexed_db/indexed_db_messages.h"
15 #include "webkit/browser/quota/quota_manager.h"
17 using WebKit::WebIDBCallbacks;
19 namespace content {
21 namespace {
22 const int32 kNoCursor = -1;
23 const int32 kNoDatabase = -1;
24 const int32 kNoDatabaseCallbacks = -1;
25 const int64 kNoTransaction = -1;
28 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
29 int32 ipc_thread_id,
30 int32 ipc_callbacks_id)
31 : dispatcher_host_(dispatcher_host),
32 ipc_callbacks_id_(ipc_callbacks_id),
33 ipc_thread_id_(ipc_thread_id),
34 ipc_cursor_id_(kNoCursor),
35 host_transaction_id_(kNoTransaction),
36 ipc_database_id_(kNoDatabase),
37 ipc_database_callbacks_id_(kNoDatabaseCallbacks) {}
39 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
40 int32 ipc_thread_id,
41 int32 ipc_callbacks_id,
42 int32 ipc_cursor_id)
43 : dispatcher_host_(dispatcher_host),
44 ipc_callbacks_id_(ipc_callbacks_id),
45 ipc_thread_id_(ipc_thread_id),
46 ipc_cursor_id_(ipc_cursor_id),
47 host_transaction_id_(kNoTransaction),
48 ipc_database_id_(kNoDatabase),
49 ipc_database_callbacks_id_(kNoDatabaseCallbacks) {}
51 IndexedDBCallbacks::IndexedDBCallbacks(IndexedDBDispatcherHost* dispatcher_host,
52 int32 ipc_thread_id,
53 int32 ipc_callbacks_id,
54 int32 ipc_database_callbacks_id,
55 int64 host_transaction_id,
56 const GURL& origin_url)
57 : dispatcher_host_(dispatcher_host),
58 ipc_callbacks_id_(ipc_callbacks_id),
59 ipc_thread_id_(ipc_thread_id),
60 ipc_cursor_id_(kNoCursor),
61 host_transaction_id_(host_transaction_id),
62 origin_url_(origin_url),
63 ipc_database_id_(kNoDatabase),
64 ipc_database_callbacks_id_(ipc_database_callbacks_id) {}
66 IndexedDBCallbacks::~IndexedDBCallbacks() {}
68 void IndexedDBCallbacks::OnError(const IndexedDBDatabaseError& error) {
69 DCHECK(dispatcher_host_.get());
71 dispatcher_host_->Send(new IndexedDBMsg_CallbacksError(
72 ipc_thread_id_, ipc_callbacks_id_, error.code(), error.message()));
73 dispatcher_host_ = NULL;
76 void IndexedDBCallbacks::OnSuccess(const std::vector<string16>& value) {
77 DCHECK(dispatcher_host_.get());
79 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
80 DCHECK_EQ(kNoTransaction, host_transaction_id_);
81 DCHECK_EQ(kNoDatabase, ipc_database_id_);
82 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
84 std::vector<string16> list;
85 for (unsigned i = 0; i < value.size(); ++i)
86 list.push_back(value[i]);
88 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessStringList(
89 ipc_thread_id_, ipc_callbacks_id_, list));
90 dispatcher_host_ = NULL;
93 void IndexedDBCallbacks::OnBlocked(int64 existing_version) {
94 DCHECK(dispatcher_host_.get());
96 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
97 // No transaction/db callbacks for DeleteDatabase.
98 DCHECK_EQ(kNoTransaction == host_transaction_id_,
99 kNoDatabaseCallbacks == ipc_database_callbacks_id_);
100 DCHECK_EQ(kNoDatabase, ipc_database_id_);
102 dispatcher_host_->Send(new IndexedDBMsg_CallbacksIntBlocked(
103 ipc_thread_id_, ipc_callbacks_id_, existing_version));
106 void IndexedDBCallbacks::OnUpgradeNeeded(
107 int64 old_version,
108 scoped_ptr<IndexedDBConnection> connection,
109 const IndexedDBDatabaseMetadata& metadata,
110 WebIDBCallbacks::DataLoss data_loss) {
111 DCHECK(dispatcher_host_.get());
113 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
114 DCHECK_NE(kNoTransaction, host_transaction_id_);
115 DCHECK_EQ(kNoDatabase, ipc_database_id_);
116 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
118 dispatcher_host_->RegisterTransactionId(host_transaction_id_, origin_url_);
119 int32 ipc_database_id =
120 dispatcher_host_->Add(connection.release(), ipc_thread_id_, origin_url_);
121 if (ipc_database_id < 0)
122 return;
123 ipc_database_id_ = ipc_database_id;
124 IndexedDBMsg_CallbacksUpgradeNeeded_Params params;
125 params.ipc_thread_id = ipc_thread_id_;
126 params.ipc_callbacks_id = ipc_callbacks_id_;
127 params.ipc_database_id = ipc_database_id;
128 params.ipc_database_callbacks_id = ipc_database_callbacks_id_;
129 params.old_version = old_version;
130 params.idb_metadata = IndexedDBDispatcherHost::ConvertMetadata(metadata);
131 params.data_loss = data_loss;
132 dispatcher_host_->Send(new IndexedDBMsg_CallbacksUpgradeNeeded(params));
135 void IndexedDBCallbacks::OnSuccess(scoped_ptr<IndexedDBConnection> connection,
136 const IndexedDBDatabaseMetadata& metadata) {
137 DCHECK(dispatcher_host_.get());
139 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
140 DCHECK_NE(kNoTransaction, host_transaction_id_);
141 DCHECK_NE(ipc_database_id_ == kNoDatabase, !connection);
142 DCHECK_NE(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
144 scoped_refptr<IndexedDBCallbacks> self(this);
146 int32 ipc_object_id = ipc_database_id_;
147 if (ipc_object_id == kNoDatabase) {
148 ipc_object_id = dispatcher_host_->Add(
149 connection.release(), ipc_thread_id_, origin_url_);
152 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBDatabase(
153 ipc_thread_id_,
154 ipc_callbacks_id_,
155 ipc_database_callbacks_id_,
156 ipc_object_id,
157 IndexedDBDispatcherHost::ConvertMetadata(metadata)));
158 dispatcher_host_ = NULL;
161 void IndexedDBCallbacks::OnSuccess(scoped_refptr<IndexedDBCursor> cursor,
162 const IndexedDBKey& key,
163 const IndexedDBKey& primary_key,
164 std::string* value) {
165 DCHECK(dispatcher_host_.get());
167 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
168 DCHECK_EQ(kNoTransaction, host_transaction_id_);
169 DCHECK_EQ(kNoDatabase, ipc_database_id_);
170 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
172 int32 ipc_object_id = dispatcher_host_->Add(cursor.get());
173 IndexedDBMsg_CallbacksSuccessIDBCursor_Params params;
174 params.ipc_thread_id = ipc_thread_id_;
175 params.ipc_callbacks_id = ipc_callbacks_id_;
176 params.ipc_cursor_id = ipc_object_id;
177 params.key = key;
178 params.primary_key = primary_key;
179 if (value && !value->empty())
180 std::swap(params.value, *value);
181 // TODO(alecflett): Avoid a copy here: the whole params object is
182 // being copied into the message.
183 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIDBCursor(params));
185 dispatcher_host_ = NULL;
188 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& key,
189 const IndexedDBKey& primary_key,
190 std::string* value) {
191 DCHECK(dispatcher_host_.get());
193 DCHECK_NE(kNoCursor, ipc_cursor_id_);
194 DCHECK_EQ(kNoTransaction, host_transaction_id_);
195 DCHECK_EQ(kNoDatabase, ipc_database_id_);
196 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
198 IndexedDBCursor* idb_cursor =
199 dispatcher_host_->GetCursorFromId(ipc_cursor_id_);
201 DCHECK(idb_cursor);
202 if (!idb_cursor)
203 return;
204 IndexedDBMsg_CallbacksSuccessCursorContinue_Params params;
205 params.ipc_thread_id = ipc_thread_id_;
206 params.ipc_callbacks_id = ipc_callbacks_id_;
207 params.ipc_cursor_id = ipc_cursor_id_;
208 params.key = key;
209 params.primary_key = primary_key;
210 if (value && !value->empty())
211 std::swap(params.value, *value);
212 // TODO(alecflett): Avoid a copy here: the whole params object is
213 // being copied into the message.
214 dispatcher_host_->Send(
215 new IndexedDBMsg_CallbacksSuccessCursorContinue(params));
216 dispatcher_host_ = NULL;
219 void IndexedDBCallbacks::OnSuccessWithPrefetch(
220 const std::vector<IndexedDBKey>& keys,
221 const std::vector<IndexedDBKey>& primary_keys,
222 const std::vector<std::string>& values) {
223 DCHECK_EQ(keys.size(), primary_keys.size());
224 DCHECK_EQ(keys.size(), values.size());
226 DCHECK(dispatcher_host_.get());
228 DCHECK_NE(kNoCursor, ipc_cursor_id_);
229 DCHECK_EQ(kNoTransaction, host_transaction_id_);
230 DCHECK_EQ(kNoDatabase, ipc_database_id_);
231 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
233 std::vector<IndexedDBKey> msgKeys;
234 std::vector<IndexedDBKey> msgPrimaryKeys;
236 for (size_t i = 0; i < keys.size(); ++i) {
237 msgKeys.push_back(keys[i]);
238 msgPrimaryKeys.push_back(primary_keys[i]);
241 IndexedDBMsg_CallbacksSuccessCursorPrefetch_Params params;
242 params.ipc_thread_id = ipc_thread_id_;
243 params.ipc_callbacks_id = ipc_callbacks_id_;
244 params.ipc_cursor_id = ipc_cursor_id_;
245 params.keys = msgKeys;
246 params.primary_keys = msgPrimaryKeys;
247 params.values = values;
248 dispatcher_host_->Send(
249 new IndexedDBMsg_CallbacksSuccessCursorPrefetch(params));
250 dispatcher_host_ = NULL;
253 void IndexedDBCallbacks::OnSuccess(std::string* value,
254 const IndexedDBKey& key,
255 const IndexedDBKeyPath& key_path) {
256 DCHECK(dispatcher_host_.get());
258 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
259 DCHECK_EQ(kNoTransaction, host_transaction_id_);
260 DCHECK_EQ(kNoDatabase, ipc_database_id_);
261 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
263 std::string value_copy;
264 if (value && !value->empty())
265 std::swap(value_copy, *value);
267 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValueWithKey(
268 ipc_thread_id_,
269 ipc_callbacks_id_,
270 // TODO(alecflett): Avoid a copy here.
271 value_copy,
272 key,
273 key_path));
274 dispatcher_host_ = NULL;
277 void IndexedDBCallbacks::OnSuccess(std::string* value) {
278 DCHECK(dispatcher_host_.get());
280 DCHECK(kNoCursor == ipc_cursor_id_ || value == NULL);
281 DCHECK_EQ(kNoTransaction, host_transaction_id_);
282 DCHECK_EQ(kNoDatabase, ipc_database_id_);
283 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
285 std::string value_copy;
286 if (value && !value->empty())
287 std::swap(value_copy, *value);
289 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessValue(
290 ipc_thread_id_,
291 ipc_callbacks_id_,
292 // TODO(alecflett): avoid a copy here.
293 value_copy));
294 dispatcher_host_ = NULL;
297 void IndexedDBCallbacks::OnSuccess(const IndexedDBKey& value) {
298 DCHECK(dispatcher_host_.get());
300 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
301 DCHECK_EQ(kNoTransaction, host_transaction_id_);
302 DCHECK_EQ(kNoDatabase, ipc_database_id_);
303 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
305 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessIndexedDBKey(
306 ipc_thread_id_, ipc_callbacks_id_, value));
307 dispatcher_host_ = NULL;
310 void IndexedDBCallbacks::OnSuccess(int64 value) {
311 DCHECK(dispatcher_host_.get());
313 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
314 DCHECK_EQ(kNoTransaction, host_transaction_id_);
315 DCHECK_EQ(kNoDatabase, ipc_database_id_);
316 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
318 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessInteger(
319 ipc_thread_id_, ipc_callbacks_id_, value));
320 dispatcher_host_ = NULL;
323 void IndexedDBCallbacks::OnSuccess() {
324 DCHECK(dispatcher_host_.get());
326 DCHECK_EQ(kNoCursor, ipc_cursor_id_);
327 DCHECK_EQ(kNoTransaction, host_transaction_id_);
328 DCHECK_EQ(kNoDatabase, ipc_database_id_);
329 DCHECK_EQ(kNoDatabaseCallbacks, ipc_database_callbacks_id_);
331 dispatcher_host_->Send(new IndexedDBMsg_CallbacksSuccessUndefined(
332 ipc_thread_id_, ipc_callbacks_id_));
333 dispatcher_host_ = NULL;
336 } // namespace content