// Copyright 2017 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.

#include "content/browser/dom_storage/session_storage_context_mojo.h"

#include <inttypes.h>
#include <cctype>  // for std::isalnum
#include <cstring>
#include <utility>

#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/trace_event/memory_dump_manager.h"
#include "build/build_config.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "components/services/leveldb/public/interfaces/leveldb.mojom.h"
#include "content/browser/dom_storage/session_storage_area_impl.h"
#include "content/browser/dom_storage/session_storage_namespace_impl_mojo.h"
#include "content/browser/dom_storage/storage_area_impl.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/public/browser/session_storage_usage_info.h"
#include "services/file/public/mojom/constants.mojom.h"
#include "services/service_manager/public/cpp/connector.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/leveldatabase/env_chromium.h"
#include "third_party/leveldatabase/leveldb_chrome.h"
#include "url/gurl.h"

namespace content {
namespace {
// After this many consecutive commit errors we'll throw away the entire
// database.
const int kSessionStorageCommitErrorThreshold = 8;

// Limits on the cache size and number of areas in memory, over which the areas
// are purged.
#if defined(OS_ANDROID)
const unsigned kMaxSessionStorageAreaCount = 10;
const size_t kMaxSessionStorageCacheSize = 2 * 1024 * 1024;
#else
const unsigned kMaxSessionStorageAreaCount = 50;
const size_t kMaxSessionStorageCacheSize = 20 * 1024 * 1024;
#endif

enum class SessionStorageCachePurgeReason {
  kNotNeeded,
  kSizeLimitExceeded,
  kAreaCountLimitExceeded,
  kInactiveOnLowEndDevice,
  kAggressivePurgeTriggered
};

void RecordSessionStorageCachePurgedHistogram(
    SessionStorageCachePurgeReason reason,
    size_t purged_size_kib) {
  UMA_HISTOGRAM_COUNTS_100000("SessionStorageContext.CachePurgedInKB",
                              purged_size_kib);
  switch (reason) {
    case SessionStorageCachePurgeReason::kSizeLimitExceeded:
      UMA_HISTOGRAM_COUNTS_100000(
          "SessionStorageContext.CachePurgedInKB.SizeLimitExceeded",
          purged_size_kib);
      break;
    case SessionStorageCachePurgeReason::kAreaCountLimitExceeded:
      UMA_HISTOGRAM_COUNTS_100000(
          "SessionStorageContext.CachePurgedInKB.AreaCountLimitExceeded",
          purged_size_kib);
      break;
    case SessionStorageCachePurgeReason::kInactiveOnLowEndDevice:
      UMA_HISTOGRAM_COUNTS_100000(
          "SessionStorageContext.CachePurgedInKB.InactiveOnLowEndDevice",
          purged_size_kib);
      break;
    case SessionStorageCachePurgeReason::kAggressivePurgeTriggered:
      UMA_HISTOGRAM_COUNTS_100000(
          "SessionStorageContext.CachePurgedInKB.AggressivePurgeTriggered",
          purged_size_kib);
      break;
    case SessionStorageCachePurgeReason::kNotNeeded:
      NOTREACHED();
      break;
  }
}

void SessionStorageErrorResponse(base::OnceClosure callback,
                                 leveldb::mojom::DatabaseError error) {
  std::move(callback).Run();
}
}  // namespace

SessionStorageContextMojo::SessionStorageContextMojo(
    scoped_refptr<base::SequencedTaskRunner> memory_dump_task_runner,
    service_manager::Connector* connector,
    BackingMode backing_mode,
    base::FilePath local_partition_directory,
    std::string leveldb_name)
    : connector_(connector ? connector->Clone() : nullptr),
      backing_mode_(backing_mode),
      partition_directory_path_(std::move(local_partition_directory)),
      leveldb_name_(std::move(leveldb_name)),
      memory_dump_id_(base::StringPrintf("SessionStorage/0x%" PRIXPTR,
                                         reinterpret_cast<uintptr_t>(this))),
      is_low_end_device_(base::SysInfo::IsLowEndDevice()),
      weak_ptr_factory_(this) {
  DCHECK(base::FeatureList::IsEnabled(blink::features::kOnionSoupDOMStorage));
  base::trace_event::MemoryDumpManager::GetInstance()
      ->RegisterDumpProviderWithSequencedTaskRunner(
          this, "SessionStorage", std::move(memory_dump_task_runner),
          base::trace_event::MemoryDumpProvider::Options());
}

SessionStorageContextMojo::~SessionStorageContextMojo() {
  DCHECK_EQ(connection_state_, CONNECTION_SHUTDOWN);
  base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider(
      this);
}

void SessionStorageContextMojo::OpenSessionStorage(
    int process_id,
    const std::string& namespace_id,
    mojo::ReportBadMessageCallback bad_message_callback,
    blink::mojom::SessionStorageNamespaceRequest request) {
  if (connection_state_ != CONNECTION_FINISHED) {
    RunWhenConnected(
        base::BindOnce(&SessionStorageContextMojo::OpenSessionStorage,
                       weak_ptr_factory_.GetWeakPtr(), process_id, namespace_id,
                       std::move(bad_message_callback), std::move(request)));
    return;
  }
  auto found = namespaces_.find(namespace_id);
  if (found == namespaces_.end()) {
    std::move(bad_message_callback).Run("Namespace not found: " + namespace_id);
    return;
  }

  if (!found->second->IsPopulated() &&
      !found->second->waiting_on_clone_population()) {
    found->second->PopulateFromMetadata(
        database_.get(), metadata_.GetOrCreateNamespaceEntry(namespace_id));
  }

  PurgeUnusedAreasIfNeeded();
  found->second->Bind(std::move(request), process_id);

  size_t total_cache_size, unused_area_count;
  GetStatistics(&total_cache_size, &unused_area_count);
  // Track the total sessionStorage cache size.
  UMA_HISTOGRAM_COUNTS_100000("SessionStorageContext.CacheSizeInKB",
                              total_cache_size / 1024);
}

void SessionStorageContextMojo::CreateSessionNamespace(
    const std::string& namespace_id) {
  if (namespaces_.find(namespace_id) != namespaces_.end())
    return;

  namespaces_.emplace(std::make_pair(
      namespace_id, CreateSessionStorageNamespaceImplMojo(namespace_id)));
}

void SessionStorageContextMojo::CloneSessionNamespace(
    const std::string& namespace_id_to_clone,
    const std::string& clone_namespace_id,
    CloneType clone_type) {
  if (namespaces_.find(clone_namespace_id) != namespaces_.end()) {
    // Non-immediate commits expect to be paired with a |Clone| from the mojo
    // namespace object. If that clone has already happened, then we don't need
    // to do anything here.
    // However, immediate commits happen without a |Clone| from the mojo
    // namespace object, so there should never be a namespace already populated
    // for an immediate clone.
    DCHECK_NE(clone_type, CloneType::kImmediate);
    return;
  }

  std::unique_ptr<SessionStorageNamespaceImplMojo> namespace_impl =
      CreateSessionStorageNamespaceImplMojo(clone_namespace_id);
  auto clone_from_ns = namespaces_.find(namespace_id_to_clone);
  switch (clone_type) {
    case CloneType::kImmediate: {
      // If the namespace doesn't exist or it's not populated yet, just create
      // an empty session storage.
      if (clone_from_ns == namespaces_.end() ||
          !clone_from_ns->second->IsPopulated()) {
        break;
      }
      clone_from_ns->second->Clone(clone_namespace_id);
      return;
    }
    case CloneType::kWaitForCloneOnNamespace:
      if (clone_from_ns != namespaces_.end()) {
        // The namespace exists and is in-use, so wait until receiving a clone
        // call on that mojo binding.
        namespace_impl->SetWaitingForClonePopulation();
        clone_from_ns->second->AddNamespacesWaitingForClone(clone_namespace_id);
      } else if (base::Contains(metadata_.namespace_origin_map(),
                                namespace_id_to_clone)) {
        // The namespace exists on disk but is not in-use, so do the appropriate
        // metadata operations to clone the namespace and set up the new object.
        std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
        auto source_namespace_entry =
            metadata_.GetOrCreateNamespaceEntry(namespace_id_to_clone);
        auto namespace_entry =
            metadata_.GetOrCreateNamespaceEntry(clone_namespace_id);
        metadata_.RegisterShallowClonedNamespace(
            source_namespace_entry, namespace_entry, &save_operations);
        if (database_) {
          database_->Write(
              std::move(save_operations),
              base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
                             base::Unretained(this)));
        }
        namespace_impl->PopulateFromMetadata(database_.get(), namespace_entry);
      }
      // If there is no sign of a source namespace, just run with an empty
      // namespace.
      break;
    default:
      NOTREACHED();
  }
  namespaces_.emplace(std::piecewise_construct,
                      std::forward_as_tuple(clone_namespace_id),
                      std::forward_as_tuple(std::move(namespace_impl)));
}

