// Copyright (c) 2012 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/renderer/dom_storage/dom_storage_dispatcher.h"

#include <list>
#include <map>

#include "base/strings/string_number_conversions.h"
#include "base/synchronization/lock.h"
#include "content/common/dom_storage/dom_storage_messages.h"
#include "content/common/dom_storage/dom_storage_types.h"
#include "content/renderer/dom_storage/dom_storage_cached_area.h"
#include "content/renderer/dom_storage/dom_storage_proxy.h"
#include "content/renderer/dom_storage/webstoragearea_impl.h"
#include "content/renderer/dom_storage/webstoragenamespace_impl.h"
#include "content/renderer/render_thread_impl.h"
#include "ipc/message_filter.h"
#include "third_party/WebKit/public/platform/Platform.h"
#include "third_party/WebKit/public/web/WebKit.h"
#include "third_party/WebKit/public/web/WebStorageEventDispatcher.h"

namespace content {

namespace {
// MessageThrottlingFilter -------------------------------------------
// Used to limit the number of ipc messages pending completion so we
// don't overwhelm the main browser process. When the limit is reached,
// a synchronous message is sent to flush all pending messages thru.
// We expect to receive an 'ack' for each message sent. This object
// observes receipt of the acks on the IPC thread to decrement a counter.
class MessageThrottlingFilter : public IPC::MessageFilter {
 public:
  explicit MessageThrottlingFilter(RenderThreadImpl* sender)
      : pending_count_(0), sender_(sender) {}

  void SendThrottled(IPC::Message* message);
  void Shutdown() { sender_ = nullptr; }

 private:
  ~MessageThrottlingFilter() override {}

  bool OnMessageReceived(const IPC::Message& message) override;

  int GetPendingCount() { return IncrementPendingCountN(0); }
  int IncrementPendingCount() { return IncrementPendingCountN(1); }
  int DecrementPendingCount() { return IncrementPendingCountN(-1); }
  int IncrementPendingCountN(int increment) {
    base::AutoLock locker(lock_);
    pending_count_ += increment;
    return pending_count_;
  }

  base::Lock lock_;
  int pending_count_;
  RenderThreadImpl* sender_;
};

void MessageThrottlingFilter::SendThrottled(IPC::Message* message) {
  // Should only be used for sending of messages which will be acknowledged
  // with a separate DOMStorageMsg_AsyncOperationComplete message.
  DCHECK(message->type() == DOMStorageHostMsg_LoadStorageArea::ID ||
         message->type() == DOMStorageHostMsg_SetItem::ID ||
         message->type() == DOMStorageHostMsg_RemoveItem::ID ||
         message->type() == DOMStorageHostMsg_Clear::ID);
  DCHECK(sender_);
  if (!sender_) {
    delete message;
    return;
  }
  const int kMaxPendingMessages = 1000;
  bool need_to_flush = (IncrementPendingCount() > kMaxPendingMessages) &&
                       !message->is_sync();
  sender_->Send(message);
  if (need_to_flush) {
    sender_->Send(new DOMStorageHostMsg_FlushMessages);
    DCHECK_EQ(0, GetPendingCount());
  } else {
    DCHECK_LE(0, GetPendingCount());
  }
}

bool MessageThrottlingFilter::OnMessageReceived(const IPC::Message& message) {
  if (message.type() == DOMStorageMsg_AsyncOperationComplete::ID) {
    DecrementPendingCount();
    DCHECK_LE(0, GetPendingCount());
  }
  return false;
}
}  // namespace

// ProxyImpl -----------------------------------------------------
// An implementation of the DOMStorageProxy interface in terms of IPC.
// This class also manages the collection of cached areas and pending
// operations awaiting completion callbacks.
class DomStorageDispatcher::ProxyImpl : public DOMStorageProxy {
 public:
  explicit ProxyImpl(RenderThreadImpl* sender);

  // Methods for use by DomStorageDispatcher directly.
  DOMStorageCachedArea* OpenCachedArea(const std::string& namespace_id,
                                       const GURL& origin);
  void CloseCachedArea(DOMStorageCachedArea* area);
  DOMStorageCachedArea* LookupCachedArea(const std::string& namespace_id,
                                         const GURL& origin);
  void CompleteOnePendingCallback(bool success);
  void Shutdown();

