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

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: Created 3 years, 8 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 23 matching lines...) Expand all
34 #include "bindings/modules/v8/ToV8ForModules.h" 34 #include "bindings/modules/v8/ToV8ForModules.h"
35 #include "bindings/modules/v8/V8BindingForModules.h" 35 #include "bindings/modules/v8/V8BindingForModules.h"
36 #include "core/dom/DOMStringList.h" 36 #include "core/dom/DOMStringList.h"
37 #include "core/dom/ExceptionCode.h" 37 #include "core/dom/ExceptionCode.h"
38 #include "core/dom/ExecutionContext.h" 38 #include "core/dom/ExecutionContext.h"
39 #include "modules/indexeddb/IDBAny.h" 39 #include "modules/indexeddb/IDBAny.h"
40 #include "modules/indexeddb/IDBCursorWithValue.h" 40 #include "modules/indexeddb/IDBCursorWithValue.h"
41 #include "modules/indexeddb/IDBDatabase.h" 41 #include "modules/indexeddb/IDBDatabase.h"
42 #include "modules/indexeddb/IDBKeyPath.h" 42 #include "modules/indexeddb/IDBKeyPath.h"
43 #include "modules/indexeddb/IDBTracing.h" 43 #include "modules/indexeddb/IDBTracing.h"
44 #include "modules/indexeddb/IDBValueWrapper.h"
44 #include "platform/Histogram.h" 45 #include "platform/Histogram.h"
45 #include "platform/SharedBuffer.h" 46 #include "platform/SharedBuffer.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 355 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 return nullptr; 413 return nullptr;
412 } 414 }
413 if (transaction_->IsReadOnly()) { 415 if (transaction_->IsReadOnly()) {
414 exception_state.ThrowDOMException( 416 exception_state.ThrowDOMException(
415 kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage); 417 kReadOnlyError, IDBDatabase::kTransactionReadOnlyErrorMessage);
416 return nullptr; 418 return nullptr;
417 } 419 }
418 420
419 v8::Isolate* isolate = script_state->GetIsolate(); 421 v8::Isolate* isolate = script_state->GetIsolate();
420 DCHECK(isolate->InContext()); 422 DCHECK(isolate->InContext());
421 Vector<WebBlobInfo> blob_info; 423 bool write_wasm_to_stream =
422 SerializedScriptValue::SerializeOptions options;
423 options.blob_info = &blob_info;
424 options.write_wasm_to_stream =
425 ExecutionContext::From(script_state)->IsSecureContext(); 424 ExecutionContext::From(script_state)->IsSecureContext();
426 RefPtr<SerializedScriptValue> serialized_value = 425 IDBValueWrapper value_wrapper(isolate, value.V8Value(), write_wasm_to_stream,
427 SerializedScriptValue::Serialize(isolate, value.V8Value(), options, 426 exception_state);
428 exception_state);
429 if (exception_state.HadException()) 427 if (exception_state.HadException())
430 return nullptr; 428 return nullptr;
431 429
432 // Keys that need to be extracted must be taken from a clone so that 430 // Keys that need to be extracted must be taken from a clone so that
433 // side effects (i.e. getters) are not triggered. Construct the 431 // side effects (i.e. getters) are not triggered. Construct the
434 // clone lazily since the operation may be expensive. 432 // clone lazily since the operation may be expensive.
435 ScriptValue clone; 433 ScriptValue clone;
436 434
437 const IDBKeyPath& key_path = IdbKeyPath(); 435 const IDBKeyPath& key_path = IdbKeyPath();
438 const bool uses_in_line_keys = !key_path.IsNull(); 436 const bool uses_in_line_keys = !key_path.IsNull();
439 const bool has_key_generator = autoIncrement(); 437 const bool has_key_generator = autoIncrement();
440 438
441 if (put_mode != kWebIDBPutModeCursorUpdate && uses_in_line_keys && key) { 439 if (put_mode != kWebIDBPutModeCursorUpdate && uses_in_line_keys && key) {
442 exception_state.ThrowDOMException(kDataError, 440 exception_state.ThrowDOMException(kDataError,
443 "The object store uses in-line keys and " 441 "The object store uses in-line keys and "
444 "the key parameter was provided."); 442 "the key parameter was provided.");
445 return nullptr; 443 return nullptr;
446 } 444 }
447 445
448 // This test logically belongs in IDBCursor, but must operate on the cloned 446 // This test logically belongs in IDBCursor, but must operate on the cloned
449 // value. 447 // value.
450 if (put_mode == kWebIDBPutModeCursorUpdate && uses_in_line_keys) { 448 if (put_mode == kWebIDBPutModeCursorUpdate && uses_in_line_keys) {
451 DCHECK(key); 449 DCHECK(key);
452 if (clone.IsEmpty()) 450 DCHECK(clone.IsEmpty());
453 clone = DeserializeScriptValue(script_state, serialized_value.Get(), 451 value_wrapper.Clone(script_state, &clone);
454 &blob_info);
455 IDBKey* key_path_key = ScriptValue::To<IDBKey*>( 452 IDBKey* key_path_key = ScriptValue::To<IDBKey*>(
456 script_state->GetIsolate(), clone, exception_state, key_path); 453 script_state->GetIsolate(), clone, exception_state, key_path);
457 if (exception_state.HadException()) 454 if (exception_state.HadException())
458 return nullptr; 455 return nullptr;
459 if (!key_path_key || !key_path_key->IsEqual(key)) { 456 if (!key_path_key || !key_path_key->IsEqual(key)) {
460 exception_state.ThrowDOMException( 457 exception_state.ThrowDOMException(
461 kDataError, 458 kDataError,
462 "The effective object store of this cursor uses in-line keys and " 459 "The effective object store of this cursor uses in-line keys and "
463 "evaluating the key path of the value parameter results in a " 460 "evaluating the key path of the value parameter results in a "
464 "different value than the cursor's effective key."); 461 "different value than the cursor's effective key.");
465 return nullptr; 462 return nullptr;
466 } 463 }
467 } 464 }
468 465
469 if (!uses_in_line_keys && !has_key_generator && !key) { 466 if (!uses_in_line_keys && !has_key_generator && !key) {
470 exception_state.ThrowDOMException(kDataError, 467 exception_state.ThrowDOMException(kDataError,
471 "The object store uses out-of-line keys " 468 "The object store uses out-of-line keys "
472 "and has no key generator and the key " 469 "and has no key generator and the key "
473 "parameter was not provided."); 470 "parameter was not provided.");
474 return nullptr; 471 return nullptr;
475 } 472 }
476 if (uses_in_line_keys) { 473 if (uses_in_line_keys) {
477 if (clone.IsEmpty()) { 474 if (clone.IsEmpty())
478 clone = DeserializeScriptValue(script_state, serialized_value.Get(), 475 value_wrapper.Clone(script_state, &clone);
479 &blob_info);
480 }
481 IDBKey* key_path_key = ScriptValue::To<IDBKey*>( 476 IDBKey* key_path_key = ScriptValue::To<IDBKey*>(
482 script_state->GetIsolate(), clone, exception_state, key_path); 477 script_state->GetIsolate(), clone, exception_state, key_path);
483 if (exception_state.HadException()) 478 if (exception_state.HadException())
484 return nullptr; 479 return nullptr;
485 if (key_path_key && !key_path_key->IsValid()) { 480 if (key_path_key && !key_path_key->IsValid()) {
486 exception_state.ThrowDOMException( 481 exception_state.ThrowDOMException(
487 kDataError, 482 kDataError,
488 "Evaluating the object store's key path " 483 "Evaluating the object store's key path "
489 "yielded a value that is not a valid " 484 "yielded a value that is not a valid "
490 "key."); 485 "key.");
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 DEFINE_THREAD_SAFE_STATIC_LOCAL( 519 DEFINE_THREAD_SAFE_STATIC_LOCAL(
525 EnumerationHistogram, key_type_histogram, 520 EnumerationHistogram, key_type_histogram,
526 new EnumerationHistogram("WebCore.IndexedDB.ObjectStore.Record.KeyType", 521 new EnumerationHistogram("WebCore.IndexedDB.ObjectStore.Record.KeyType",
527 static_cast<int>(IDBKey::kTypeEnumMax))); 522 static_cast<int>(IDBKey::kTypeEnumMax)));
528 key_type_histogram.Count(static_cast<int>(key->GetType())); 523 key_type_histogram.Count(static_cast<int>(key->GetType()));
529 } 524 }
530 525
531 Vector<int64_t> index_ids; 526 Vector<int64_t> index_ids;
532 HeapVector<IndexKeys> index_keys; 527 HeapVector<IndexKeys> index_keys;
533 for (const auto& it : Metadata().indexes) { 528 for (const auto& it : Metadata().indexes) {
534 if (clone.IsEmpty()) { 529 if (clone.IsEmpty())
535 clone = DeserializeScriptValue(script_state, serialized_value.Get(), 530 value_wrapper.Clone(script_state, &clone);
536 &blob_info);
537 }
538 IndexKeys keys; 531 IndexKeys keys;
539 GenerateIndexKeysForValue(script_state->GetIsolate(), *it.value, clone, 532 GenerateIndexKeysForValue(script_state->GetIsolate(), *it.value, clone,
540 &keys); 533 &keys);
541 index_ids.push_back(it.key); 534 index_ids.push_back(it.key);
542 index_keys.push_back(keys); 535 index_keys.push_back(keys);
543 } 536 }
544 537
545 IDBRequest* request = 538 IDBRequest* request =
546 IDBRequest::Create(script_state, source, transaction_.Get()); 539 IDBRequest::Create(script_state, source, transaction_.Get());
547 Vector<char> wire_bytes;
548 serialized_value->ToWireBytes(wire_bytes);
549 RefPtr<SharedBuffer> value_buffer = SharedBuffer::AdoptVector(wire_bytes);
550 540
551 BackendDB()->Put(transaction_->Id(), Id(), WebData(value_buffer), blob_info, 541 value_wrapper.WrapIfBiggerThan(IDBValueWrapper::kWrapThreshold);
552 key, static_cast<WebIDBPutMode>(put_mode), 542
553 request->CreateWebCallbacks().release(), index_ids, 543 BackendDB()->Put(
554 index_keys); 544 transaction_->Id(), Id(), WebData(value_wrapper.ExtractWireBytes()),
545 value_wrapper.WrappedBlobInfo(), key,
546 static_cast<WebIDBPutMode>(put_mode),
547 request->CreateWebCallbacks().release(), index_ids, index_keys);
555 return request; 548 return request;
556 } 549 }
557 550
558 IDBRequest* IDBObjectStore::deleteFunction(ScriptState* script_state, 551 IDBRequest* IDBObjectStore::deleteFunction(ScriptState* script_state,
559 const ScriptValue& key, 552 const ScriptValue& key,
560 ExceptionState& exception_state) { 553 ExceptionState& exception_state) {
561 IDB_TRACE("IDBObjectStore::delete"); 554 IDB_TRACE("IDBObjectStore::delete");
562 if (IsDeleted()) { 555 if (IsDeleted()) {
563 exception_state.ThrowDOMException( 556 exception_state.ThrowDOMException(
564 kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage); 557 kInvalidStateError, IDBDatabase::kObjectStoreDeletedErrorMessage);
(...skipping 578 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 } 1136 }
1144 } 1137 }
1145 return IDBIndexMetadata::kInvalidId; 1138 return IDBIndexMetadata::kInvalidId;
1146 } 1139 }
1147 1140
1148 WebIDBDatabase* IDBObjectStore::BackendDB() const { 1141 WebIDBDatabase* IDBObjectStore::BackendDB() const {
1149 return transaction_->BackendDB(); 1142 return transaction_->BackendDB();
1150 } 1143 }
1151 1144
1152 } // namespace blink 1145 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698