void SessionStorageContextMojo::DeleteSessionNamespace(
    const std::string& namespace_id,
    bool should_persist) {
  auto namespace_it = namespaces_.find(namespace_id);
  // If the namespace has pending clones, do the clone now before destroying it.
  if (namespace_it != namespaces_.end()) {
    if (namespace_it->second->HasNamespacesWaitingForClone())
      namespace_it->second->CloneAllNamespacesWaitingForClone();

    // The object hierarchy uses iterators bound to the metadata object, so
    // make sure to delete the object hierarchy first.
    namespaces_.erase(namespace_it);
  }

  if (!has_scavenged_ && should_persist)
    protected_namespaces_from_scavenge_.insert(namespace_id);

  if (!should_persist) {
    RunWhenConnected(
        base::BindOnce(&SessionStorageContextMojo::DoDatabaseDelete,
                       weak_ptr_factory_.GetWeakPtr(), namespace_id));
  }
}

void SessionStorageContextMojo::Flush() {
  if (connection_state_ != CONNECTION_FINISHED) {
    RunWhenConnected(base::BindOnce(&SessionStorageContextMojo::Flush,
                                    weak_ptr_factory_.GetWeakPtr()));
    return;
  }
  for (const auto& it : data_maps_)
    it.second->storage_area()->ScheduleImmediateCommit();
}

