1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108

content / browser / indexed_db / instance / connection_coordinator.h [blame]

// Copyright 2019 The Chromium Authors
// 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_INSTANCE_CONNECTION_COORDINATOR_H_
#define CONTENT_BROWSER_INDEXED_DB_INSTANCE_CONNECTION_COORDINATOR_H_

#include <memory>
#include <tuple>

#include "base/containers/queue.h"
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/indexed_db/instance/bucket_context.h"
#include "content/browser/indexed_db/status.h"
#include "content/common/content_export.h"

namespace content::indexed_db {
class FactoryClient;
class Connection;
class Database;
struct PendingConnection;

class CONTENT_EXPORT ConnectionCoordinator {
 public:
  static const int64_t kInvalidDatabaseId = 0;
  static const int64_t kMinimumIndexId = 30;

  ConnectionCoordinator(Database* db, BucketContext& bucket_context);

  ConnectionCoordinator(const ConnectionCoordinator&) = delete;
  ConnectionCoordinator& operator=(const ConnectionCoordinator&) = delete;

  ~ConnectionCoordinator();

  void ScheduleOpenConnection(std::unique_ptr<PendingConnection> connection);

  void ScheduleDeleteDatabase(std::unique_ptr<FactoryClient> factory_client,
                              base::OnceClosure on_deletion_complete);

  // Call this method to prune any tasks that don't want to be run during
  // force close. Returns any error caused by rolling back changes.
  Status PruneTasksForForceClose();

  void OnConnectionClosed(Connection* connection);

  void OnNoConnections();

  // 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 OnVersionChangeIgnored();

  void BindVersionChangeTransactionReceiver();

  void OnUpgradeTransactionStarted(int64_t old_version);

  void OnUpgradeTransactionFinished(bool committed);

  enum class ExecuteTaskResult {
    // There are more tasks to run, so ExecuteTask() should be called again.
    kMoreTasks,
    // There are tasks but they are waiting on async work to complete. No more
    // calls to ExecuteTask() are necessary.
    kPendingAsyncWork,
    // There was an error executing a task - see the status. The offending task
    // was removed, and the caller can choose to continue executing tasks if
    // they want.
    kError,
    // There are no more tasks to run.
    kDone,
  };
  std::tuple<ExecuteTaskResult, Status> ExecuteTask(bool has_connections);

  bool HasTasks() const { return !request_queue_.empty(); }

  // Number of active open/delete calls (running or blocked on other
  // connections).
  size_t ActiveOpenDeleteCount() const;

  // Number of open/delete calls that are waiting their turn.
  size_t PendingOpenDeleteCount() const;

  base::WeakPtr<ConnectionCoordinator> AsWeakPtr() {
    return weak_factory_.GetWeakPtr();
  }

 private:
  friend class Database;
  class ConnectionRequest;
  class OpenRequest;
  class DeleteRequest;

  raw_ptr<Database> db_;

  raw_ref<BucketContext> bucket_context_;

  base::queue<std::unique_ptr<ConnectionRequest>> request_queue_;

  // `weak_factory_` is used for all callback uses.
  base::WeakPtrFactory<ConnectionCoordinator> weak_factory_{this};
};

}  // namespace content::indexed_db

#endif  // CONTENT_BROWSER_INDEXED_DB_INSTANCE_CONNECTION_COORDINATOR_H_