Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: third_party/WebKit/Source/modules/indexeddb/IDBRequest.cpp

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: WIP: Getting IDBRequestTest.EventsAfterStopping to pass. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 Google Inc. All rights reserved. 2 * Copyright (C) 2010 Google Inc. All rights reserved.
3 * 3 *
4 * Redistribution and use in source and binary forms, with or without 4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions 5 * modification, are permitted provided that the following conditions
6 * are met: 6 * are met:
7 * 7 *
8 * 1. Redistributions of source code must retain the above copyright 8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright 10 * 2. Redistributions in binary form must reproduce the above copyright
(...skipping 11 matching lines...) Expand all
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28 28
29 #include "modules/indexeddb/IDBRequest.h" 29 #include "modules/indexeddb/IDBRequest.h"
30 30
31 #include <memory> 31 #include <memory>
32 #include <utility>
33
32 #include "bindings/core/v8/ExceptionState.h" 34 #include "bindings/core/v8/ExceptionState.h"
33 #include "bindings/core/v8/ToV8ForCore.h" 35 #include "bindings/core/v8/ToV8ForCore.h"
34 #include "bindings/modules/v8/ToV8ForModules.h" 36 #include "bindings/modules/v8/ToV8ForModules.h"
35 #include "bindings/modules/v8/V8BindingForModules.h" 37 #include "bindings/modules/v8/V8BindingForModules.h"
36 #include "core/dom/DOMException.h" 38 #include "core/dom/DOMException.h"
37 #include "core/dom/ExceptionCode.h" 39 #include "core/dom/ExceptionCode.h"
38 #include "core/dom/ExecutionContext.h" 40 #include "core/dom/ExecutionContext.h"
39 #include "core/events/EventQueue.h" 41 #include "core/events/EventQueue.h"
40 #include "modules/IndexedDBNames.h" 42 #include "modules/IndexedDBNames.h"
41 #include "modules/indexeddb/IDBCursorWithValue.h" 43 #include "modules/indexeddb/IDBCursorWithValue.h"
42 #include "modules/indexeddb/IDBDatabase.h" 44 #include "modules/indexeddb/IDBDatabase.h"
43 #include "modules/indexeddb/IDBEventDispatcher.h" 45 #include "modules/indexeddb/IDBEventDispatcher.h"
46 #include "modules/indexeddb/IDBRequestLoader.h"
47 #include "modules/indexeddb/IDBRequestQueueItem.h"
44 #include "modules/indexeddb/IDBTracing.h" 48 #include "modules/indexeddb/IDBTracing.h"
45 #include "modules/indexeddb/IDBValue.h" 49 #include "modules/indexeddb/IDBValue.h"
46 #include "modules/indexeddb/WebIDBCallbacksImpl.h" 50 #include "modules/indexeddb/WebIDBCallbacksImpl.h"
47 #include "platform/SharedBuffer.h" 51 #include "platform/SharedBuffer.h"
52 #include "platform/wtf/PtrUtil.h"
48 #include "public/platform/WebBlobInfo.h" 53 #include "public/platform/WebBlobInfo.h"
49 54
50 using blink::WebIDBCursor; 55 using blink::WebIDBCursor;
51 56
52 namespace blink { 57 namespace blink {
53 58
54 IDBRequest* IDBRequest::Create(ScriptState* script_state, 59 IDBRequest* IDBRequest::Create(ScriptState* script_state,
55 IDBAny* source, 60 IDBAny* source,
56 IDBTransaction* transaction) { 61 IDBTransaction* transaction) {
57 IDBRequest* request = new IDBRequest(script_state, source, transaction); 62 IDBRequest* request = new IDBRequest(script_state, source, transaction);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 if (result_->GetType() == IDBAny::kIDBCursorType) 203 if (result_->GetType() == IDBAny::kIDBCursorType)
199 return result_->IdbCursor(); 204 return result_->IdbCursor();
200 if (result_->GetType() == IDBAny::kIDBCursorWithValueType) 205 if (result_->GetType() == IDBAny::kIDBCursorWithValueType)
201 return result_->IdbCursorWithValue(); 206 return result_->IdbCursorWithValue();
202 return nullptr; 207 return nullptr;
203 } 208 }
204 209
205 void IDBRequest::SetResultCursor(IDBCursor* cursor, 210 void IDBRequest::SetResultCursor(IDBCursor* cursor,
206 IDBKey* key, 211 IDBKey* key,
207 IDBKey* primary_key, 212 IDBKey* primary_key,
208 PassRefPtr<IDBValue> value) { 213 RefPtr<IDBValue>&& value) {
209 DCHECK_EQ(ready_state_, PENDING); 214 DCHECK_EQ(ready_state_, PENDING);
210 cursor_key_ = key; 215 cursor_key_ = key;
211 cursor_primary_key_ = primary_key; 216 cursor_primary_key_ = primary_key;
212 cursor_value_ = std::move(value); 217 cursor_value_ = std::move(value);
213 AckReceivedBlobs(cursor_value_.Get()); 218 AckReceivedBlobs(cursor_value_.Get());
214 219
215 EnqueueResultInternal(IDBAny::Create(cursor)); 220 EnqueueResultInternal(IDBAny::Create(cursor));
216 } 221 }
217 222
218 void IDBRequest::AckReceivedBlobs(const IDBValue* value) { 223 void IDBRequest::AckReceivedBlobs(const IDBValue* value) {
(...skipping 13 matching lines...) Expand all
232 if (!GetExecutionContext()) 237 if (!GetExecutionContext())
233 return false; 238 return false;
234 DCHECK(ready_state_ == PENDING || ready_state_ == DONE); 239 DCHECK(ready_state_ == PENDING || ready_state_ == DONE);
235 if (request_aborted_) 240 if (request_aborted_)
236 return false; 241 return false;
237 DCHECK_EQ(ready_state_, PENDING); 242 DCHECK_EQ(ready_state_, PENDING);
238 DCHECK(!error_ && !result_); 243 DCHECK(!error_ && !result_);
239 return true; 244 return true;
240 } 245 }
241 246
247 void IDBRequest::HandleResponse(DOMException* error) {
248 transit_blob_handles_.clear();
249 if (!transaction_ || !transaction_->HasQueuedResults())
250 return EnqueueResponse(error);
251 transaction_->EnqueueResult(
252 WTF::MakeUnique<IDBRequestQueueItem>(this, error));
253 }
254
255 void IDBRequest::HandleResponse(IDBKey* key) {
256 transit_blob_handles_.clear();
jsbell 2017/05/15 23:37:37 Why is this cleared here but not in all HandleResp
pwnall 2017/05/19 18:27:33 This is only set in put() requests, which (IIUC) c
jsbell 2017/05/22 21:54:19 Yes, that would have answered my question before I
257 DCHECK(transaction_);
258 if (!transaction_->HasQueuedResults())
259 return EnqueueResponse(key);
260 transaction_->EnqueueResult(WTF::MakeUnique<IDBRequestQueueItem>(this, key));
261 }
262
263 void IDBRequest::HandleResponse(int64_t value_or_old_version) {
264 transit_blob_handles_.clear();
265 if (!transaction_ || !transaction_->HasQueuedResults())
266 return EnqueueResponse(value_or_old_version);
267 transaction_->EnqueueResult(
268 WTF::MakeUnique<IDBRequestQueueItem>(this, value_or_old_version));
269 }
270
271 void IDBRequest::HandleResponse() {
272 transit_blob_handles_.clear();
273 if (!transaction_ || !transaction_->HasQueuedResults())
274 return EnqueueResponse();
275 transaction_->EnqueueResult(WTF::MakeUnique<IDBRequestQueueItem>(this));
276 }
277
278 void IDBRequest::HandleResponse(std::unique_ptr<WebIDBCursor> backend,
279 IDBKey* key,
280 IDBKey* primary_key,
281 RefPtr<IDBValue>&& value) {
282 bool needs_unwrapping = IDBRequestLoader::NeedsUnwrapping(value.Get());
jsbell 2017/05/15 23:37:37 Maybe use the method on IDBValueWrapper to reduce
pwnall 2017/05/19 18:27:33 Done.
283 DCHECK(transaction_);
284 if (!transaction_->HasQueuedResults() && !needs_unwrapping) {
285 return EnqueueResponse(std::move(backend), key, primary_key,
286 std::move(value));
287 }
288 transaction_->EnqueueResult(WTF::MakeUnique<IDBRequestQueueItem>(
289 this, std::move(backend), key, primary_key, std::move(value),
290 needs_unwrapping));
291 }
292
293 void IDBRequest::HandleResponse(RefPtr<IDBValue>&& value) {
294 bool needs_unwrapping = IDBRequestLoader::NeedsUnwrapping(value.Get());
295 DCHECK(transaction_);
296 if (!transaction_->HasQueuedResults() && !needs_unwrapping)
297 return EnqueueResponse(std::move(value));
298 transaction_->EnqueueResult(WTF::MakeUnique<IDBRequestQueueItem>(
299 this, std::move(value), needs_unwrapping));
300 }
301
302 void IDBRequest::HandleResponse(const Vector<RefPtr<IDBValue>>& values) {
303 bool needs_unwrapping = IDBRequestLoader::NeedUnwrapping(values);
jsbell 2017/05/15 23:37:38 Maybe move NeedsUnwrapping to IDBValueWrapper to r
pwnall 2017/05/19 18:27:34 Done.
304 DCHECK(transaction_);
305 if (!transaction_->HasQueuedResults() && !needs_unwrapping)
306 return EnqueueResponse(values);
307 transaction_->EnqueueResult(
308 WTF::MakeUnique<IDBRequestQueueItem>(this, values, needs_unwrapping));
309 }
310
311 void IDBRequest::HandleResponse(IDBKey* key,
312 IDBKey* primary_key,
313 RefPtr<IDBValue>&& value) {
314 bool needs_unwrapping = IDBRequestLoader::NeedsUnwrapping(value.Get());
315
316 DCHECK(transaction_);
317 if (!transaction_->HasQueuedResults() && !needs_unwrapping)
318 return EnqueueResponse(key, primary_key, std::move(value));
319
320 transaction_->EnqueueResult(WTF::MakeUnique<IDBRequestQueueItem>(
321 this, key, primary_key, std::move(value), needs_unwrapping));
322 }
323
242 void IDBRequest::EnqueueResponse(DOMException* error) { 324 void IDBRequest::EnqueueResponse(DOMException* error) {
243 IDB_TRACE("IDBRequest::onError()"); 325 IDB_TRACE("IDBRequest::EnqueueResponse(DOMException)");
244 ClearPutOperationBlobs();
245 if (!ShouldEnqueueEvent()) 326 if (!ShouldEnqueueEvent())
246 return; 327 return;
247 328
248 error_ = error; 329 error_ = error;
249 SetResult(IDBAny::CreateUndefined()); 330 SetResult(IDBAny::CreateUndefined());
250 pending_cursor_.Clear(); 331 pending_cursor_.Clear();
251 EnqueueEvent(Event::CreateCancelableBubble(EventTypeNames::error)); 332 EnqueueEvent(Event::CreateCancelableBubble(EventTypeNames::error));
252 } 333 }
253 334
254 void IDBRequest::EnqueueResponse(const Vector<String>& string_list) { 335 void IDBRequest::EnqueueResponse(const Vector<String>& string_list) {
255 IDB_TRACE("IDBRequest::onSuccess(StringList)"); 336 IDB_TRACE("IDBRequest::onSuccess(StringList)");
256 if (!ShouldEnqueueEvent()) 337 if (!ShouldEnqueueEvent())
257 return; 338 return;
258 339
259 DOMStringList* dom_string_list = DOMStringList::Create(); 340 DOMStringList* dom_string_list = DOMStringList::Create();
260 for (size_t i = 0; i < string_list.size(); ++i) 341 for (size_t i = 0; i < string_list.size(); ++i)
261 dom_string_list->Append(string_list[i]); 342 dom_string_list->Append(string_list[i]);
262 EnqueueResultInternal(IDBAny::Create(dom_string_list)); 343 EnqueueResultInternal(IDBAny::Create(dom_string_list));
263 } 344 }
264 345
265 void IDBRequest::EnqueueResponse(std::unique_ptr<WebIDBCursor> backend, 346 void IDBRequest::EnqueueResponse(std::unique_ptr<WebIDBCursor> backend,
266 IDBKey* key, 347 IDBKey* key,
267 IDBKey* primary_key, 348 IDBKey* primary_key,
268 PassRefPtr<IDBValue> value) { 349 RefPtr<IDBValue>&& value) {
269 IDB_TRACE("IDBRequest::onSuccess(IDBCursor)"); 350 IDB_TRACE("IDBRequest::EnqueueResponse(IDBCursor)");
270 if (!ShouldEnqueueEvent()) 351 if (!ShouldEnqueueEvent())
271 return; 352 return;
272 353
273 DCHECK(!pending_cursor_); 354 DCHECK(!pending_cursor_);
274 IDBCursor* cursor = nullptr; 355 IDBCursor* cursor = nullptr;
275 switch (cursor_type_) { 356 switch (cursor_type_) {
276 case IndexedDB::kCursorKeyOnly: 357 case IndexedDB::kCursorKeyOnly:
277 cursor = IDBCursor::Create(std::move(backend), cursor_direction_, this, 358 cursor = IDBCursor::Create(std::move(backend), cursor_direction_, this,
278 source_.Get(), transaction_.Get()); 359 source_.Get(), transaction_.Get());
279 break; 360 break;
280 case IndexedDB::kCursorKeyAndValue: 361 case IndexedDB::kCursorKeyAndValue:
281 cursor = 362 cursor =
282 IDBCursorWithValue::Create(std::move(backend), cursor_direction_, 363 IDBCursorWithValue::Create(std::move(backend), cursor_direction_,
283 this, source_.Get(), transaction_.Get()); 364 this, source_.Get(), transaction_.Get());
284 break; 365 break;
285 default: 366 default:
286 NOTREACHED(); 367 NOTREACHED();
287 } 368 }
288 SetResultCursor(cursor, key, primary_key, std::move(value)); 369 SetResultCursor(cursor, key, primary_key, std::move(value));
289 } 370 }
290 371
291 void IDBRequest::EnqueueResponse(IDBKey* idb_key) { 372 void IDBRequest::EnqueueResponse(IDBKey* idb_key) {
292 IDB_TRACE("IDBRequest::onSuccess(IDBKey)"); 373 IDB_TRACE("IDBRequest::EnqueueResponse(IDBKey)");
293 ClearPutOperationBlobs();
294 if (!ShouldEnqueueEvent()) 374 if (!ShouldEnqueueEvent())
295 return; 375 return;
296 376
297 if (idb_key && idb_key->IsValid()) 377 if (idb_key && idb_key->IsValid())
298 EnqueueResultInternal(IDBAny::Create(idb_key)); 378 EnqueueResultInternal(IDBAny::Create(idb_key));
299 else 379 else
300 EnqueueResultInternal(IDBAny::CreateUndefined()); 380 EnqueueResultInternal(IDBAny::CreateUndefined());
301 } 381 }
302 382
303 void IDBRequest::EnqueueResponse(const Vector<RefPtr<IDBValue>>& values) { 383 void IDBRequest::EnqueueResponse(const Vector<RefPtr<IDBValue>>& values) {
304 IDB_TRACE("IDBRequest::onSuccess([IDBValue])"); 384 IDB_TRACE("IDBRequest::EnqueueResponse([IDBValue])");
305 if (!ShouldEnqueueEvent()) 385 if (!ShouldEnqueueEvent())
306 return; 386 return;
307 387
308 AckReceivedBlobs(values); 388 AckReceivedBlobs(values);
309 EnqueueResultInternal(IDBAny::Create(values)); 389 EnqueueResultInternal(IDBAny::Create(values));
310 } 390 }
311 391
312 #if DCHECK_IS_ON() 392 #if DCHECK_IS_ON()
313 static IDBObjectStore* EffectiveObjectStore(IDBAny* source) { 393 static IDBObjectStore* EffectiveObjectStore(IDBAny* source) {
314 if (source->GetType() == IDBAny::kIDBObjectStoreType) 394 if (source->GetType() == IDBAny::kIDBObjectStoreType)
315 return source->IdbObjectStore(); 395 return source->IdbObjectStore();
316 if (source->GetType() == IDBAny::kIDBIndexType) 396 if (source->GetType() == IDBAny::kIDBIndexType)
317 return source->IdbIndex()->objectStore(); 397 return source->IdbIndex()->objectStore();
318 398
319 NOTREACHED(); 399 NOTREACHED();
320 return nullptr; 400 return nullptr;
321 } 401 }
322 #endif // DCHECK_IS_ON() 402 #endif // DCHECK_IS_ON()
323 403
324 void IDBRequest::EnqueueResponse(PassRefPtr<IDBValue> prp_value) { 404 void IDBRequest::EnqueueResponse(RefPtr<IDBValue>&& value) {
325 IDB_TRACE("IDBRequest::onSuccess(IDBValue)"); 405 IDB_TRACE("IDBRequest::EnqueueResponse(IDBValue)");
326 if (!ShouldEnqueueEvent()) 406 if (!ShouldEnqueueEvent())
327 return; 407 return;
328 408
329 RefPtr<IDBValue> value(std::move(prp_value));
330 AckReceivedBlobs(value.Get()); 409 AckReceivedBlobs(value.Get());
331 410
332 if (pending_cursor_) { 411 if (pending_cursor_) {
333 // Value should be null, signifying the end of the cursor's range. 412 // Value should be null, signifying the end of the cursor's range.
334 DCHECK(value->IsNull()); 413 DCHECK(value->IsNull());
335 DCHECK(!value->BlobInfo()->size()); 414 DCHECK(!value->BlobInfo()->size());
336 pending_cursor_->Close(); 415 pending_cursor_->Close();
337 pending_cursor_.Clear(); 416 pending_cursor_.Clear();
338 } 417 }
339 418
340 #if DCHECK_IS_ON() 419 #if DCHECK_IS_ON()
341 DCHECK(!value->PrimaryKey() || 420 DCHECK(!value->PrimaryKey() ||
342 value->KeyPath() == EffectiveObjectStore(source_)->IdbKeyPath()); 421 value->KeyPath() == EffectiveObjectStore(source_)->IdbKeyPath());
343 #endif 422 #endif
344 423
345 EnqueueResultInternal(IDBAny::Create(value.Release())); 424 EnqueueResultInternal(IDBAny::Create(std::move(value)));
346 } 425 }
347 426
348 void IDBRequest::EnqueueResponse(int64_t value) { 427 void IDBRequest::EnqueueResponse(int64_t value) {
349 IDB_TRACE("IDBRequest::onSuccess(int64_t)"); 428 IDB_TRACE("IDBRequest::EnqueueResponse(int64_t)");
350 if (!ShouldEnqueueEvent()) 429 if (!ShouldEnqueueEvent())
351 return; 430 return;
352 EnqueueResultInternal(IDBAny::Create(value)); 431 EnqueueResultInternal(IDBAny::Create(value));
353 } 432 }
354 433
355 void IDBRequest::EnqueueResponse() { 434 void IDBRequest::EnqueueResponse() {
356 IDB_TRACE("IDBRequest::onSuccess()"); 435 IDB_TRACE("IDBRequest::EnqueueResponse()");
357 if (!ShouldEnqueueEvent()) 436 if (!ShouldEnqueueEvent())
358 return; 437 return;
359 EnqueueResultInternal(IDBAny::CreateUndefined()); 438 EnqueueResultInternal(IDBAny::CreateUndefined());
360 } 439 }
361 440
362 void IDBRequest::EnqueueResultInternal(IDBAny* result) { 441 void IDBRequest::EnqueueResultInternal(IDBAny* result) {
363 DCHECK(GetExecutionContext()); 442 DCHECK(GetExecutionContext());
364 DCHECK(!pending_cursor_); 443 DCHECK(!pending_cursor_);
365 DCHECK(transit_blob_handles_.IsEmpty()); 444 DCHECK(transit_blob_handles_.IsEmpty());
366 SetResult(result); 445 SetResult(result);
367 EnqueueEvent(Event::Create(EventTypeNames::success)); 446 EnqueueEvent(Event::Create(EventTypeNames::success));
368 } 447 }
369 448
370 void IDBRequest::SetResult(IDBAny* result) { 449 void IDBRequest::SetResult(IDBAny* result) {
371 result_ = result; 450 result_ = result;
372 result_dirty_ = true; 451 result_dirty_ = true;
373 } 452 }
374 453
375 void IDBRequest::EnqueueResponse(IDBKey* key, 454 void IDBRequest::EnqueueResponse(IDBKey* key,
376 IDBKey* primary_key, 455 IDBKey* primary_key,
377 PassRefPtr<IDBValue> value) { 456 RefPtr<IDBValue>&& value) {
378 IDB_TRACE("IDBRequest::onSuccess(key, primaryKey, value)"); 457 IDB_TRACE("IDBRequest::EnqueueResponse(IDBKey, IDBKey primaryKey, IDBValue)");
379 if (!ShouldEnqueueEvent()) 458 if (!ShouldEnqueueEvent())
380 return; 459 return;
381 460
382 DCHECK(pending_cursor_); 461 DCHECK(pending_cursor_);
383 SetResultCursor(pending_cursor_.Release(), key, primary_key, 462 SetResultCursor(pending_cursor_.Release(), key, primary_key,
384 std::move(value)); 463 std::move(value));
385 } 464 }
386 465
387 bool IDBRequest::HasPendingActivity() const { 466 bool IDBRequest::HasPendingActivity() const {
388 // FIXME: In an ideal world, we should return true as long as anyone has a or 467 // FIXME: In an ideal world, we should return true as long as anyone has a or
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 } 635 }
557 636
558 void IDBRequest::DequeueEvent(Event* event) { 637 void IDBRequest::DequeueEvent(Event* event) {
559 for (size_t i = 0; i < enqueued_events_.size(); ++i) { 638 for (size_t i = 0; i < enqueued_events_.size(); ++i) {
560 if (enqueued_events_[i].Get() == event) 639 if (enqueued_events_[i].Get() == event)
561 enqueued_events_.erase(i); 640 enqueued_events_.erase(i);
562 } 641 }
563 } 642 }
564 643
565 } // namespace blink 644 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698