void SessionStorageContextMojo::GetStorageUsage(
    GetStorageUsageCallback callback) {
  if (connection_state_ != CONNECTION_FINISHED) {
    RunWhenConnected(base::BindOnce(&SessionStorageContextMojo::GetStorageUsage,
                                    weak_ptr_factory_.GetWeakPtr(),
                                    std::move(callback)));
    return;
  }

  const SessionStorageMetadata::NamespaceOriginMap& all_namespaces =
      metadata_.namespace_origin_map();

  std::vector<SessionStorageUsageInfo> result;
  result.reserve(all_namespaces.size());
  for (const auto& pair : all_namespaces) {
    for (const auto& origin_map_pair : pair.second) {
      SessionStorageUsageInfo info = {origin_map_pair.first.GetURL(),
                                      pair.first};
      result.push_back(std::move(info));
    }
  }
  std::move(callback).Run(std::move(result));
}

void SessionStorageContextMojo::DeleteStorage(const url::Origin& origin,
                                              const std::string& namespace_id,
                                              base::OnceClosure callback) {
  if (connection_state_ != CONNECTION_FINISHED) {
    RunWhenConnected(base::BindOnce(&SessionStorageContextMojo::DeleteStorage,
                                    weak_ptr_factory_.GetWeakPtr(), origin,
                                    namespace_id, std::move(callback)));
    return;
  }
  auto found = namespaces_.find(namespace_id);
  if (found != namespaces_.end() &&
      (found->second->IsPopulated() ||
       found->second->waiting_on_clone_population())) {
    found->second->RemoveOriginData(origin, std::move(callback));
  } else {
    // If we don't have the namespace loaded, then we can delete it all
    // using the metadata.
    std::vector<leveldb::mojom::BatchedOperationPtr> delete_operations;
    metadata_.DeleteArea(namespace_id, origin, &delete_operations);
    if (database_) {
      database_->Write(
          std::move(delete_operations),
          base::BindOnce(&SessionStorageContextMojo::OnCommitResultWithCallback,
                         base::Unretained(this), std::move(callback)));
    } else {
      std::move(callback).Run();
    }
  }
}

