• Chase Phillips's avatar
    IndexedDB: Change Mojo IDBValue.bits type from string to array<uint8> · 48bcb8e3
    Chase Phillips authored
    TL;DR IDBValue.bits was type string which worked until we added a
    Mojo Blink variant that introduced a new conversion requirement.
    IDBValue.bits is actually a sequence of octets, so use array<uint8>,
    instead.
    
    More details:
    
    Chrome's IndexedDB implementation uses a Mojo definition that
    specifies the IDBValue struct contains a field |bits|.  The field is
    used to represent the data that's written to and read off of disk by
    IndexedDB's LevelDB instance.
    
    Previously, the |bits| field was of type string and there were only
    content variants of the Mojo C++ bindings for IndexedDB.  This led to
    the field only ever being translated to/from std::string.
    std::string can contain these raw byte sequences since there are no
    constraints placed on the string holding data following any
    particular format or validation.
    
    As part of bug 717812 and https://crrev.com/1265900, a new Blink
    variant for the IndexedDB Mojo interfaces was added.  The Blink
    variant relies on WTF::String instead of std::string, and so the
    IDBValue.bits field was translated for that variant to/from
    WTF::String.
    
    Mojo's WTF::String traits uses WTF::String::FromUTF8().  As part of
    FromUTF8()'s implementation, if the given set of characters contains
    invalid UTF-8 data, FromUTF8() will return a null String instance.
    The IDBValue.bits field is not restricted just to UTF-8 characters,
    and so it always ended up being set to the null String in the traits.
    
    The net result of this bug was that our carriage format changed:
    
    - Chrome with https://crrev.com/1265900 could not read Chrome
      stable's IDB instances
    
    - Chrome without https://crrev.com/1265900 could not read Chrome with
      http://crrev.com/1265900's IDB instances
    
    More about the impact of that bug can be read at
    https://crbug.com/899446.
    
    We must observe FromUTF8()'s requirement that we pass only UTF-8
    valid data in string types.  We also need to observe that we are in
    fact passing raw byte data in the IDBValue.bits field instead of what
    both variants would consider as valid strings.
    
    The fix is to change IDBValue.bits from a string type to a type of
    array<uint8>.  LevelDB's API requires strings, so in content to/from
    the LevelDB instance we must pass in and receive strings.  In Blink,
    the data is represented as a WebData instance, which also takes raw
    character data.  To support both sides, I've added in-place
    conversions to/from std::string and to/from WebData.
    
    Bug: 717812
    Change-Id: Iadfbd21be52fc50abc60a2695b95691bc07028e4
    Reviewed-on: https://chromium-review.googlesource.com/c/1316444
    Commit-Queue: Chase Phillips <cmp@chromium.org>
    Reviewed-by: default avatarVictor Costan <pwnall@chromium.org>
    Reviewed-by: default avatarKentaro Hara <haraken@chromium.org>
    Reviewed-by: default avatarDaniel Murphy <dmurph@chromium.org>
    Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
    Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
    Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
    Cr-Commit-Position: refs/heads/master@{#605918}
    48bcb8e3
indexed_db_callbacks_impl.cc 9.65 KB