// Copyright 2017 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_VALUE_WRAPPING_H_ #define THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_VALUE_WRAPPING_H_ #include <memory> #include <utility> #include "base/dcheck_is_on.h" #include "base/feature_list.h" #include "base/memory/scoped_refptr.h" #include "third_party/blink/public/platform/web_blob_info.h" #include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.h" #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" #include "third_party/blink/renderer/platform/wtf/text/string_view.h" #include "third_party/blink/renderer/platform/wtf/vector.h" #include "v8/include/v8.h" namespace blink { class BlobDataHandle; class ExceptionState; class IDBValue; class ScriptState; class ScriptValue; class SerializedScriptValue; // Logic for serializing V8 values for storage in IndexedDB. // // An IDBValueWrapper instance drives the serialization of a single V8 value to // IndexedDB. An instance's lifecycle goes through the following stages: // 1) Cloning - Right after an instance is constructed, its internal // representation is optimized for structured cloning via the Clone() method. // This may be necessary when extracting the primary key and/or index keys // for the serialized value. // 2) Wrapping - DoneCloning() transitions the instance to an internal // representation optimized IPC and disk storage. See below for details. // 3) Reading results - After any desired wrapping is performed, the Take*() // methods yield the serialized value components passed to the backing store. // To avoid unnecessary copies, the Take*() methods move out parts of the // internal representation, so each Take*() method can be called at most // once. // // Example usage: // auto wrapper = new IDBValueWrapper(); // wrapper.Clone(...); // Structured clone used to extract keys. // wrapper.DoneCloning(); // wrapper.TakeWireBytes(); // wrapper.TakeBlobDataHandles(); // wrapper.TakeBlobInfo(); // // V8 values are first serialized via SerializedScriptValue (SSV), which is // essentially a byte array plus an array of attached Blobs. The SSV output's // byte array is then further compressed via Snappy. If the compressed array is // not too large, it will be stored directly in IndexedDB's backing store, // together with references to the attached Blobs. // // Values that are still "large" after compression are converted into a Blob // (additional to those already attached). Specifically, the byte array in the // SSV output is replaced with a "wrapped value" marker, and stored inside a // Blob that is tacked to the end of the SSV's Blob array. IndexedDB's backing // store receives the "wrapped value" marker and the references to the Blobs, // while the large byte array in the SSV output is handled by the Blob storage // system. // // In summary: // "normal" v8::Value -> SSV + Snappy -> IDBValue (stores SSV output) -> LevelDB // "large" v8::Value -> SSV + Snappy -> IDBValue (stores SSV output) -> // Blob (stores SSV output) + IDBValue (stores Blob reference) -> LevelDB // // Full picture that accounts for Blob attachments: // "normal" v8::Value -> SSV (byte array, Blob attachments) -> Snappy -> // IDBValue (bytes: compressed SSV byte array, blobs: SSV Blob attachments) // -> LevelDB // "large" v8::Value -> SSV (byte array, Blob attachments) -> Snappy -> // IDBValue (bytes: "wrapped value" marker, // blobs: SSV Blob attachments + // [wrapper Blob(compressed SSV byte array)] -> // LevelDB class MODULES_EXPORT IDBValueWrapper { … }; // State and logic for unwrapping large IndexedDB values from Blobs. // // See IDBValueWrapper for an explanation of the wrapping concept. // // Once created, an IDBValueUnwrapper instance can be used to unwrap multiple // Blobs. For each Blob to be unwrapped, the caller should first call Parse(). // If the method succeeds, the IDBValueUnwrapper will store the parse state, // which can be obtained using WrapperBlobSize() and WrapperBlobHandle(). class MODULES_EXPORT IDBValueUnwrapper { … }; } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_INDEXEDDB_IDB_VALUE_WRAPPING_H_