void SessionStorageContextMojo::PerformStorageCleanup(
    base::OnceClosure callback) {
  if (connection_state_ != CONNECTION_FINISHED) {
    RunWhenConnected(
        base::BindOnce(&SessionStorageContextMojo::PerformStorageCleanup,
                       weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
    return;
  }
  if (database_) {
    for (const auto& it : data_maps_)
      it.second->storage_area()->ScheduleImmediateCommit();
    database_->RewriteDB(
        base::BindOnce(&SessionStorageErrorResponse, std::move(callback)));
  } else {
    std::move(callback).Run();
  }
}

void SessionStorageContextMojo::ShutdownAndDelete() {
  DCHECK_NE(connection_state_, CONNECTION_SHUTDOWN);

  // The namespaces will DCHECK if they are destructed with pending clones. It
  // is valid for to drop these on shutdown.
  for (auto& namespace_pair : namespaces_) {
    namespace_pair.second->ClearNamespacesWaitingForClone();
  }

  // Nothing to do if no connection to the database was ever finished.
  if (connection_state_ != CONNECTION_FINISHED) {
    connection_state_ = CONNECTION_SHUTDOWN;
    OnShutdownComplete(leveldb::mojom::DatabaseError::OK);
    return;
  }
  connection_state_ = CONNECTION_SHUTDOWN;

  // Flush any uncommitted data.
  for (const auto& it : data_maps_) {
    auto* area = it.second->storage_area();
    LOCAL_HISTOGRAM_BOOLEAN(
        "SessionStorageContext.ShutdownAndDelete.MaybeDroppedChanges",
        area->has_pending_load_tasks());
    area->ScheduleImmediateCommit();
    // TODO(dmurph): Monitor the above histogram, and if dropping changes is
    // common then handle that here.
    area->CancelAllPendingRequests();
  }

  OnShutdownComplete(leveldb::mojom::DatabaseError::OK);
}

void SessionStorageContextMojo::PurgeMemory() {
  size_t total_cache_size, unused_area_count;
  GetStatistics(&total_cache_size, &unused_area_count);

  // Purge all areas that don't have bindings.
  for (const auto& namespace_pair : namespaces_) {
    namespace_pair.second->PurgeUnboundAreas();
  }
  // Purge memory from bound maps.
  for (const auto& data_map_pair : data_maps_) {
    data_map_pair.second->storage_area()->PurgeMemory();
  }

  // Track the size of cache purged.
  size_t final_total_cache_size;
  GetStatistics(&final_total_cache_size, &unused_area_count);
  size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
  RecordSessionStorageCachePurgedHistogram(
      SessionStorageCachePurgeReason::kAggressivePurgeTriggered,
      purged_size_kib);
}

void SessionStorageContextMojo::PurgeUnusedAreasIfNeeded() {
  size_t total_cache_size, unused_area_count;
  GetStatistics(&total_cache_size, &unused_area_count);

  // Nothing to purge.
  if (!unused_area_count)
    return;

  SessionStorageCachePurgeReason purge_reason =
      SessionStorageCachePurgeReason::kNotNeeded;

  if (total_cache_size > kMaxSessionStorageCacheSize)
    purge_reason = SessionStorageCachePurgeReason::kSizeLimitExceeded;
  else if (data_maps_.size() > kMaxSessionStorageAreaCount)
    purge_reason = SessionStorageCachePurgeReason::kAreaCountLimitExceeded;
  else if (is_low_end_device_)
    purge_reason = SessionStorageCachePurgeReason::kInactiveOnLowEndDevice;

  if (purge_reason == SessionStorageCachePurgeReason::kNotNeeded)
    return;

  // Purge all areas that don't have bindings.
  for (const auto& namespace_pair : namespaces_) {
    namespace_pair.second->PurgeUnboundAreas();
  }

  size_t final_total_cache_size;
  GetStatistics(&final_total_cache_size, &unused_area_count);
  size_t purged_size_kib = (total_cache_size - final_total_cache_size) / 1024;
  RecordSessionStorageCachePurgedHistogram(purge_reason, purged_size_kib);
}

void SessionStorageContextMojo::ScavengeUnusedNamespaces(
    base::OnceClosure done) {
  if (has_scavenged_)
    return;
  if (connection_state_ != CONNECTION_FINISHED) {
    RunWhenConnected(
        base::BindOnce(&SessionStorageContextMojo::ScavengeUnusedNamespaces,
                       weak_ptr_factory_.GetWeakPtr(), std::move(done)));
    return;
  }
  has_scavenged_ = true;
  std::vector<std::string> namespaces_to_delete;
  for (const auto& metadata_namespace : metadata_.namespace_origin_map()) {
    const std::string& namespace_id = metadata_namespace.first;
    if (namespaces_.find(namespace_id) != namespaces_.end() ||
        protected_namespaces_from_scavenge_.find(namespace_id) !=
            protected_namespaces_from_scavenge_.end()) {
      continue;
    }
    namespaces_to_delete.push_back(namespace_id);
  }
  std::vector<leveldb::mojom::BatchedOperationPtr> delete_operations;
  for (const auto& namespace_id : namespaces_to_delete) {
    metadata_.DeleteNamespace(namespace_id, &delete_operations);
  }

  if (!delete_operations.empty()) {
    database_->Write(std::move(delete_operations),
                     base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
                                    base::Unretained(this)));
  }
  protected_namespaces_from_scavenge_.clear();
  if (done)
    std::move(done).Run();
}

bool SessionStorageContextMojo::OnMemoryDump(
    const base::trace_event::MemoryDumpArgs& args,
    base::trace_event::ProcessMemoryDump* pmd) {
  if (connection_state_ != CONNECTION_FINISHED)
    return true;

  std::string context_name =
      base::StringPrintf("site_storage/sessionstorage/0x%" PRIXPTR,
                         reinterpret_cast<uintptr_t>(this));

  // Account for leveldb memory usage, which actually lives in the file service.
  auto* global_dump = pmd->CreateSharedGlobalAllocatorDump(memory_dump_id_);
  // The size of the leveldb dump will be added by the leveldb service.
  auto* leveldb_mad = pmd->CreateAllocatorDump(context_name + "/leveldb");
  // Specifies that the current context is responsible for keeping memory alive.
  int kImportance = 2;
  pmd->AddOwnershipEdge(leveldb_mad->guid(), global_dump->guid(), kImportance);

  if (args.level_of_detail ==
      base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND) {
    size_t total_cache_size, unused_area_count;
    GetStatistics(&total_cache_size, &unused_area_count);
    auto* mad = pmd->CreateAllocatorDump(context_name + "/cache_size");
    mad->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize,
                   base::trace_event::MemoryAllocatorDump::kUnitsBytes,
                   total_cache_size);
    mad->AddScalar("total_areas",
                   base::trace_event::MemoryAllocatorDump::kUnitsObjects,
                   data_maps_.size());
    return true;
  }
  for (const auto& it : data_maps_) {
    // Limit the url length to 50 and strip special characters.
    const auto& origin = it.second->map_data()->origin();
    std::string url = origin.Serialize().substr(0, 50);
    for (size_t index = 0; index < url.size(); ++index) {
      if (!std::isalnum(url[index]))
        url[index] = '_';
    }
    std::string area_dump_name = base::StringPrintf(
        "%s/%s/0x%" PRIXPTR, context_name.c_str(), url.c_str(),
        reinterpret_cast<uintptr_t>(it.second->storage_area()));
    it.second->storage_area()->OnMemoryDump(area_dump_name, pmd);
  }
  return true;
}

void SessionStorageContextMojo::SetDatabaseForTesting(
    leveldb::mojom::LevelDBDatabaseAssociatedPtr database) {
  DCHECK_EQ(connection_state_, NO_CONNECTION);
  connection_state_ = CONNECTION_IN_PROGRESS;
  database_ = std::move(database);
  OnDatabaseOpened(true, leveldb::mojom::DatabaseError::OK);
}