  // DOMStorageProxy interface for use by DOMStorageCachedArea.
  void LoadArea(int connection_id,
                DOMStorageValuesMap* values,
                CompletionCallback callback) override;
  void SetItem(int connection_id,
               const base::string16& key,
               const base::string16& value,
               const base::NullableString16& old_value,
               const GURL& page_url,
               CompletionCallback callback) override;
  void RemoveItem(int connection_id,
                  const base::string16& key,
                  const base::NullableString16& old_value,
                  const GURL& page_url,
                  CompletionCallback callback) override;
  void ClearArea(int connection_id,
                 const GURL& page_url,
                 CompletionCallback callback) override;

 private:
  // Struct to hold references to our contained areas and
  // to keep track of how many tabs have a given area open.
  struct CachedAreaHolder {
    scoped_refptr<DOMStorageCachedArea> area_;
    int open_count_;
    CachedAreaHolder() : open_count_(0) {}
    CachedAreaHolder(DOMStorageCachedArea* area, int count)
        : area_(area), open_count_(count) {}
  };
  typedef std::map<std::string, CachedAreaHolder> CachedAreaMap;
  typedef std::list<CompletionCallback> CallbackList;

  ~ProxyImpl() override {}

  void PushPendingCallback(CompletionCallback callback) {
    // Terminate the renderer if an excessive number of calls are made,
    // This is indicative of script in an infinite loop or being malicious.
    // It's better to crash intentionally than by running the system OOM
    // and interfering with everything else running in the system.
    const int kMaxPendingCompletionCallbacks = 1000000;
    if (pending_callbacks_.size() > kMaxPendingCompletionCallbacks)
      CHECK(false) << "Too many pending DOMStorage calls.";

    // Sudden termination is disabled when there are callbacks pending
    // to more reliably commit changes during shutdown.
    if (pending_callbacks_.empty())
      blink::Platform::Current()->SuddenTerminationChanged(false);
    pending_callbacks_.push_back(std::move(callback));
  }

  CompletionCallback PopPendingCallback() {
    CompletionCallback callback = std::move(pending_callbacks_.front());
    pending_callbacks_.pop_front();
    if (pending_callbacks_.empty())
      blink::Platform::Current()->SuddenTerminationChanged(true);
    return callback;
  }

  std::string GetCachedAreaKey(const std::string& namespace_id,
                               const GURL& origin) {
    return namespace_id + origin.spec();
  }

  CachedAreaHolder* GetAreaHolder(const std::string& key) {
    CachedAreaMap::iterator found = cached_areas_.find(key);
    if (found == cached_areas_.end())
      return nullptr;
    return &(found->second);
  }

