Changeset 280410 in webkit


Ignore:
Timestamp:
Jul 28, 2021 4:35:42 PM (12 months ago)
Author:
sihui_liu@apple.com
Message:

IDBFactory.databases should not return databases with invalid version
https://bugs.webkit.org/show_bug.cgi?id=228554

Reviewed by Chris Dumez.

LayoutTests/imported/w3c:

  • web-platform-tests/IndexedDB/get-databases.any-expected.txt:
  • web-platform-tests/IndexedDB/get-databases.any.worker-expected.txt:

Source/WebCore:

To get database information, we used to open all database files and read from them. To avoid opening new
connection to databases that are already opened, and to ensure we get the latest information, for database that
is already opened, we should get its information from UniqueIDBDatabase directly. If database is not opened, we
open its file and read. By doing this, we also fix the issue that no databases are returned in private browsing
(since there is no file created).

Also, version 0 means the database is just created and has not finished version change transaction (version 1
is the first valid version according to spec), so we should not return databases with version 0.

Tests: storage/indexeddb/getdatabases-private.html

storage/indexeddb/getdatabases.html

  • Modules/indexeddb/server/IDBBackingStore.h:
  • Modules/indexeddb/server/IDBServer.cpp:

(WebCore::IDBServer::getDatabaseNameAndVersionFromOriginDirectory):
(WebCore::IDBServer::IDBServer::getAllDatabaseNamesAndVersions):

  • Modules/indexeddb/server/MemoryIDBBackingStore.h:
  • Modules/indexeddb/server/SQLiteIDBBackingStore.h:
  • Modules/indexeddb/server/UniqueIDBDatabase.cpp:

(WebCore::IDBServer::UniqueIDBDatabase::didDeleteBackingStore):
(WebCore::IDBServer::UniqueIDBDatabase::filePath const):
(WebCore::IDBServer::UniqueIDBDatabase::nameAndVersion const):

  • Modules/indexeddb/server/UniqueIDBDatabase.h:

LayoutTests:

  • storage/indexeddb/getdatabases-expected.txt: Added.
  • storage/indexeddb/getdatabases-private-expected.txt: Added.
  • storage/indexeddb/getdatabases-private.html: Added.
  • storage/indexeddb/getdatabases.html: Added.
  • storage/indexeddb/resources/getdatabases.js: Added.

(test):

