// Copyright 2018 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_namespace_impl_mojo.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "base/bind.h"
#include "components/services/leveldb/public/cpp/util.h"
#include "content/browser/child_process_security_policy_impl.h"

namespace content {

namespace {
void SessionStorageResponse(base::OnceClosure callback, bool success) {
  std::move(callback).Run();
}
}  // namespace

SessionStorageNamespaceImplMojo::SessionStorageNamespaceImplMojo(
    std::string namespace_id,
    SessionStorageDataMap::Listener* data_map_listener,
    SessionStorageAreaImpl::RegisterNewAreaMap register_new_map_callback,
    Delegate* delegate)
    : namespace_id_(std::move(namespace_id)),
      data_map_listener_(data_map_listener),
      register_new_map_callback_(std::move(register_new_map_callback)),
      delegate_(delegate) {}

SessionStorageNamespaceImplMojo::~SessionStorageNamespaceImplMojo() {
  DCHECK(child_namespaces_waiting_for_clone_call_.empty());
}

void SessionStorageNamespaceImplMojo::SetPendingPopulationFromParentNamespace(
    const std::string& from_namespace) {
  pending_population_from_parent_namespace_ = from_namespace;
  state_ = State::kNotPopulatedAndPendingClone;
}

void SessionStorageNamespaceImplMojo::AddChildNamespaceWaitingForClone(
    const std::string& namespace_id) {
  child_namespaces_waiting_for_clone_call_.insert(namespace_id);
}
bool SessionStorageNamespaceImplMojo::HasChildNamespacesWaitingForClone()
    const {
  return !child_namespaces_waiting_for_clone_call_.empty();
}
void SessionStorageNamespaceImplMojo::ClearChildNamespacesWaitingForClone() {
  child_namespaces_waiting_for_clone_call_.clear();
}

bool SessionStorageNamespaceImplMojo::HasAreaForOrigin(
    const url::Origin& origin) const {
  return origin_areas_.find(origin) != origin_areas_.end();
}

void SessionStorageNamespaceImplMojo::PopulateFromMetadata(
    leveldb::mojom::LevelDBDatabase* database,
    SessionStorageMetadata::NamespaceEntry namespace_metadata) {
  DCHECK(!IsPopulated());
  database_ = database;
  state_ = State::kPopulated;
  pending_population_from_parent_namespace_.clear();
  namespace_entry_ = namespace_metadata;
  for (const auto& pair : namespace_entry_->second) {
    scoped_refptr<SessionStorageDataMap> data_map =
        delegate_->MaybeGetExistingDataMapForId(
            pair.second->MapNumberAsBytes());
    if (!data_map) {
      data_map = SessionStorageDataMap::CreateFromDisk(data_map_listener_,
                                                       pair.second, database_);
    }
    origin_areas_[pair.first] = std::make_unique<SessionStorageAreaImpl>(
        namespace_entry_, pair.first, std::move(data_map),
        register_new_map_callback_);
  }
  if (!run_after_population_.empty()) {
    for (base::OnceClosure& callback : run_after_population_)
      std::move(callback).Run();
    run_after_population_.clear();
  }
}

void SessionStorageNamespaceImplMojo::PopulateAsClone(
    leveldb::mojom::LevelDBDatabase* database,
    SessionStorageMetadata::NamespaceEntry namespace_metadata,
    const OriginAreas& areas_to_clone) {
  DCHECK(!IsPopulated());
  database_ = database;
  state_ = State::kPopulated;
  pending_population_from_parent_namespace_.clear();
  namespace_entry_ = namespace_metadata;
  std::transform(areas_to_clone.begin(), areas_to_clone.end(),
                 std::inserter(origin_areas_, origin_areas_.begin()),
                 [namespace_metadata](const auto& source) {
                   return std::make_pair(
                       source.first, source.second->Clone(namespace_metadata));
                 });
  if (!run_after_population_.empty()) {
    for (base::OnceClosure& callback : run_after_population_)
      std::move(callback).Run();
    run_after_population_.clear();
  }
}

void SessionStorageNamespaceImplMojo::Reset() {
  namespace_entry_ = SessionStorageMetadata::NamespaceEntry();
  database_ = nullptr;
  pending_population_from_parent_namespace_.clear();
  bind_waiting_on_population_ = false;
  run_after_population_.clear();
  state_ = State::kNotPopulated;
  child_namespaces_waiting_for_clone_call_.clear();
  origin_areas_.clear();
  receivers_.Clear();
}

void SessionStorageNamespaceImplMojo::Bind(
    mojo::PendingReceiver<blink::mojom::SessionStorageNamespace> receiver,
    int process_id) {
  if (!IsPopulated()) {
    bind_waiting_on_population_ = true;
    run_after_population_.push_back(base::BindOnce(
        &SessionStorageNamespaceImplMojo::Bind, base::Unretained(this),
        std::move(receiver), process_id));
    return;
  }
  DCHECK(IsPopulated());
  receivers_.Add(this, std::move(receiver), process_id);
  bind_waiting_on_population_ = false;
}

void SessionStorageNamespaceImplMojo::PurgeUnboundAreas() {
  auto it = origin_areas_.begin();
  while (it != origin_areas_.end()) {
    if (!it->second->IsBound())
      it = origin_areas_.erase(it);
    else
      ++it;
  }
}

void SessionStorageNamespaceImplMojo::RemoveOriginData(
    const url::Origin& origin,
    base::OnceClosure callback) {
  DCHECK_NE(state_, State::kNotPopulated);
  if (!IsPopulated()) {
    run_after_population_.push_back(
        base::BindOnce(&SessionStorageNamespaceImplMojo::RemoveOriginData,
                       base::Unretained(this), origin, std::move(callback)));
    return;
  }
  DCHECK(IsPopulated());
  auto it = origin_areas_.find(origin);
  if (it == origin_areas_.end()) {
    std::move(callback).Run();
    return;
  }
  // Renderer process expects |source| to always be two newline separated
  // strings.
  it->second->DeleteAll(
      "\n", base::BindOnce(&SessionStorageResponse, std::move(callback)));
  it->second->NotifyObserversAllDeleted();
  it->second->data_map()->storage_area()->ScheduleImmediateCommit();
}

void SessionStorageNamespaceImplMojo::OpenArea(
    const url::Origin& origin,
    mojo::PendingAssociatedReceiver<blink::mojom::StorageArea> receiver) {
  DCHECK(IsPopulated());
  DCHECK(!receivers_.empty());
  int process_id = receivers_.current_context();
  // TODO(943887): Replace HasSecurityState() call with something that can
  // preserve security state after process shutdown. The security state check
  // is a temporary solution to avoid crashes when this method is run after the
  // process associated with |process_id| has been destroyed.
  // It temporarily restores the old behavior of always allowing access if the
  // process is gone.
  auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
  if (!policy->CanAccessDataForOrigin(process_id, origin) &&
      policy->HasSecurityState(process_id)) {
    receivers_.ReportBadMessage("Access denied for sessionStorage request");
    return;
  }
  auto it = origin_areas_.find(origin);
  if (it == origin_areas_.end()) {
    // The area may have been purged due to lack of bindings, so check the
    // metadata for the map.
    scoped_refptr<SessionStorageDataMap> data_map;
    auto map_data_it = namespace_entry_->second.find(origin);
    if (map_data_it != namespace_entry_->second.end()) {
      // The map exists already, either on disk or being used by another
      // namespace.
      scoped_refptr<SessionStorageMetadata::MapData> map_data =
          map_data_it->second;
      data_map =
          delegate_->MaybeGetExistingDataMapForId(map_data->MapNumberAsBytes());
      if (!data_map) {
        data_map = SessionStorageDataMap::CreateFromDisk(data_map_listener_,
                                                         map_data, database_);
      }
    } else {
      // The map doesn't exist yet.
      data_map = SessionStorageDataMap::CreateEmpty(
          data_map_listener_,
          register_new_map_callback_.Run(namespace_entry_, origin), database_);
    }
    it = origin_areas_
             .emplace(std::make_pair(
                 origin, std::make_unique<SessionStorageAreaImpl>(
                             namespace_entry_, origin, std::move(data_map),
                             register_new_map_callback_)))
             .first;
  }
  it->second->Bind(std::move(receiver));
}

void SessionStorageNamespaceImplMojo::Clone(
    const std::string& clone_to_namespace) {
  DCHECK(IsPopulated());
  child_namespaces_waiting_for_clone_call_.erase(clone_to_namespace);
  delegate_->RegisterShallowClonedNamespace(namespace_entry_,
                                            clone_to_namespace, origin_areas_);
}

void SessionStorageNamespaceImplMojo::CloneAllNamespacesWaitingForClone(
    leveldb::mojom::LevelDBDatabase* database,
    SessionStorageMetadata* metadata,
    const std::map<std::string,
                   std::unique_ptr<SessionStorageNamespaceImplMojo>>&
        namespaces_map) {
  SessionStorageNamespaceImplMojo* parent = this;
  // If the current state is kNotPopulatedAndPendingClone, then the children can
  // all be cloned from our parent instead of us.
  if (state() ==
      SessionStorageNamespaceImplMojo::State::kNotPopulatedAndPendingClone) {
    auto parent_it =
        namespaces_map.find(pending_population_from_parent_namespace_);
    // The parent must be in the map, because the only way to remove something
    // from the map is to call DeleteSessionNamespace, which would have called
    // this method on the parent if there were children, and resolved our clone
    // dependency.
    DCHECK(parent_it != namespaces_map.end());
    parent = parent_it->second.get();
  }

  if (parent->state() ==
      SessionStorageNamespaceImplMojo::State::kNotPopulated) {
    // Populate the namespace to prepare for copy.
    parent->PopulateFromMetadata(
        database, metadata->GetOrCreateNamespaceEntry(parent->namespace_id_));
  }

  auto* delegate = parent->delegate_;
  for (const std::string& destination_namespace :
       child_namespaces_waiting_for_clone_call_) {
    if (parent->IsPopulated()) {
      delegate->RegisterShallowClonedNamespace(parent->namespace_entry(),
                                               destination_namespace,
                                               parent->origin_areas_);
    } else {
      parent->AddChildNamespaceWaitingForClone(destination_namespace);
      parent->run_after_population_.push_back(
          base::BindOnce(&SessionStorageNamespaceImplMojo::Clone,
                         base::Unretained(parent), destination_namespace));
      auto child_it = namespaces_map.find(destination_namespace);
      // The child must be in the map, as the only way to add it to
      // |child_namespaces_waiting_for_clone_call_| is to call
      // CloneSessionNamespace, which always adds it to the map.
      DCHECK(child_it != namespaces_map.end());
      child_it->second->SetPendingPopulationFromParentNamespace(
          parent->namespace_id_);
    }
  }
  child_namespaces_waiting_for_clone_call_.clear();
}

void SessionStorageNamespaceImplMojo::FlushOriginForTesting(
    const url::Origin& origin) {
  if (!IsPopulated())
    return;
  auto it = origin_areas_.find(origin);
  if (it == origin_areas_.end())
    return;
  it->second->data_map()->storage_area()->ScheduleImmediateCommit();
}

}  // namespace content