void SessionStorageContextMojo::FlushAreaForTesting(
    const std::string& namespace_id,
    const url::Origin& origin) {
  if (connection_state_ != CONNECTION_FINISHED)
    return;
  const auto& it = namespaces_.find(namespace_id);
  if (it == namespaces_.end())
    return;
  it->second->FlushOriginForTesting(origin);
}

scoped_refptr<SessionStorageMetadata::MapData>
SessionStorageContextMojo::RegisterNewAreaMap(
    SessionStorageMetadata::NamespaceEntry namespace_entry,
    const url::Origin& origin) {
  std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;
  scoped_refptr<SessionStorageMetadata::MapData> map_entry =
      metadata_.RegisterNewMap(namespace_entry, origin, &save_operations);

  if (database_) {
    database_->Write(std::move(save_operations),
                     base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
                                    base::Unretained(this)));
  }
  return map_entry;
}

void SessionStorageContextMojo::OnDataMapCreation(
    const std::vector<uint8_t>& map_prefix,
    SessionStorageDataMap* map) {
  DCHECK(data_maps_.find(map_prefix) == data_maps_.end());
  data_maps_.emplace(std::piecewise_construct,
                     std::forward_as_tuple(map_prefix),
                     std::forward_as_tuple(map));
}

void SessionStorageContextMojo::OnDataMapDestruction(
    const std::vector<uint8_t>& map_prefix) {
  data_maps_.erase(map_prefix);
}

void SessionStorageContextMojo::OnCommitResult(
    leveldb::mojom::DatabaseError error) {
  DCHECK_EQ(connection_state_, CONNECTION_FINISHED);
  UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.CommitResult",
                            leveldb::GetLevelDBStatusUMAValue(error),
                            leveldb_env::LEVELDB_STATUS_MAX);
  if (error == leveldb::mojom::DatabaseError::OK) {
    commit_error_count_ = 0;
    return;
  }
  commit_error_count_++;
  if (commit_error_count_ > kSessionStorageCommitErrorThreshold) {
    if (tried_to_recover_from_commit_errors_) {
      // We already tried to recover from a high commit error rate before, but
      // are still having problems: there isn't really anything left to try, so
      // just ignore errors.
      return;
    }
    tried_to_recover_from_commit_errors_ = true;

    // Deleting StorageAreas in here could cause more commits (and commit
    // errors), but those commits won't reach OnCommitResult because the area
    // will have been deleted before the commit finishes.
    DeleteAndRecreateDatabase(
        "SessionStorageContext.OpenResultAfterCommitErrors");
  }
}

void SessionStorageContextMojo::OnCommitResultWithCallback(
    base::OnceClosure callback,
    leveldb::mojom::DatabaseError error) {
  OnCommitResult(error);
  std::move(callback).Run();
}

scoped_refptr<SessionStorageDataMap>
SessionStorageContextMojo::MaybeGetExistingDataMapForId(
    const std::vector<uint8_t>& map_number_as_bytes) {
  auto it = data_maps_.find(map_number_as_bytes);
  if (it == data_maps_.end())
    return nullptr;
  return base::WrapRefCounted(it->second);
}

void SessionStorageContextMojo::RegisterShallowClonedNamespace(
    SessionStorageMetadata::NamespaceEntry source_namespace_entry,
    const std::string& new_namespace_id,
    const SessionStorageNamespaceImplMojo::OriginAreas& clone_from_areas) {
  std::vector<leveldb::mojom::BatchedOperationPtr> save_operations;

  bool found = false;
  auto it = namespaces_.find(new_namespace_id);
  if (it != namespaces_.end()) {
    found = true;
    if (it->second->IsPopulated()) {
      // Assumes this method is called on a stack handling a mojo message.
      mojo::ReportBadMessage("Cannot clone to already populated namespace");
      return;
    }
  }

  auto namespace_entry = metadata_.GetOrCreateNamespaceEntry(new_namespace_id);
  metadata_.RegisterShallowClonedNamespace(source_namespace_entry,
                                           namespace_entry, &save_operations);
  if (database_) {
    database_->Write(std::move(save_operations),
                     base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
                                    base::Unretained(this)));
  }

  if (found) {
    it->second->PopulateAsClone(database_.get(), namespace_entry,
                                clone_from_areas);
    return;
  }

  auto namespace_impl = CreateSessionStorageNamespaceImplMojo(new_namespace_id);
  namespace_impl->PopulateAsClone(database_.get(), namespace_entry,
                                  clone_from_areas);
  namespaces_.emplace(std::piecewise_construct,
                      std::forward_as_tuple(new_namespace_id),
                      std::forward_as_tuple(std::move(namespace_impl)));
}

std::unique_ptr<SessionStorageNamespaceImplMojo>
SessionStorageContextMojo::CreateSessionStorageNamespaceImplMojo(
    std::string namespace_id) {
  SessionStorageAreaImpl::RegisterNewAreaMap map_id_callback =
      base::BindRepeating(&SessionStorageContextMojo::RegisterNewAreaMap,
                          base::Unretained(this));

  return std::make_unique<SessionStorageNamespaceImplMojo>(
      std::move(namespace_id), this, std::move(map_id_callback), this);
}

