blob: a3c8f430c9b22051c7d3b1a2b5db832827c9ee58 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATABASE_H_
#define CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATABASE_H_
#include <stddef.h>
#include <stdint.h>
#include <list>
#include <map>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <vector>
#include "base/containers/queue.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "content/browser/indexed_db/indexed_db.h"
#include "content/browser/indexed_db/indexed_db_backing_store.h"
#include "content/browser/indexed_db/indexed_db_callbacks.h"
#include "content/browser/indexed_db/indexed_db_observer.h"
#include "content/browser/indexed_db/indexed_db_pending_connection.h"
#include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
#include "content/browser/indexed_db/list_set.h"
#include "content/common/content_export.h"
#include "content/common/indexed_db/indexed_db_metadata.h"
#include "third_party/blink/public/platform/modules/indexeddb/web_idb_types.h"
namespace url {
class Origin;
}
namespace content {
class IndexedDBConnection;
class IndexedDBDatabaseCallbacks;
class IndexedDBFactory;
class IndexedDBKey;
class IndexedDBKeyPath;
class IndexedDBKeyRange;
class IndexedDBMetadataCoding;
class IndexedDBTransaction;
struct IndexedDBValue;
class CONTENT_EXPORT IndexedDBDatabase
: public base::RefCounted<IndexedDBDatabase> {
public:
// Identifier is pair of (origin, database name).
using Identifier = std::pair<url::Origin, base::string16>;
static const int64_t kInvalidId = 0;
static const int64_t kMinimumIndexId = 30;
static std::tuple<scoped_refptr<IndexedDBDatabase>, leveldb::Status> Create(
const base::string16& name,
scoped_refptr<IndexedDBBackingStore> backing_store,
scoped_refptr<IndexedDBFactory> factory,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const Identifier& unique_identifier);
const Identifier& identifier() const { return identifier_; }
IndexedDBBackingStore* backing_store() { return backing_store_.get(); }
int64_t id() const { return metadata_.id; }
const base::string16& name() const { return metadata_.name; }
const url::Origin& origin() const { return identifier_.first; }
void AddObjectStore(IndexedDBObjectStoreMetadata metadata,
int64_t new_max_object_store_id);
IndexedDBObjectStoreMetadata RemoveObjectStore(int64_t object_store_id);
void AddIndex(int64_t object_store_id,
IndexedDBIndexMetadata metadata,
int64_t new_max_index_id);
IndexedDBIndexMetadata RemoveIndex(int64_t object_store_id, int64_t index_id);
void OpenConnection(std::unique_ptr<IndexedDBPendingConnection> connection);
void DeleteDatabase(scoped_refptr<IndexedDBCallbacks> callbacks,
bool force_close);
const IndexedDBDatabaseMetadata& metadata() const { return metadata_; }
void CreateObjectStore(IndexedDBTransaction* transaction,
int64_t object_store_id,
const base::string16& name,
const IndexedDBKeyPath& key_path,
bool auto_increment);
void DeleteObjectStore(IndexedDBTransaction* transaction,
int64_t object_store_id);
void RenameObjectStore(IndexedDBTransaction* transaction,
int64_t object_store_id,
const base::string16& new_name);
// Returns a pointer to a newly created transaction. The object is owned
// by |transaction_coordinator_|.
IndexedDBTransaction* CreateTransaction(
int64_t transaction_id,
IndexedDBConnection* connection,
const std::vector<int64_t>& object_store_ids,
blink::WebIDBTransactionMode mode);
void Close(IndexedDBConnection* connection, bool forced);
void ForceClose();
// Ack that one of the connections notified with a "versionchange" event did
// not promptly close. Therefore a "blocked" event should be fired at the
// pending connection.
void VersionChangeIgnored();
void Commit(IndexedDBTransaction* transaction);
void CreateIndex(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
const base::string16& name,
const IndexedDBKeyPath& key_path,
bool unique,
bool multi_entry);
void DeleteIndex(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id);
void RenameIndex(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
const base::string16& new_name);
IndexedDBTransactionCoordinator& transaction_coordinator() {
return transaction_coordinator_;
}
const IndexedDBTransactionCoordinator& transaction_coordinator() const {
return transaction_coordinator_;
}
void TransactionCreated(IndexedDBTransaction* transaction);
void TransactionFinished(IndexedDBTransaction* transaction, bool committed);
void AbortAllTransactionsForConnections();
void AddPendingObserver(IndexedDBTransaction* transaction,
int32_t observer_id,
const IndexedDBObserver::Options& options);
// |value| can be null for delete and clear operations.
void FilterObservation(IndexedDBTransaction*,
int64_t object_store_id,
blink::WebIDBOperationType type,
const IndexedDBKeyRange& key_range,
const IndexedDBValue* value);
void SendObservations(
std::map<int32_t, ::indexed_db::mojom::ObserverChangesPtr> change_map);
void Get(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
bool key_only,
scoped_refptr<IndexedDBCallbacks> callbacks);
void GetAll(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
bool key_only,
int64_t max_count,
scoped_refptr<IndexedDBCallbacks> callbacks);
void Put(IndexedDBTransaction* transaction,
int64_t object_store_id,
IndexedDBValue* value,
std::unique_ptr<IndexedDBKey> key,
blink::WebIDBPutMode mode,
scoped_refptr<IndexedDBCallbacks> callbacks,
const std::vector<IndexedDBIndexKeys>& index_keys);
void SetIndexKeys(IndexedDBTransaction* transaction,
int64_t object_store_id,
std::unique_ptr<IndexedDBKey> primary_key,
const std::vector<IndexedDBIndexKeys>& index_keys);
void SetIndexesReady(IndexedDBTransaction* transaction,
int64_t object_store_id,
const std::vector<int64_t>& index_ids);
void OpenCursor(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
blink::WebIDBCursorDirection,
bool key_only,
blink::WebIDBTaskType task_type,
scoped_refptr<IndexedDBCallbacks> callbacks);
void Count(IndexedDBTransaction* transaction,
int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks);
void DeleteRange(IndexedDBTransaction* transaction,
int64_t object_store_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks);
void Clear(IndexedDBTransaction* transaction,
int64_t object_store_id,
scoped_refptr<IndexedDBCallbacks> callbacks);
// Number of connections that have progressed passed initial open call.
size_t ConnectionCount() const { return connections_.size(); }
// Number of active open/delete calls (running or blocked on other
// connections).
size_t ActiveOpenDeleteCount() const { return active_request_ ? 1 : 0; }
// Number of open/delete calls that are waiting their turn.
size_t PendingOpenDeleteCount() const { return pending_requests_.size(); }
// Asynchronous tasks scheduled within transactions:
void CreateObjectStoreAbortOperation(int64_t object_store_id);
leveldb::Status DeleteObjectStoreOperation(int64_t object_store_id,
IndexedDBTransaction* transaction);
void DeleteObjectStoreAbortOperation(
IndexedDBObjectStoreMetadata object_store_metadata);
void RenameObjectStoreAbortOperation(int64_t object_store_id,
base::string16 old_name);
leveldb::Status VersionChangeOperation(
int64_t version,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
void VersionChangeAbortOperation(int64_t previous_version);
leveldb::Status DeleteIndexOperation(int64_t object_store_id,
int64_t index_id,
IndexedDBTransaction* transaction);
void CreateIndexAbortOperation(int64_t object_store_id, int64_t index_id);
void DeleteIndexAbortOperation(int64_t object_store_id,
IndexedDBIndexMetadata index_metadata);
void RenameIndexAbortOperation(int64_t object_store_id,
int64_t index_id,
base::string16 old_name);
leveldb::Status GetOperation(int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
indexed_db::CursorType cursor_type,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
leveldb::Status GetAllOperation(int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
indexed_db::CursorType cursor_type,
int64_t max_count,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
struct PutOperationParams;
leveldb::Status PutOperation(std::unique_ptr<PutOperationParams> params,
IndexedDBTransaction* transaction);
leveldb::Status SetIndexesReadyOperation(size_t index_count,
IndexedDBTransaction* transaction);
struct OpenCursorOperationParams;
leveldb::Status OpenCursorOperation(
std::unique_ptr<OpenCursorOperationParams> params,
IndexedDBTransaction* transaction);
leveldb::Status CountOperation(int64_t object_store_id,
int64_t index_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
leveldb::Status DeleteRangeOperation(
int64_t object_store_id,
std::unique_ptr<IndexedDBKeyRange> key_range,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
leveldb::Status ClearOperation(int64_t object_store_id,
scoped_refptr<IndexedDBCallbacks> callbacks,
IndexedDBTransaction* transaction);
// Called when a backing store operation has failed. The database will be
// closed (IndexedDBFactory::ForceClose) during this call. This should NOT
// be used in an method scheduled as a transaction operation.
void ReportError(leveldb::Status status);
void ReportErrorWithDetails(leveldb::Status status, const char* message);
IndexedDBFactory* factory() const { return factory_.get(); }
protected:
friend class IndexedDBTransaction;
IndexedDBDatabase(const base::string16& name,
scoped_refptr<IndexedDBBackingStore> backing_store,
scoped_refptr<IndexedDBFactory> factory,
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding,
const Identifier& unique_identifier);
virtual ~IndexedDBDatabase();
// May be overridden in tests.
virtual size_t GetMaxMessageSizeInBytes() const;
private:
friend class base::RefCounted<IndexedDBDatabase>;
friend class IndexedDBClassFactory;
FRIEND_TEST_ALL_PREFIXES(IndexedDBDatabaseTest, OpenDeleteClear);
void CallUpgradeTransactionStartedForTesting(int64_t old_version);
class ConnectionRequest;
class OpenRequest;
class DeleteRequest;
leveldb::Status OpenInternal();
// Called internally when an open or delete request comes in. Processes
// the queue immediately if there are no other requests.
void AppendRequest(std::unique_ptr<ConnectionRequest> request);
// Called by requests when complete. The request will be freed, so the
// request must do no other work after calling this. If there are pending
// requests, the queue will be synchronously processed.
void RequestComplete(ConnectionRequest* request);
// Pop the first request from the queue and start it.
void ProcessRequestQueue();
std::unique_ptr<IndexedDBConnection> CreateConnection(
scoped_refptr<IndexedDBDatabaseCallbacks> database_callbacks,
int child_process_id);
bool ValidateObjectStoreId(int64_t object_store_id) const;
bool ValidateObjectStoreIdAndIndexId(int64_t object_store_id,
int64_t index_id) const;
bool ValidateObjectStoreIdAndOptionalIndexId(int64_t object_store_id,
int64_t index_id) const;
bool ValidateObjectStoreIdAndNewIndexId(int64_t object_store_id,
int64_t index_id) const;
scoped_refptr<IndexedDBBackingStore> backing_store_;
IndexedDBDatabaseMetadata metadata_;
const Identifier identifier_;
scoped_refptr<IndexedDBFactory> factory_;
std::unique_ptr<IndexedDBMetadataCoding> metadata_coding_;
IndexedDBTransactionCoordinator transaction_coordinator_;
int64_t transaction_count_ = 0;
list_set<IndexedDBConnection*> connections_;
// This holds the first open or delete request that is currently being
// processed. The request has already broadcast OnVersionChange if
// necessary.
std::unique_ptr<ConnectionRequest> active_request_;
// This holds open or delete requests that are waiting for the active
// request to be completed. The requests have not yet broadcast
// OnVersionChange (if necessary).
base::queue<std::unique_ptr<ConnectionRequest>> pending_requests_;
// The |processing_pending_requests_| flag is set while ProcessRequestQueue()
// is executing. It prevents rentrant calls if the active request completes
// synchronously.
bool processing_pending_requests_ = false;
DISALLOW_COPY_AND_ASSIGN(IndexedDBDatabase);
};
} // namespace content
#endif // CONTENT_BROWSER_INDEXED_DB_INDEXED_DB_DATABASE_H_