// 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/browser/appcache/appcache_dispatcher_host.h"

#include <map>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "content/browser/appcache/appcache_navigation_handle_core.h"
#include "content/browser/appcache/chrome_appcache_service.h"
#include "content/browser/bad_message.h"
#include "content/public/browser/render_process_host.h"

namespace content {

AppCacheDispatcherHost::AppCacheDispatcherHost(
    ChromeAppCacheService* appcache_service,
    int process_id)
    : appcache_service_(appcache_service),
      frontend_proxy_(process_id),
      weak_factory_(this) {
  if (appcache_service) {
    backend_impl_.Initialize(appcache_service, &frontend_proxy_, process_id);
  }
}

AppCacheDispatcherHost::~AppCacheDispatcherHost() = default;

// static
void AppCacheDispatcherHost::Create(ChromeAppCacheService* appcache_service,
                                    int process_id,
                                    mojom::AppCacheBackendRequest request) {
  // The process_id is the id of the RenderProcessHost, which can be reused for
  // a new renderer process if the previous renderer process was shutdown.
  // It can take some time after shutdown for the pipe error to propagate
  // and unregister the previous backend. Since the AppCacheService assumes
  // that there is one backend per process_id, we need to ensure that the
  // previous backend is unregistered by eagerly unbinding the pipe.
  appcache_service->Unbind(process_id);

  appcache_service->Bind(
      std::make_unique<AppCacheDispatcherHost>(appcache_service, process_id),
      std::move(request), process_id);
}

void AppCacheDispatcherHost::RegisterHost(int32_t host_id) {
  if (appcache_service_) {
    // The AppCacheHost could have been precreated in which case we want to
    // register it with the backend here.
    std::unique_ptr<content::AppCacheHost> host =
        AppCacheNavigationHandleCore::GetPrecreatedHost(host_id);
    if (host.get()) {
      backend_impl_.RegisterPrecreatedHost(std::move(host));
      return;
    }

    if (!backend_impl_.RegisterHost(host_id)) {
      mojo::ReportBadMessage("ACDH_REGISTER");
    }
  }
}

void AppCacheDispatcherHost::UnregisterHost(int32_t host_id) {
  if (appcache_service_) {
    if (!backend_impl_.UnregisterHost(host_id)) {
      mojo::ReportBadMessage("ACDH_UNREGISTER");
    }
  }
}

void AppCacheDispatcherHost::SetSpawningHostId(int32_t host_id,
                                               int spawning_host_id) {
  if (appcache_service_) {
    if (!backend_impl_.SetSpawningHostId(host_id, spawning_host_id))
      mojo::ReportBadMessage("ACDH_SET_SPAWNING");
  }
}

void AppCacheDispatcherHost::SelectCache(int32_t host_id,
                                         const GURL& document_url,
                                         int64_t cache_document_was_loaded_from,
                                         const GURL& opt_manifest_url) {
  if (appcache_service_) {
    if (!backend_impl_.SelectCache(host_id, document_url,
                                   cache_document_was_loaded_from,
                                   opt_manifest_url)) {
      mojo::ReportBadMessage("ACDH_SELECT_CACHE");
    }
  } else {
    frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
  }
}

void AppCacheDispatcherHost::SelectCacheForSharedWorker(int32_t host_id,
                                                        int64_t appcache_id) {
  if (appcache_service_) {
    if (!backend_impl_.SelectCacheForSharedWorker(host_id, appcache_id))
      mojo::ReportBadMessage("ACDH_SELECT_CACHE_FOR_SHARED_WORKER");
  } else {
    frontend_proxy_.OnCacheSelected(host_id, AppCacheInfo());
  }
}

void AppCacheDispatcherHost::MarkAsForeignEntry(
    int32_t host_id,
    const GURL& document_url,
    int64_t cache_document_was_loaded_from) {
  if (appcache_service_) {
    if (!backend_impl_.MarkAsForeignEntry(host_id, document_url,
                                          cache_document_was_loaded_from)) {
      mojo::ReportBadMessage("ACDH_MARK_AS_FOREIGN_ENTRY");
    }
  }
}

void AppCacheDispatcherHost::GetResourceList(int32_t host_id,
                                             GetResourceListCallback callback) {
  std::vector<AppCacheResourceInfo> params;
  std::vector<mojom::AppCacheResourceInfoPtr> out;
  if (appcache_service_) {
    backend_impl_.GetResourceList(host_id, &params);

    // Box up params for output.
    out.reserve(params.size());
    for (auto& p : params) {
      out.emplace_back(base::in_place, std::move(p));
    }
  }
  std::move(callback).Run(std::move(out));
}

void AppCacheDispatcherHost::GetStatus(int32_t host_id,
                                       GetStatusCallback callback) {
  if (appcache_service_) {
    if (backend_impl_.GetStatusWithCallback(host_id, &callback)) {
      return;
    } else {
      mojo::ReportBadMessage("ACDH_GET_STATUS");
    }
  }
  std::move(callback).Run(AppCacheStatus::APPCACHE_STATUS_UNCACHED);
}

void AppCacheDispatcherHost::StartUpdate(int32_t host_id,
                                         StartUpdateCallback callback) {
  if (appcache_service_) {
    if (backend_impl_.StartUpdateWithCallback(host_id, &callback)) {
      return;
    } else {
      mojo::ReportBadMessage("ACDH_START_UPDATE");
    }
  }
  std::move(callback).Run(false);
}

void AppCacheDispatcherHost::SwapCache(int32_t host_id,
                                       SwapCacheCallback callback) {
  if (appcache_service_) {
    if (backend_impl_.SwapCacheWithCallback(host_id, &callback)) {
      return;
    } else {
      mojo::ReportBadMessage("ACDH_SWAP_CACHE");
    }
  }
  std::move(callback).Run(false);
}

}  // namespace content