void SessionStorageContextMojo::DoDatabaseDelete(
    const std::string& namespace_id) {
  DCHECK_EQ(connection_state_, CONNECTION_FINISHED);
  std::vector<leveldb::mojom::BatchedOperationPtr> delete_operations;
  metadata_.DeleteNamespace(namespace_id, &delete_operations);
  if (database_) {
    database_->Write(std::move(delete_operations),
                     base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
                                    base::Unretained(this)));
  }
}

void SessionStorageContextMojo::RunWhenConnected(base::OnceClosure callback) {
  switch (connection_state_) {
    case NO_CONNECTION:
      // If we don't have a filesystem_connection_, we'll need to establish one.
      connection_state_ = CONNECTION_IN_PROGRESS;
      on_database_opened_callbacks_.push_back(std::move(callback));
      InitiateConnection();
      return;
    case CONNECTION_IN_PROGRESS:
      // Queue this OpenSessionStorage call for when we have a level db pointer.
      on_database_opened_callbacks_.push_back(std::move(callback));
      return;
    case CONNECTION_SHUTDOWN:
      NOTREACHED();
      return;
    case CONNECTION_FINISHED:
      std::move(callback).Run();
      return;
  }
  NOTREACHED();
}

void SessionStorageContextMojo::InitiateConnection(bool in_memory_only) {
  DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
  // Unit tests might not always have a Connector, use in-memory only if that
  // happens.
  if (!connector_) {
    OnDatabaseOpened(false, leveldb::mojom::DatabaseError::OK);
    return;
  }

  if (backing_mode_ != BackingMode::kNoDisk && !in_memory_only) {
    // We were given a subdirectory to write to. Get it and use a disk backed
    // database.
    connector_->BindInterface(file::mojom::kServiceName, &file_system_);
    file_system_->GetSubDirectory(
        partition_directory_path_.AsUTF8Unsafe(),
        MakeRequest(&partition_directory_),
        base::BindOnce(&SessionStorageContextMojo::OnDirectoryOpened,
                       weak_ptr_factory_.GetWeakPtr()));
  } else {
    // We were not given a subdirectory. Use a memory backed database.
    connector_->BindInterface(file::mojom::kServiceName, &leveldb_service_);
    leveldb_service_->OpenInMemory(
        memory_dump_id_, "SessionStorageDatabase", MakeRequest(&database_),
        base::BindOnce(&SessionStorageContextMojo::OnDatabaseOpened,
                       weak_ptr_factory_.GetWeakPtr(), true));
  }
}

void SessionStorageContextMojo::OnDirectoryOpened(base::File::Error err) {
  if (err != base::File::FILE_OK) {
    // We failed to open the directory; continue with startup so that we create
    // the data maps.
    UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DirectoryOpenError", -err,
                              -base::File::FILE_ERROR_MAX);
    LogDatabaseOpenResult(OpenResult::kDirectoryOpenFailed);
    OnDatabaseOpened(false, leveldb::mojom::DatabaseError::OK);
    return;
  }

  // Now that we have a directory, connect to the LevelDB service and get our
  // database.
  connector_->BindInterface(file::mojom::kServiceName, &leveldb_service_);

  // We might still need to use the directory, so create a clone.
  filesystem::mojom::DirectoryPtr partition_directory_clone;
  partition_directory_->Clone(MakeRequest(&partition_directory_clone));

  if (backing_mode_ == BackingMode::kClearDiskStateOnOpen) {
    filesystem::mojom::DirectoryPtr partition_directory_clone_for_deletion;
    partition_directory_->Clone(
        MakeRequest(&partition_directory_clone_for_deletion));
    leveldb_service_->Destroy(std::move(partition_directory_clone_for_deletion),
                              leveldb_name_, base::DoNothing());
  }

  leveldb_env::Options options;
  options.create_if_missing = true;
  options.max_open_files = 0;  // use minimum
  // Default write_buffer_size is 4 MB but that might leave a 3.999
  // memory allocation in RAM from a log file recovery.
  options.write_buffer_size = 64 * 1024;
  options.block_cache = leveldb_chrome::GetSharedWebBlockCache();
  leveldb_service_->OpenWithOptions(
      std::move(options), std::move(partition_directory_clone), leveldb_name_,
      memory_dump_id_, MakeRequest(&database_),
      base::BindOnce(&SessionStorageContextMojo::OnDatabaseOpened,
                     weak_ptr_factory_.GetWeakPtr(), false));
}

void SessionStorageContextMojo::OnMojoConnectionDestroyed() {
  UMA_HISTOGRAM_BOOLEAN("SessionStorageContext.OnConnectionDestroyed", true);
  LOG(ERROR) << "Lost connection to database";
  for (const auto& it : data_maps_)
    it.second->storage_area()->CancelAllPendingRequests();

  for (const auto& namespace_pair : namespaces_)
    namespace_pair.second->Reset();

  DCHECK(data_maps_.empty());
  database_.reset();
}

