// Copyright 2014 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 "storage/browser/quota/storage_monitor.h"

#include <stdint.h>

#include <algorithm>
#include <memory>

#include "base/bind.h"
#include "base/trace_event/trace_event.h"
#include "net/base/url_util.h"
#include "storage/browser/quota/quota_manager.h"

namespace storage {

// StorageObserverList:

StorageObserverList::ObserverState::ObserverState()
    : requires_update(false) {
}

StorageObserverList::StorageObserverList() = default;

StorageObserverList::~StorageObserverList() = default;

void StorageObserverList::AddObserver(
    StorageObserver* observer, const StorageObserver::MonitorParams& params) {
  ObserverState& observer_state = observer_state_map_[observer];
  observer_state.origin = params.filter.origin;
  observer_state.rate = params.rate;
}

void StorageObserverList::RemoveObserver(StorageObserver* observer) {
  observer_state_map_.erase(observer);
}

size_t StorageObserverList::ObserverCount() const {
  return observer_state_map_.size();
}

void StorageObserverList::OnStorageChange(const StorageObserver::Event& event) {
  // crbug.com/349708
  TRACE_EVENT0("io",
               "HostStorageObserversStorageObserverList::OnStorageChange");

  for (auto& observer_state_pair : observer_state_map_)
    observer_state_pair.second.requires_update = true;

  MaybeDispatchEvent(event);
}

void StorageObserverList::MaybeDispatchEvent(
    const StorageObserver::Event& event) {
  // crbug.com/349708
  TRACE_EVENT0("io", "StorageObserverList::MaybeDispatchEvent");

  notification_timer_.Stop();
  base::TimeDelta min_delay = base::TimeDelta::Max();
  bool all_observers_notified = true;

  for (auto& observer_state_pair : observer_state_map_) {
    StorageObserver* observer = observer_state_pair.first;
    ObserverState& state = observer_state_pair.second;

    if (!state.requires_update)
      continue;

    base::TimeTicks current_time = base::TimeTicks::Now();
    base::TimeDelta delta = current_time - state.last_notification_time;
    if (state.last_notification_time.is_null() || delta >= state.rate) {
      state.requires_update = false;
      state.last_notification_time = current_time;

      if (state.origin == event.filter.origin) {
        // crbug.com/349708
        TRACE_EVENT0("io",
                     "StorageObserverList::MaybeDispatchEvent OnStorageEvent1");

        observer->OnStorageEvent(event);
      } else {
        // When the quota and usage of an origin is requested, QuotaManager
        // returns the quota and usage of the host. Multiple origins can map to
        // to the same host, so ensure the |origin| field in the dispatched
        // event matches the |origin| specified by the observer when it was
        // registered.
        StorageObserver::Event dispatch_event(event);
        dispatch_event.filter.origin = state.origin;

        // crbug.com/349708
        TRACE_EVENT0("io",
                     "StorageObserverList::MaybeDispatchEvent OnStorageEvent2");

        observer->OnStorageEvent(dispatch_event);
      }
    } else {
      all_observers_notified = false;
      base::TimeDelta delay = state.rate - delta;
      if (delay < min_delay)
        min_delay = delay;
    }
  }

  // We need to respect the notification rate specified by observers. So if it
  // is too soon to dispatch an event to an observer, save the event and
  // dispatch it after a delay. If we simply drop the event, another one may
  // not arrive anytime soon and the observer will miss the most recent event.
  if (!all_observers_notified) {
    pending_event_ = event;
    notification_timer_.Start(
        FROM_HERE,
        min_delay,
        this,
        &StorageObserverList::DispatchPendingEvent);
  }
}

void StorageObserverList::ScheduleUpdateForObserver(StorageObserver* observer) {
  DCHECK(base::ContainsKey(observer_state_map_, observer));
  observer_state_map_[observer].requires_update = true;
}

void StorageObserverList::DispatchPendingEvent() {
  MaybeDispatchEvent(pending_event_);
}


// HostStorageObservers:

HostStorageObservers::HostStorageObservers(QuotaManager* quota_manager)
    : quota_manager_(quota_manager),
      initialized_(false),
      initializing_(false),
      event_occurred_before_init_(false),
      usage_deltas_during_init_(0),
      cached_usage_(0),
      cached_quota_(0),
      weak_factory_(this) {
}

HostStorageObservers::~HostStorageObservers() = default;

void HostStorageObservers::AddObserver(
    StorageObserver* observer,
    const StorageObserver::MonitorParams& params) {
  observers_.AddObserver(observer, params);

  if (!params.dispatch_initial_state)
    return;

  if (initialized_) {
    StorageObserver::Event event(params.filter,
                                 std::max<int64_t>(cached_usage_, 0),
                                 std::max<int64_t>(cached_quota_, 0));
    observer->OnStorageEvent(event);
    return;
  }

  // Ensure the observer receives the initial storage state once initialization
  // is complete.
  observers_.ScheduleUpdateForObserver(observer);
  StartInitialization(params.filter);
}

void HostStorageObservers::RemoveObserver(StorageObserver* observer) {
  observers_.RemoveObserver(observer);
}

bool HostStorageObservers::ContainsObservers() const {
  return observers_.ObserverCount() > 0;
}

void HostStorageObservers::NotifyUsageChange(
    const StorageObserver::Filter& filter,
    int64_t delta) {
  if (initialized_) {
    cached_usage_ += delta;
    DispatchEvent(filter, true);
    return;
  }

  // If a storage change occurs before initialization, ensure all observers will
  // receive an event once initialization is complete.
  event_occurred_before_init_ = true;

  // During QuotaManager::GetUsageAndQuotaForWebApps(), cached data is read
  // synchronously, but other data may be retrieved asynchronously. A usage
  // change may occur between the function call and callback. These deltas need
  // to be added to the usage received by GotHostUsageAndQuota() to ensure
  // |cached_usage_| is correctly initialized.
  if (initializing_) {
    usage_deltas_during_init_ += delta;
    return;
  }

  StartInitialization(filter);
}

void HostStorageObservers::StartInitialization(
    const StorageObserver::Filter& filter) {
  if (initialized_ || initializing_)
    return;
  // crbug.com/349708
  TRACE_EVENT0("io", "HostStorageObservers::StartInitialization");

  initializing_ = true;
  quota_manager_->GetUsageAndQuotaForWebApps(
      filter.origin, filter.storage_type,
      base::BindOnce(&HostStorageObservers::GotHostUsageAndQuota,
                     weak_factory_.GetWeakPtr(), filter));
}

void HostStorageObservers::GotHostUsageAndQuota(
    const StorageObserver::Filter& filter,
    blink::mojom::QuotaStatusCode status,
    int64_t usage,
    int64_t quota) {
  initializing_ = false;
  if (status != blink::mojom::QuotaStatusCode::kOk)
    return;
  initialized_ = true;
  cached_quota_ = quota;
  cached_usage_ = usage + usage_deltas_during_init_;
  DispatchEvent(filter, event_occurred_before_init_);
}

void HostStorageObservers::DispatchEvent(
    const StorageObserver::Filter& filter, bool is_update) {
  StorageObserver::Event event(filter, std::max<int64_t>(cached_usage_, 0),
                               std::max<int64_t>(cached_quota_, 0));
  if (is_update)
    observers_.OnStorageChange(event);
  else
    observers_.MaybeDispatchEvent(event);
}


// StorageTypeObservers:

StorageTypeObservers::StorageTypeObservers(QuotaManager* quota_manager)
    : quota_manager_(quota_manager) {
}

StorageTypeObservers::~StorageTypeObservers() = default;

void StorageTypeObservers::AddObserver(
    StorageObserver* observer, const StorageObserver::MonitorParams& params) {
  std::string host = net::GetHostOrSpecFromURL(params.filter.origin.GetURL());
  if (host.empty())
    return;

  auto& host_observers = host_observers_map_[host];
  if (!host_observers) {
    // Because there are no null entries in host_observers_map_, the [] inserted
    // a blank pointer, so let's populate it.
    host_observers = std::make_unique<HostStorageObservers>(quota_manager_);
  }

  host_observers->AddObserver(observer, params);
}

void StorageTypeObservers::RemoveObserver(StorageObserver* observer) {
  for (auto it = host_observers_map_.begin();
       it != host_observers_map_.end();) {
    it->second->RemoveObserver(observer);
    if (!it->second->ContainsObservers()) {
      it = host_observers_map_.erase(it);
    } else {
      ++it;
    }
  }
}

const HostStorageObservers* StorageTypeObservers::GetHostObservers(
    const std::string& host) const {
  auto it = host_observers_map_.find(host);
  if (it != host_observers_map_.end())
    return it->second.get();

  return nullptr;
}

void StorageTypeObservers::NotifyUsageChange(
    const StorageObserver::Filter& filter,
    int64_t delta) {
  std::string host = net::GetHostOrSpecFromURL(filter.origin.GetURL());
  auto it = host_observers_map_.find(host);
  if (it == host_observers_map_.end())
    return;

  it->second->NotifyUsageChange(filter, delta);
}


// StorageMonitor:

StorageMonitor::StorageMonitor(QuotaManager* quota_manager)
    : quota_manager_(quota_manager) {
}

StorageMonitor::~StorageMonitor() = default;

void StorageMonitor::AddObserver(
    StorageObserver* observer, const StorageObserver::MonitorParams& params) {
  DCHECK(observer);

  // Check preconditions.
  if (params.filter.storage_type == blink::mojom::StorageType::kUnknown ||
      params.filter.storage_type ==
          blink::mojom::StorageType::kQuotaNotManaged) {
    NOTREACHED();
    return;
  }

  auto& type_observers =
      storage_type_observers_map_[params.filter.storage_type];
  if (!type_observers)
    type_observers = std::make_unique<StorageTypeObservers>(quota_manager_);

  type_observers->AddObserver(observer, params);
}

void StorageMonitor::RemoveObserver(StorageObserver* observer) {
  for (const auto& type_observers_pair : storage_type_observers_map_)
    type_observers_pair.second->RemoveObserver(observer);
}

const StorageTypeObservers* StorageMonitor::GetStorageTypeObservers(
    blink::mojom::StorageType storage_type) const {
  auto it = storage_type_observers_map_.find(storage_type);
  if (it != storage_type_observers_map_.end())
    return it->second.get();

  return nullptr;
}

void StorageMonitor::NotifyUsageChange(const StorageObserver::Filter& filter,
                                       int64_t delta) {
  // Check preconditions.
  if (filter.storage_type == blink::mojom::StorageType::kUnknown ||
      filter.storage_type == blink::mojom::StorageType::kQuotaNotManaged) {
    NOTREACHED();
    return;
  }

  auto it = storage_type_observers_map_.find(filter.storage_type);
  if (it == storage_type_observers_map_.end())
    return;

  it->second->NotifyUsageChange(filter, delta);
}

}  // namespace storage