Location:
trunk
Files:
5 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r280409 r280410  
     12021-07-28  Sihui Liu  <sihui_liu@apple.com>
     2
     3        IDBFactory.databases should not return databases with invalid version
     4        https://bugs.webkit.org/show_bug.cgi?id=228554
     5
     6        Reviewed by Chris Dumez.
     7
     8        * storage/indexeddb/getdatabases-expected.txt: Added.
     9        * storage/indexeddb/getdatabases-private-expected.txt: Added.
     10        * storage/indexeddb/getdatabases-private.html: Added.
     11        * storage/indexeddb/getdatabases.html: Added.
     12        * storage/indexeddb/resources/getdatabases.js: Added.
     13        (test):
     14
    1152021-07-28  Ayumi Kojima  <ayumi_kojima@apple.com>
    216
  • trunk/LayoutTests/imported/w3c/ChangeLog

    r280404 r280410  
     12021-07-28  Sihui Liu  <sihui_liu@apple.com>
     2
     3        IDBFactory.databases should not return databases with invalid version
     4        https://bugs.webkit.org/show_bug.cgi?id=228554
     5
     6        Reviewed by Chris Dumez.
     7
     8        * web-platform-tests/IndexedDB/get-databases.any-expected.txt:
     9        * web-platform-tests/IndexedDB/get-databases.any.worker-expected.txt:
     10
    1112021-07-28  Ayumi Kojima  <ayumi_kojima@apple.com>
    212
  • trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/get-databases.any-expected.txt

    r267651 r280410  
    44PASS Enumerate multiple databases.
    55PASS Make sure an empty list is returned for the case of no databases.
    6 FAIL Ensure that databases() doesn't pick up changes that haven't commited. assert_equals: The result of databases() should be only those databases which have been created at the time of calling, regardless of versionchange transactions currently running. expected 1 but got 2
     6PASS Ensure that databases() doesn't pick up changes that haven't commited.
    77
  • trunk/LayoutTests/imported/w3c/web-platform-tests/IndexedDB/get-databases.any.worker-expected.txt

    r267651 r280410  
    44PASS Enumerate multiple databases.
    55PASS Make sure an empty list is returned for the case of no databases.
    6 FAIL Ensure that databases() doesn't pick up changes that haven't commited. assert_equals: The result of databases() should be only those databases which have been created at the time of calling, regardless of versionchange transactions currently running. expected 1 but got 2
     6PASS Ensure that databases() doesn't pick up changes that haven't commited.
    77
  • trunk/Source/WebCore/ChangeLog

    r280401 r280410  
     12021-07-28  Sihui Liu  <sihui_liu@apple.com>
     2
     3        IDBFactory.databases should not return databases with invalid version
     4        https://bugs.webkit.org/show_bug.cgi?id=228554
     5
     6        Reviewed by Chris Dumez.
     7
     8        To get database information, we used to open all database files and read from them. To avoid opening new
     9        connection to databases that are already opened, and to ensure we get the latest information, for database that
     10        is already opened, we should get its information from UniqueIDBDatabase directly. If database is not opened, we
     11        open its file and read. By doing this, we also fix the issue that no databases are returned in private browsing
     12        (since there is no file created).
     13
     14        Also, version 0 means the database is just created and has not finished version change transaction (version 1
     15        is the first valid version according to spec), so we should not return databases with version 0.
     16
     17        Tests: storage/indexeddb/getdatabases-private.html
     18               storage/indexeddb/getdatabases.html
     19
     20        * Modules/indexeddb/server/IDBBackingStore.h:
     21        * Modules/indexeddb/server/IDBServer.cpp:
     22        (WebCore::IDBServer::getDatabaseNameAndVersionFromOriginDirectory):
     23        (WebCore::IDBServer::IDBServer::getAllDatabaseNamesAndVersions):
     24        * Modules/indexeddb/server/MemoryIDBBackingStore.h:
     25        * Modules/indexeddb/server/SQLiteIDBBackingStore.h:
     26        * Modules/indexeddb/server/UniqueIDBDatabase.cpp:
     27        (WebCore::IDBServer::UniqueIDBDatabase::didDeleteBackingStore):
     28        (WebCore::IDBServer::UniqueIDBDatabase::filePath const):
     29        (WebCore::IDBServer::UniqueIDBDatabase::nameAndVersion const):
     30        * Modules/indexeddb/server/UniqueIDBDatabase.h:
     31
    1322021-07-28  Myles C. Maxfield  <mmaxfield@apple.com>
    233
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBBackingStore.h

    r278393 r280410  
    9292    virtual bool supportsSimultaneousTransactions() = 0;
    9393    virtual bool isEphemeral() = 0;
     94    virtual String fullDatabasePath() const = 0;
    9495
    9596    virtual void close() = 0;
  • trunk/Source/WebCore/Modules/indexeddb/server/IDBServer.cpp

    r280053 r280410  
    509509}
    510510
     511static void getDatabaseNameAndVersionFromOriginDirectory(const String& directory, HashSet<String>& excludedDatabasePaths, Vector<IDBDatabaseNameAndVersion>& result)
     512{
     513    Vector<String> databaseDirectoryNames = FileSystem::listDirectory(directory);
     514    for (auto& databaseDirectoryName : databaseDirectoryNames) {
     515        auto fullDatabasePath = SQLiteIDBBackingStore::fullDatabasePathForDirectory(FileSystem::pathByAppendingComponent(directory, databaseDirectoryName));
     516        if (excludedDatabasePaths.contains(fullDatabasePath))
     517            continue;
     518
     519        if (auto nameAndVersion = SQLiteIDBBackingStore::databaseNameAndVersionFromFile(fullDatabasePath))
     520            result.append(WTFMove(*nameAndVersion));
     521    }
     522}
     523
    511524void IDBServer::getAllDatabaseNamesAndVersions(IDBConnectionIdentifier serverConnectionIdentifier, const IDBResourceIdentifier& requestIdentifier, const ClientOrigin& origin)
    512525{
     
    514527    ASSERT(m_lock.isHeld());
    515528
     529    Vector<IDBDatabaseNameAndVersion> result;
     530    HashSet<String> visitedDatabasePaths;
     531
     532    for (auto& database : m_uniqueIDBDatabaseMap.values()) {
     533        auto path = database->filePath();
     534        if (!path.isEmpty())
     535            visitedDatabasePaths.add(path);
     536
     537        if (auto nameAndVersion = database->nameAndVersion())
     538            result.append(WTFMove(*nameAndVersion));
     539    }
     540
    516541    String oldDirectory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, m_databaseDirectoryPath, "v0");
    517     Vector<String> fileNames = FileSystem::listDirectory(oldDirectory);
    518     Vector<IDBDatabaseNameAndVersion> databases;
    519     for (auto& fileName : fileNames) {
    520         auto databaseTuple = SQLiteIDBBackingStore::databaseNameAndVersionFromFile(SQLiteIDBBackingStore::fullDatabasePathForDirectory(FileSystem::pathByAppendingComponent(oldDirectory, fileName)));
    521         if (databaseTuple)
    522             databases.append(WTFMove(*databaseTuple));
    523     }
     542    getDatabaseNameAndVersionFromOriginDirectory(oldDirectory, visitedDatabasePaths, result);
    524543
    525544    String directory = IDBDatabaseIdentifier::databaseDirectoryRelativeToRoot(origin.topOrigin, origin.clientOrigin, m_databaseDirectoryPath, "v1");
    526     fileNames = FileSystem::listDirectory(directory);
    527     for (auto& fileName : fileNames) {
    528         auto databaseTuple = SQLiteIDBBackingStore::databaseNameAndVersionFromFile(SQLiteIDBBackingStore::fullDatabasePathForDirectory(FileSystem::pathByAppendingComponent(directory, fileName)));
    529         if (databaseTuple)
    530             databases.append(WTFMove(*databaseTuple));
    531     }
     545    getDatabaseNameAndVersionFromOriginDirectory(directory, visitedDatabasePaths, result);
    532546
    533547    auto connection = m_connectionMap.get(serverConnectionIdentifier);
     
    535549        return;
    536550
    537     connection->didGetAllDatabaseNamesAndVersions(requestIdentifier, WTFMove(databases));
     551    connection->didGetAllDatabaseNamesAndVersions(requestIdentifier, WTFMove(result));
    538552}
    539553
  • trunk/Source/WebCore/Modules/indexeddb/server/MemoryIDBBackingStore.h

    r279956 r280410  
    8181    bool supportsSimultaneousTransactions() final { return true; }
    8282    bool isEphemeral() final { return true; }
     83    String fullDatabasePath() const final { return nullString(); }
    8384
    8485    bool hasTransaction(const IDBResourceIdentifier& identifier) const final { return m_transactions.contains(identifier); }
  • trunk/Source/WebCore/Modules/indexeddb/server/SQLiteIDBBackingStore.h

    r278393 r280410  
    8787    bool supportsSimultaneousTransactions() final { return false; }
    8888    bool isEphemeral() final { return false; }
     89    String fullDatabasePath() const final;
    8990
    9091    bool hasTransaction(const IDBResourceIdentifier&) const final;
     
    104105private:
    105106    String filenameForDatabaseName() const;
    106     String fullDatabasePath() const;
    107107    String fullDatabaseDirectoryWithUpgrade();
    108108
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.cpp

    r280176 r280410  
    313313
    314314    if (m_databaseInfo)
    315         m_mostRecentDeletedDatabaseInfo = WTFMove(m_databaseInfo);
     315        m_mostRecentDeletedDatabaseInfo = std::exchange(m_databaseInfo, nullptr);
    316316
    317317    // If this UniqueIDBDatabase was brought into existence for the purpose of deleting the file on disk,
     
    12411241}
    12421242
     1243String UniqueIDBDatabase::filePath() const
     1244{
     1245    return m_backingStore ? m_backingStore->fullDatabasePath() : nullString();
     1246}
     1247
     1248std::optional<IDBDatabaseNameAndVersion> UniqueIDBDatabase::nameAndVersion() const
     1249{
     1250    if (!m_backingStore)
     1251        return std::nullopt;
     1252
     1253    if (m_versionChangeTransaction) {
     1254        if (auto databaseInfo = m_versionChangeTransaction->originalDatabaseInfo()) {
     1255            // The database is newly created.
     1256            if (!databaseInfo->version())
     1257                return std::nullopt;
     1258
     1259            return IDBDatabaseNameAndVersion { databaseInfo->name(), databaseInfo->version() };
     1260        }
     1261
     1262        return std::nullopt;
     1263    }
     1264
     1265    return IDBDatabaseNameAndVersion { m_databaseInfo->name(), m_databaseInfo->version() };
     1266}
     1267
    12431268} // namespace IDBServer
    12441269} // namespace WebCore
  • trunk/Source/WebCore/Modules/indexeddb/server/UniqueIDBDatabase.h

    r279966 r280410  
    2929#include "IDBDatabaseIdentifier.h"
    3030#include "IDBDatabaseInfo.h"
     31#include "IDBDatabaseNameAndVersion.h"
    3132#include "IDBGetResult.h"
    3233#include "ServerOpenDBRequest.h"
     
    112113    bool tryClose();
    113114
     115    String filePath() const;
     116    std::optional<IDBDatabaseNameAndVersion> nameAndVersion() const;
     117
    114118private:
    115119    void handleDatabaseOperations();
Note: See TracChangeset for help on using the changeset viewer.