void SessionStorageContextMojo::OnDatabaseOpened(
    bool in_memory,
    leveldb::mojom::DatabaseError status) {
  if (status != leveldb::mojom::DatabaseError::OK) {
    UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DatabaseOpenError",
                              leveldb::GetLevelDBStatusUMAValue(status),
                              leveldb_env::LEVELDB_STATUS_MAX);
    if (in_memory) {
      UMA_HISTOGRAM_ENUMERATION(
          "SessionStorageContext.DatabaseOpenError.Memory",
          leveldb::GetLevelDBStatusUMAValue(status),
          leveldb_env::LEVELDB_STATUS_MAX);
    } else {
      UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DatabaseOpenError.Disk",
                                leveldb::GetLevelDBStatusUMAValue(status),
                                leveldb_env::LEVELDB_STATUS_MAX);
    }
    LogDatabaseOpenResult(OpenResult::kDatabaseOpenFailed);
    // If we failed to open the database, try to delete and recreate the
    // database, or ultimately fallback to an in-memory database.
    DeleteAndRecreateDatabase(
        "SessionStorageContext.OpenResultAfterOpenFailed");
    return;
  }

  // Verify DB schema version.
  if (database_) {
    database_.set_connection_error_handler(
        base::BindOnce(&SessionStorageContextMojo::OnMojoConnectionDestroyed,
                       weak_ptr_factory_.GetWeakPtr()));
    database_->Get(
        std::vector<uint8_t>(
            SessionStorageMetadata::kDatabaseVersionBytes,
            std::end(SessionStorageMetadata::kDatabaseVersionBytes)),
        base::BindOnce(&SessionStorageContextMojo::OnGotDatabaseVersion,
                       weak_ptr_factory_.GetWeakPtr()));
    return;
  }

  OnConnectionFinished();
}

void SessionStorageContextMojo::OnGotDatabaseVersion(
    leveldb::mojom::DatabaseError status,
    const std::vector<uint8_t>& value) {
  std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations;
  if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
    // New database, or schema v0. We must treat this as a schema v0 database.
    metadata_.ParseDatabaseVersion(base::nullopt, &migration_operations);
  } else if (status == leveldb::mojom::DatabaseError::OK) {
    if (!metadata_.ParseDatabaseVersion(value, &migration_operations)) {
      LogDatabaseOpenResult(OpenResult::kInvalidVersion);
      DeleteAndRecreateDatabase(
          "SessionStorageContext.OpenResultAfterInvalidVersion");
      return;
    }
    database_initialized_ = true;
  } else {
    // Other read error. Possibly database corruption.
    UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.ReadVersionError",
                              leveldb::GetLevelDBStatusUMAValue(status),
                              leveldb_env::LEVELDB_STATUS_MAX);
    LogDatabaseOpenResult(OpenResult::kVersionReadError);
    DeleteAndRecreateDatabase(
        "SessionStorageContext.OpenResultAfterReadVersionError");
    return;
  }

  base::RepeatingClosure barrier = base::BarrierClosure(
      2, base::BindOnce(&SessionStorageContextMojo::OnConnectionFinished,
                        weak_ptr_factory_.GetWeakPtr()));

  std::vector<uint8_t> namespace_prefix(
      SessionStorageMetadata::kNamespacePrefixBytes,
      std::end(SessionStorageMetadata::kNamespacePrefixBytes));
  std::vector<uint8_t> next_map_id_key(
      SessionStorageMetadata::kNextMapIdKeyBytes,
      std::end(SessionStorageMetadata::kNextMapIdKeyBytes));
  database_->GetPrefixed(
      namespace_prefix,
      base::BindOnce(&SessionStorageContextMojo::OnGotNamespaces,
                     weak_ptr_factory_.GetWeakPtr(), barrier,
                     std::move(migration_operations)));
  database_->Get(next_map_id_key,
                 base::BindOnce(&SessionStorageContextMojo::OnGotNextMapId,
                                weak_ptr_factory_.GetWeakPtr(), barrier));
}

void SessionStorageContextMojo::OnGotNamespaces(
    base::OnceClosure done,
    std::vector<leveldb::mojom::BatchedOperationPtr> migration_operations,
    leveldb::mojom::DatabaseError status,
    std::vector<leveldb::mojom::KeyValuePtr> values) {
  DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
  bool parsing_failure =
      status == leveldb::mojom::DatabaseError::OK &&
      !metadata_.ParseNamespaces(std::move(values), &migration_operations);
  if (status != leveldb::mojom::DatabaseError::OK || parsing_failure) {
    UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.ReadNamespacesError",
                              leveldb::GetLevelDBStatusUMAValue(status),
                              leveldb_env::LEVELDB_STATUS_MAX);
    LogDatabaseOpenResult(OpenResult::kNamespacesReadError);
    DeleteAndRecreateDatabase(
        "SessionStorageContext.OpenResultAfterReadNamespacesError");
    return;
  }

  // Write all of our migration operations if we have any.
  if (!migration_operations.empty()) {
    database_->Write(std::move(migration_operations),
                     base::BindOnce(&SessionStorageContextMojo::OnCommitResult,
                                    base::Unretained(this)));
  }
  std::move(done).Run();
}

