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

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

Issue 2822453003: Wrap large IndexedDB values into Blobs before writing to LevelDB. (Closed)
Patch Set: Addressed last round of feedback. Created 3 years, 6 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 22 matching lines...) Expand all
33 #include "bindings/modules/v8/ToV8ForModules.h" 33 #include "bindings/modules/v8/ToV8ForModules.h"
34 #include "bindings/modules/v8/V8BindingForModules.h" 34 #include "bindings/modules/v8/V8BindingForModules.h"
35 #include "core/dom/DOMStringList.h" 35 #include "core/dom/DOMStringList.h"
36 #include "core/dom/ExceptionCode.h" 36 #include "core/dom/ExceptionCode.h"
37 #include "core/dom/ExecutionContext.h" 37 #include "core/dom/ExecutionContext.h"
38 #include "modules/indexeddb/IDBAny.h" 38 #include "modules/indexeddb/IDBAny.h"
39 #include "modules/indexeddb/IDBCursorWithValue.h" 39 #include "modules/indexeddb/IDBCursorWithValue.h"
40 #include "modules/indexeddb/IDBDatabase.h" 40 #include "modules/indexeddb/IDBDatabase.h"
41 #include "modules/indexeddb/IDBKeyPath.h" 41 #include "modules/indexeddb/IDBKeyPath.h"
42 #include "modules/indexeddb/IDBTracing.h" 42 #include "modules/indexeddb/IDBTracing.h"
43 #include "modules/indexeddb/IDBValueWrapping.h"
43 #include "platform/Histogram.h" 44 #include "platform/Histogram.h"
44 #include "platform/SharedBuffer.h" 45 #include "platform/SharedBuffer.h"
45 #include "platform/bindings/ScriptState.h" 46 #include "platform/bindings/ScriptState.h"
47 #include "platform/wtf/RefPtr.h"
46 #include "public/platform/WebBlobInfo.h" 48 #include "public/platform/WebBlobInfo.h"
47 #include "public/platform/WebData.h" 49 #include "public/platform/WebData.h"
48 #include "public/platform/WebVector.h" 50 #include "public/platform/WebVector.h"
49 #include "public/platform/modules/indexeddb/WebIDBKey.h" 51 #include "public/platform/modules/indexeddb/WebIDBKey.h"
50 #include "public/platform/modules/indexeddb/WebIDBKeyRange.h" 52 #include "public/platform/modules/indexeddb/WebIDBKeyRange.h"
51 #include "v8/include/v8.h" 53 #include "v8/include/v8.h"
52 54
53 using blink::WebBlobInfo; 55 using blink::WebBlobInfo;
54 using blink::WebIDBCallbacks; 56 using blink::WebIDBCallbacks;
55 using blink::WebIDBCursor; 57 using blink::WebIDBCursor;
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
369 return nullptr; 371 return nullptr;
370 } 372 }
371 if (transaction_->IsReadOnly()) { 373 if (transaction_->IsReadOnly()) {
372 exception_state.ThrowDOMException( 374 exception_state.ThrowDOMException(
373 kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage); 375 kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage);
374 return nullptr; 376 return nullptr;
375 } 377 }
376 378
377 v8::Isolate* isolate = script_state->GetIsolate(); 379 v8::Isolate* isolate = script_state->GetIsolate();
378 DCHECK(isolate->InContext()); 380 DCHECK(isolate->InContext());
379 Vector<WebBlobInfo> blob_info;
380 SerializedScriptValue::SerializeOptions options;
381 options.blob_info = &blob_info;
382
383 // TODO(crbug.com/719053): This wasm behavior differs from other browsers. 381 // TODO(crbug.com/719053): This wasm behavior differs from other browsers.
384 options.wasm_policy = 382 SerializedScriptValue::SerializeOptions::WasmSerializationPolicy wasm_policy =
385 ExecutionContext::From(script_state)->IsSecureContext() 383 ExecutionContext::From(script_state)->IsSecureContext()
386 ? SerializedScriptValue::SerializeOptions::kSerialize 384 ? SerializedScriptValue::SerializeOptions::kSerialize
387 : SerializedScriptValue::SerializeOptions::kBlockedInNonSecureContext; 385 : SerializedScriptValue::SerializeOptions::kBlockedInNonSecureContext;
388 options.for_storage = SerializedScriptValue::kForStorage; 386 IDBValueWrapper value_wrapper(isolate, value.V8Value(), wasm_policy,
389 RefPtr<SerializedScriptValue> serialized_value = 387 exception_state);
390 SerializedScriptValue::Serialize(isolate, value.V8Value(), options,
391 exception_state);
392 if (exception_state.HadException()) 388 if (exception_state.HadException())
393 return nullptr; 389 return nullptr;
394 390
395 // Keys that need to be extracted must be taken from a clone so that 391 // Keys that need to be extracted must be taken from a clone so that
396 // side effects (i.e. getters) are not triggered. Construct the 392 // side effects (i.e. getters) are not triggered. Construct the
397 // clone lazily since the operation may be expensive. 393 // clone lazily since the operation may be expensive.
398 ScriptValue clone; 394 ScriptValue clone;
399 395
400 const IDBKeyPath& key_path = IdbKeyPath(); 396 const IDBKeyPath& key_path = IdbKeyPath();
401 const bool uses_in_line_keys = !key_path.IsNull(); 397 const bool uses_in_line_keys = !key_path.IsNull();
402 const bool has_key_generator = autoIncrement(); 398 const bool has_key_generator = autoIncrement();
403 399
404 if (put_mode != kWebIDBPutModeCursorUpdate && uses_in_line_keys && key) { 400 if (put_mode != kWebIDBPutModeCursorUpdate && uses_in_line_keys && key) {
405 exception_state.ThrowDOMException(kDataError, 401 exception_state.ThrowDOMException(kDataError,
406 "The object store uses in-line keys and " 402 "The object store uses in-line keys and "
407 "the key parameter was provided."); 403 "the key parameter was provided.");
408 return nullptr; 404 return nullptr;
409 } 405 }
410 406
411 // This test logically belongs in IDBCursor, but must operate on the cloned 407 // This test logically belongs in IDBCursor, but must operate on the cloned
412 // value. 408 // value.
413 if (put_mode == kWebIDBPutModeCursorUpdate && uses_in_line_keys) { 409 if (put_mode == kWebIDBPutModeCursorUpdate && uses_in_line_keys) {
414 DCHECK(key); 410 DCHECK(key);
415 if (clone.IsEmpty()) 411 DCHECK(clone.IsEmpty());
416 clone = DeserializeScriptValue(script_state, serialized_value.Get(), 412 value_wrapper.Clone(script_state, &clone);
417 &blob_info);
418 IDBKey* key_path_key = ScriptValue::To<IDBKey*>( 413 IDBKey* key_path_key = ScriptValue::To<IDBKey*>(
419 script_state->GetIsolate(), clone, exception_state, key_path); 414 script_state->GetIsolate(), clone, exception_state, key_path);
420 if (exception_state.HadException()) 415 if (exception_state.HadException())
421 return nullptr; 416 return nullptr;
422 if (!key_path_key || !key_path_key->IsEqual(key)) { 417 if (!key_path_key || !key_path_key->IsEqual(key)) {
423 exception_state.ThrowDOMException( 418 exception_state.ThrowDOMException(
424 kDataError, 419 kDataError,
425 "The effective object store of this cursor uses in-line keys and " 420 "The effective object store of this cursor uses in-line keys and "
426 "evaluating the key path of the value parameter results in a " 421 "evaluating the key path of the value parameter results in a "
427 "different value than the cursor's effective key."); 422 "different value than the cursor's effective key.");
428 return nullptr; 423 return nullptr;
429 } 424 }
430 } 425 }
431 426
432 if (!uses_in_line_keys && !has_key_generator && !key) { 427 if (!uses_in_line_keys && !has_key_generator && !key) {
433 exception_state.ThrowDOMException(kDataError, 428 exception_state.ThrowDOMException(kDataError,
434 "The object store uses out-of-line keys " 429 "The object store uses out-of-line keys "
435 "and has no key generator and the key " 430 "and has no key generator and the key "
436 "parameter was not provided."); 431 "parameter was not provided.");
437 return nullptr; 432 return nullptr;
438 } 433 }
439 if (uses_in_line_keys) { 434 if (uses_in_line_keys) {
440 if (clone.IsEmpty()) { 435 if (clone.IsEmpty())
441 clone = DeserializeScriptValue(script_state, serialized_value.Get(), 436 value_wrapper.Clone(script_state, &clone);
442 &blob_info);
443 }
444 IDBKey* key_path_key = ScriptValue::To<IDBKey*>( 437 IDBKey* key_path_key = ScriptValue::To<IDBKey*>(
445 script_state->GetIsolate(), clone, exception_state, key_path); 438 script_state->GetIsolate(), clone, exception_state, key_path);
446 if (exception_state.HadException()) 439 if (exception_state.HadException())
447 return nullptr; 440 return nullptr;
448 if (key_path_key && !key_path_key->IsValid()) { 441 if (key_path_key && !key_path_key->IsValid()) {
449 exception_state.ThrowDOMException( 442 exception_state.ThrowDOMException(
450 kDataError, 443 kDataError,
451 "Evaluating the object store's key path " 444 "Evaluating the object store's key path "
452 "yielded a value that is not a valid " 445 "yielded a value that is not a valid "
453 "key."); 446 "key.");
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 DEFINE_THREAD_SAFE_STATIC_LOCAL( 480 DEFINE_THREAD_SAFE_STATIC_LOCAL(
488 EnumerationHistogram, key_type_histogram, 481 EnumerationHistogram, key_type_histogram,
489 new EnumerationHistogram("WebCore.IndexedDB.ObjectStore.Record.KeyType", 482 new EnumerationHistogram("WebCore.IndexedDB.ObjectStore.Record.KeyType",
490 static_cast<int>(IDBKey::kTypeEnumMax))); 483 static_cast<int>(IDBKey::kTypeEnumMax)));
491 key_type_histogram.Count(static_cast<int>(key->GetType())); 484 key_type_histogram.Count(static_cast<int>(key->GetType()));
492 } 485 }
493 486
494 Vector<int64_t> index_ids; 487 Vector<int64_t> index_ids;
495 HeapVector<IndexKeys> index_keys; 488 HeapVector<IndexKeys> index_keys;
496 for (const auto& it : Metadata().indexes) { 489 for (const auto& it : Metadata().indexes) {
497 if (clone.IsEmpty()) { 490 if (clone.IsEmpty())
498 clone = DeserializeScriptValue(script_state, serialized_value.Get(), 491 value_wrapper.Clone(script_state, &clone);
499 &blob_info);
500 }
501 IndexKeys keys; 492 IndexKeys keys;
502 GenerateIndexKeysForValue(script_state->GetIsolate(), *it.value, clone, 493 GenerateIndexKeysForValue(script_state->GetIsolate(), *it.value, clone,
503 &keys); 494 &keys);
504 index_ids.push_back(it.key); 495 index_ids.push_back(it.key);
505 index_keys.push_back(keys); 496 index_keys.push_back(keys);
506 } 497 }
507 498
508 IDBRequest* request = 499 IDBRequest* request =
509 IDBRequest::Create(script_state, source, transaction_.Get()); 500 IDBRequest::Create(script_state, source, transaction_.Get());
510 Vector<char> wire_bytes;
511 serialized_value->ToWireBytes(wire_bytes);
512 RefPtr<SharedBuffer> value_buffer = SharedBuffer::AdoptVector(wire_bytes);
513 501
514 request->StorePutOperationBlobs(serialized_value->BlobDataHandles()); 502 value_wrapper.ExtractBlobDataHandles(request->transit_blob_handles());
503 value_wrapper.WrapIfBiggerThan(IDBValueWrapper::kWrapThreshold);
515 504
516 BackendDB()->Put(transaction_->Id(), Id(), WebData(value_buffer), blob_info, 505 BackendDB()->Put(
517 key, static_cast<WebIDBPutMode>(put_mode), 506 transaction_->Id(), Id(), WebData(value_wrapper.ExtractWireBytes()),
518 request->CreateWebCallbacks().release(), index_ids, 507 value_wrapper.WrappedBlobInfo(), key,
519 index_keys); 508 static_cast<WebIDBPutMode>(put_mode),
509 request->CreateWebCallbacks().release(), index_ids, index_keys);
510
520 return request; 511 return request;
521 } 512 }
522 513
523 IDBRequest* IDBObjectStore::deleteFunction(ScriptState* script_state, 514 IDBRequest* IDBObjectStore::deleteFunction(ScriptState* script_state,
524 const ScriptValue& key, 515 const ScriptValue& key,
525 ExceptionState& exception_state) { 516 ExceptionState& exception_state) {
526 IDB_TRACE("IDBObjectStore::delete"); 517 IDB_TRACE("IDBObjectStore::delete");
527 if (IsDeleted()) { 518 if (IsDeleted()) {
528 exception_state.ThrowDOMException( 519 exception_state.ThrowDOMException(
529 kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage); 520 kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1059 } 1050 }
1060 } 1051 }
1061 return IDBIndexMetadata::kInvalidId; 1052 return IDBIndexMetadata::kInvalidId;
1062 } 1053 }
1063 1054
1064 WebIDBDatabase* IDBObjectStore::BackendDB() const { 1055 WebIDBDatabase* IDBObjectStore::BackendDB() const {
1065 return transaction_->BackendDB(); 1056 return transaction_->BackendDB();
1066 } 1057 }
1067 1058
1068 } // namespace blink 1059 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698