  RenderThreadImpl* sender_;
  CachedAreaMap cached_areas_;
  CallbackList pending_callbacks_;
  scoped_refptr<MessageThrottlingFilter> throttling_filter_;
};

DomStorageDispatcher::ProxyImpl::ProxyImpl(RenderThreadImpl* sender)
    : sender_(sender),
      throttling_filter_(new MessageThrottlingFilter(sender)) {
  sender_->AddFilter(throttling_filter_.get());
}

DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::OpenCachedArea(
    const std::string& namespace_id,
    const GURL& origin) {
  std::string key = GetCachedAreaKey(namespace_id, origin);
  if (CachedAreaHolder* holder = GetAreaHolder(key)) {
    ++(holder->open_count_);
    return holder->area_.get();
  }
  scoped_refptr<DOMStorageCachedArea> area = new DOMStorageCachedArea(
      namespace_id, origin, this,
      content::RenderThreadImpl::current()->GetRendererScheduler());
  cached_areas_[key] = CachedAreaHolder(area.get(), 1);
  return area.get();
}

void DomStorageDispatcher::ProxyImpl::CloseCachedArea(
    DOMStorageCachedArea* area) {
  std::string key = GetCachedAreaKey(area->namespace_id(), area->origin());
  CachedAreaHolder* holder = GetAreaHolder(key);
  DCHECK(holder);
  DCHECK_EQ(holder->area_.get(), area);
  DCHECK_GT(holder->open_count_, 0);
  if (--(holder->open_count_) == 0) {
    cached_areas_.erase(key);
  }
}

DOMStorageCachedArea* DomStorageDispatcher::ProxyImpl::LookupCachedArea(
    const std::string& namespace_id,
    const GURL& origin) {
  std::string key = GetCachedAreaKey(namespace_id, origin);
  CachedAreaHolder* holder = GetAreaHolder(key);
  if (!holder)
    return nullptr;
  return holder->area_.get();
}

void DomStorageDispatcher::ProxyImpl::CompleteOnePendingCallback(bool success) {
  PopPendingCallback().Run(success);
}

void DomStorageDispatcher::ProxyImpl::Shutdown() {
  throttling_filter_->Shutdown();
  sender_->RemoveFilter(throttling_filter_.get());
  sender_ = nullptr;
  cached_areas_.clear();
  pending_callbacks_.clear();
}

void DomStorageDispatcher::ProxyImpl::LoadArea(int connection_id,
                                               DOMStorageValuesMap* values,
                                               CompletionCallback callback) {
  PushPendingCallback(std::move(callback));
  throttling_filter_->SendThrottled(new DOMStorageHostMsg_LoadStorageArea(
      connection_id, values));
}

void DomStorageDispatcher::ProxyImpl::SetItem(
    int connection_id,
    const base::string16& key,
    const base::string16& value,
    const base::NullableString16& old_value,
    const GURL& page_url,
    CompletionCallback callback) {
  PushPendingCallback(std::move(callback));
  throttling_filter_->SendThrottled(new DOMStorageHostMsg_SetItem(
      connection_id, key, value, old_value, page_url));
}

void DomStorageDispatcher::ProxyImpl::RemoveItem(
    int connection_id,
    const base::string16& key,
    const base::NullableString16& old_value,
    const GURL& page_url,
    CompletionCallback callback) {
  PushPendingCallback(std::move(callback));
  throttling_filter_->SendThrottled(new DOMStorageHostMsg_RemoveItem(
      connection_id, key, old_value, page_url));
}

void DomStorageDispatcher::ProxyImpl::ClearArea(int connection_id,
                                                const GURL& page_url,
                                                CompletionCallback callback) {
  PushPendingCallback(std::move(callback));
  throttling_filter_->SendThrottled(new DOMStorageHostMsg_Clear(
      connection_id, page_url));
}

// DomStorageDispatcher ------------------------------------------------

DomStorageDispatcher::DomStorageDispatcher()
    : proxy_(new ProxyImpl(RenderThreadImpl::current())) {
}

DomStorageDispatcher::~DomStorageDispatcher() {
  proxy_->Shutdown();
}

scoped_refptr<DOMStorageCachedArea> DomStorageDispatcher::OpenCachedArea(
    int connection_id,
    const std::string& namespace_id,
    const GURL& origin) {
  RenderThreadImpl::current()->Send(
      new DOMStorageHostMsg_OpenStorageArea(
          connection_id, namespace_id, origin));
  return proxy_->OpenCachedArea(namespace_id, origin);
}

void DomStorageDispatcher::CloseCachedArea(
    int connection_id, DOMStorageCachedArea* area) {
  RenderThreadImpl::current()->Send(
      new DOMStorageHostMsg_CloseStorageArea(connection_id));
  proxy_->CloseCachedArea(area);
}

bool DomStorageDispatcher::OnMessageReceived(const IPC::Message& msg) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(DomStorageDispatcher, msg)
    IPC_MESSAGE_HANDLER(DOMStorageMsg_Event, OnStorageEvent)
    IPC_MESSAGE_HANDLER(DOMStorageMsg_AsyncOperationComplete,
                        OnAsyncOperationComplete)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void DomStorageDispatcher::OnStorageEvent(
    const DOMStorageMsg_Event_Params& params) {
  WebStorageAreaImpl* originating_area = nullptr;
  if (params.connection_id) {
    originating_area = WebStorageAreaImpl::FromConnectionId(
        params.connection_id);
  } else {
    DOMStorageCachedArea* cached_area = proxy_->LookupCachedArea(
        params.namespace_id, params.origin);
    if (cached_area)
      cached_area->ApplyMutation(params.key, params.new_value);
  }

  DCHECK(!params.namespace_id.empty());
  WebStorageNamespaceImpl session_namespace_for_event_dispatch(
      params.namespace_id);
  blink::WebStorageEventDispatcher::DispatchSessionStorageEvent(
      blink::WebString::FromUTF16(params.key),
      blink::WebString::FromUTF16(params.old_value),
      blink::WebString::FromUTF16(params.new_value), params.origin,
      params.page_url, session_namespace_for_event_dispatch, originating_area);
}

void DomStorageDispatcher::OnAsyncOperationComplete(bool success) {
  proxy_->CompleteOnePendingCallback(success);
}

}  // namespace content