void SessionStorageContextMojo::OnGotNextMapId(
    base::OnceClosure done,
    leveldb::mojom::DatabaseError status,
    const std::vector<uint8_t>& map_id) {
  DCHECK_EQ(connection_state_, CONNECTION_IN_PROGRESS);
  if (status == leveldb::mojom::DatabaseError::NOT_FOUND) {
    std::move(done).Run();
    return;
  }
  if (status == leveldb::mojom::DatabaseError::OK) {
    metadata_.ParseNextMapId(map_id);
    std::move(done).Run();
    return;
  }

  // Other read error. Possibly database corruption.
  UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.ReadNextMapIdError",
                            leveldb::GetLevelDBStatusUMAValue(status),
                            leveldb_env::LEVELDB_STATUS_MAX);
  LogDatabaseOpenResult(OpenResult::kNamespacesReadError);
  DeleteAndRecreateDatabase(
      "SessionStorageContext.OpenResultAfterReadNextMapIdError");
}

void SessionStorageContextMojo::OnConnectionFinished() {
  DCHECK(!database_ || connection_state_ == CONNECTION_IN_PROGRESS);
  if (!database_) {
    partition_directory_.reset();
    file_system_.reset();
    leveldb_service_.reset();
  }

  // If connection was opened successfully, reset tried_to_recreate_during_open_
  // to enable recreating the database on future errors.
  if (database_)
    tried_to_recreate_during_open_ = false;

  LogDatabaseOpenResult(OpenResult::kSuccess);
  open_result_histogram_ = nullptr;

  // |database_| should be known to either be valid or invalid by now. Run our
  // delayed bindings.
  connection_state_ = CONNECTION_FINISHED;
  std::vector<base::OnceClosure> callbacks;
  std::swap(callbacks, on_database_opened_callbacks_);
  for (size_t i = 0; i < callbacks.size(); ++i)
    std::move(callbacks[i]).Run();
}

void SessionStorageContextMojo::DeleteAndRecreateDatabase(
    const char* histogram_name) {
  // We're about to set database_ to null, so delete the StorageAreas
  // that might still be using the old database.
  for (const auto& it : data_maps_)
    it.second->storage_area()->CancelAllPendingRequests();

  for (const auto& namespace_pair : namespaces_) {
    namespace_pair.second->Reset();
  }
  DCHECK(data_maps_.empty());

  // Reset state to be in process of connecting. This will cause requests for
  // StorageAreas to be queued until the connection is complete.
  connection_state_ = CONNECTION_IN_PROGRESS;
  commit_error_count_ = 0;
  database_ = nullptr;
  open_result_histogram_ = histogram_name;

  bool recreate_in_memory = false;

  // If tried to recreate database on disk already, try again but this time
  // in memory.
  if (tried_to_recreate_during_open_ && backing_mode_ != BackingMode::kNoDisk) {
    recreate_in_memory = true;
  } else if (tried_to_recreate_during_open_) {
    // Give up completely, run without any database.
    OnConnectionFinished();
    return;
  }

  tried_to_recreate_during_open_ = true;

  // Unit tests might not have a bound file_service_, in which case there is
  // nothing to retry.
  if (!file_system_.is_bound()) {
    OnConnectionFinished();
    return;
  }

  protected_namespaces_from_scavenge_.clear();

  // Destroy database, and try again.
  if (partition_directory_.is_bound()) {
    leveldb_service_->Destroy(
        std::move(partition_directory_), leveldb_name_,
        base::BindOnce(&SessionStorageContextMojo::OnDBDestroyed,
                       weak_ptr_factory_.GetWeakPtr(), recreate_in_memory));
  } else {
    // No directory, so nothing to destroy. Retrying to recreate will probably
    // fail, but try anyway.
    InitiateConnection(recreate_in_memory);
  }
}

void SessionStorageContextMojo::OnDBDestroyed(
    bool recreate_in_memory,
    leveldb::mojom::DatabaseError status) {
  UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.DestroyDBResult",
                            leveldb::GetLevelDBStatusUMAValue(status),
                            leveldb_env::LEVELDB_STATUS_MAX);
  // We're essentially ignoring the status here. Even if destroying failed we
  // still want to go ahead and try to recreate.
  InitiateConnection(recreate_in_memory);
}

void SessionStorageContextMojo::OnShutdownComplete(
    leveldb::mojom::DatabaseError error) {
  delete this;
}

void SessionStorageContextMojo::GetStatistics(size_t* total_cache_size,
                                              size_t* unused_area_count) {
  *total_cache_size = 0;
  *unused_area_count = 0;
  for (const auto& it : data_maps_) {
    *total_cache_size += it.second->storage_area()->memory_used();
    if (it.second->binding_count() == 0)
      (*unused_area_count)++;
  }
}

void SessionStorageContextMojo::LogDatabaseOpenResult(OpenResult result) {
  if (result != OpenResult::kSuccess) {
    LOG(ERROR) << "Got error when opening: " << static_cast<int>(result);
    UMA_HISTOGRAM_ENUMERATION("SessionStorageContext.OpenError", result);
  }
  if (open_result_histogram_) {
    base::UmaHistogramEnumeration(open_result_histogram_, result);
  }
}

}  // namespace content
