// Copyright (c) 2011 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 "webkit/tools/test_shell/simple_appcache_system.h"

#include <string>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/synchronization/waitable_event.h"
#include "webkit/appcache/appcache_interceptor.h"
#include "webkit/appcache/web_application_cache_host_impl.h"
#include "webkit/tools/test_shell/simple_resource_loader_bridge.h"

using WebKit::WebApplicationCacheHost;
using WebKit::WebApplicationCacheHostClient;
using appcache::WebApplicationCacheHostImpl;
using appcache::AppCacheBackendImpl;
using appcache::AppCacheInterceptor;

// SimpleFrontendProxy --------------------------------------------------------
// Proxies method calls from the backend IO thread to the frontend UI thread.

class SimpleFrontendProxy
    : public base::RefCountedThreadSafe<SimpleFrontendProxy>,
      public appcache::AppCacheFrontend {
 public:
  explicit SimpleFrontendProxy(SimpleAppCacheSystem* appcache_system)
      : system_(appcache_system) {
  }

  void clear_appcache_system() { system_ = NULL; }

  virtual void OnCacheSelected(int host_id,
      const appcache::AppCacheInfo& info) {
    if (!system_)
      return;
    if (system_->is_io_thread()) {
      system_->ui_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleFrontendProxy::OnCacheSelected, this, host_id,
                     info));
    } else if (system_->is_ui_thread()) {
      system_->frontend_impl_.OnCacheSelected(host_id, info);
    } else {
      NOTREACHED();
    }
  }

  virtual void OnStatusChanged(const std::vector<int>& host_ids,
                               appcache::Status status) {
    if (!system_)
      return;
    if (system_->is_io_thread())
      system_->ui_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleFrontendProxy::OnStatusChanged, this, host_ids,
                     status));
    else if (system_->is_ui_thread())
      system_->frontend_impl_.OnStatusChanged(host_ids, status);
    else
      NOTREACHED();
  }

  virtual void OnEventRaised(const std::vector<int>& host_ids,
                             appcache::EventID event_id) {
    if (!system_)
      return;
    if (system_->is_io_thread())
      system_->ui_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleFrontendProxy::OnEventRaised, this, host_ids,
                     event_id));
    else if (system_->is_ui_thread())
      system_->frontend_impl_.OnEventRaised(host_ids, event_id);
    else
      NOTREACHED();
  }

  virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
                                     const GURL& url,
                                     int num_total, int num_complete) {
    if (!system_)
      return;
    if (system_->is_io_thread())
      system_->ui_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleFrontendProxy::OnProgressEventRaised, this,
                     host_ids, url, num_total, num_complete));
    else if (system_->is_ui_thread())
      system_->frontend_impl_.OnProgressEventRaised(
          host_ids, url, num_total, num_complete);
    else
      NOTREACHED();
  }

  virtual void OnErrorEventRaised(const std::vector<int>& host_ids,
                                  const std::string& message) {
    if (!system_)
      return;
    if (system_->is_io_thread())
      system_->ui_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleFrontendProxy::OnErrorEventRaised, this, host_ids,
                     message));
    else if (system_->is_ui_thread())
      system_->frontend_impl_.OnErrorEventRaised(
          host_ids, message);
    else
      NOTREACHED();
  }

  virtual void OnLogMessage(int host_id,
                            appcache::LogLevel log_level,
                            const std::string& message) {
    if (!system_)
      return;
    if (system_->is_io_thread())
      system_->ui_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleFrontendProxy::OnLogMessage, this, host_id,
                     log_level, message));
    else if (system_->is_ui_thread())
      system_->frontend_impl_.OnLogMessage(
          host_id, log_level, message);
    else
      NOTREACHED();
  }

  virtual void OnContentBlocked(int host_id, const GURL& manifest_url) {}

 private:
  friend class base::RefCountedThreadSafe<SimpleFrontendProxy>;

  ~SimpleFrontendProxy() {}

  SimpleAppCacheSystem* system_;
};


// SimpleBackendProxy --------------------------------------------------------
// Proxies method calls from the frontend UI thread to the backend IO thread.

class SimpleBackendProxy
    : public base::RefCountedThreadSafe<SimpleBackendProxy>,
      public appcache::AppCacheBackend {
 public:
  explicit SimpleBackendProxy(SimpleAppCacheSystem* appcache_system)
      : system_(appcache_system), event_(true, false) {
    get_status_callback_ =
        base::Bind(&SimpleBackendProxy::GetStatusCallback,
                   base::Unretained(this));
    start_update_callback_ =
        base::Bind(&SimpleBackendProxy::StartUpdateCallback,
                   base::Unretained(this));
    swap_cache_callback_=
        base::Bind(&SimpleBackendProxy::SwapCacheCallback,
                   base::Unretained(this));
  }

  virtual void RegisterHost(int host_id) {
    if (system_->is_ui_thread()) {
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleBackendProxy::RegisterHost, this, host_id));
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->RegisterHost(host_id);
    } else {
      NOTREACHED();
    }
  }

  virtual void UnregisterHost(int host_id) {
    if (system_->is_ui_thread()) {
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleBackendProxy::UnregisterHost, this, host_id));
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->UnregisterHost(host_id);
    } else {
      NOTREACHED();
    }
  }

  virtual void SetSpawningHostId(int host_id, int spawning_host_id) {
    if (system_->is_ui_thread()) {
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleBackendProxy::SetSpawningHostId, this, host_id,
                     spawning_host_id));
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->SetSpawningHostId(host_id, spawning_host_id);
    } else {
      NOTREACHED();
    }
  }

  virtual void SelectCache(int host_id,
                           const GURL& document_url,
                           const int64 cache_document_was_loaded_from,
                           const GURL& manifest_url) {
    if (system_->is_ui_thread()) {
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleBackendProxy::SelectCache, this, host_id,
                     document_url, cache_document_was_loaded_from,
                     manifest_url));
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->SelectCache(host_id, document_url,
                                          cache_document_was_loaded_from,
                                          manifest_url);
    } else {
      NOTREACHED();
    }
  }

  virtual void GetResourceList(
      int host_id,
      std::vector<appcache::AppCacheResourceInfo>* resource_infos) {
    if (system_->is_ui_thread()) {
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleBackendProxy::GetResourceList, this, host_id,
                     resource_infos));
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->GetResourceList(host_id, resource_infos);
    } else {
      NOTREACHED();
    }
  }

  virtual void SelectCacheForWorker(
                           int host_id,
                           int parent_process_id,
                           int parent_host_id) {
    NOTIMPLEMENTED();  // Workers are not supported in test_shell.
  }

  virtual void SelectCacheForSharedWorker(
                           int host_id,
                           int64 appcache_id) {
    NOTIMPLEMENTED();  // Workers are not supported in test_shell.
  }

  virtual void MarkAsForeignEntry(int host_id, const GURL& document_url,
                                  int64 cache_document_was_loaded_from) {
    if (system_->is_ui_thread()) {
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(&SimpleBackendProxy::MarkAsForeignEntry, this, host_id,
                     document_url, cache_document_was_loaded_from));
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->MarkAsForeignEntry(
                                  host_id, document_url,
                                  cache_document_was_loaded_from);
    } else {
      NOTREACHED();
    }
  }

  virtual appcache::Status GetStatus(int host_id) {
    if (system_->is_ui_thread()) {
      status_result_ = appcache::UNCACHED;
      event_.Reset();
      system_->io_message_loop()->PostTask(
          FROM_HERE,
              base::Bind(base::IgnoreResult(&SimpleBackendProxy::GetStatus),
                         this, host_id));
      event_.Wait();
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->GetStatusWithCallback(
          host_id, get_status_callback_, NULL);
    } else {
      NOTREACHED();
    }
    return status_result_;
  }

  virtual bool StartUpdate(int host_id) {
    if (system_->is_ui_thread()) {
      bool_result_ = false;
      event_.Reset();
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(base::IgnoreResult(&SimpleBackendProxy::StartUpdate),
                     this, host_id));
      event_.Wait();
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->StartUpdateWithCallback(
          host_id, start_update_callback_, NULL);
    } else {
      NOTREACHED();
    }
    return bool_result_;
  }

  virtual bool SwapCache(int host_id) {
    if (system_->is_ui_thread()) {
      bool_result_ = false;
      event_.Reset();
      system_->io_message_loop()->PostTask(
          FROM_HERE,
          base::Bind(base::IgnoreResult(&SimpleBackendProxy::SwapCache),
                     this, host_id));
      event_.Wait();
    } else if (system_->is_io_thread()) {
      system_->backend_impl_->SwapCacheWithCallback(
          host_id, swap_cache_callback_, NULL);
    } else {
      NOTREACHED();
    }
    return bool_result_;
  }

  void GetStatusCallback(appcache::Status status, void* param) {
    status_result_ = status;
    event_.Signal();
  }

  void StartUpdateCallback(bool result, void* param) {
    bool_result_ = result;
    event_.Signal();
  }

  void SwapCacheCallback(bool result, void* param) {
    bool_result_ = result;
    event_.Signal();
  }

  void SignalEvent() {
    event_.Signal();
  }

 private:
  friend class base::RefCountedThreadSafe<SimpleBackendProxy>;

  ~SimpleBackendProxy() {}

  SimpleAppCacheSystem* system_;
  base::WaitableEvent event_;
  bool bool_result_;
  appcache::Status status_result_;
  appcache::GetStatusCallback get_status_callback_;
  appcache::StartUpdateCallback start_update_callback_;
  appcache::SwapCacheCallback swap_cache_callback_;
};


// SimpleAppCacheSystem --------------------------------------------------------

// This class only works for a single process browser.
static const int kSingleProcessId = 1;

// A not so thread safe singleton, but should work for test_shell.
SimpleAppCacheSystem* SimpleAppCacheSystem::instance_ = NULL;

SimpleAppCacheSystem::SimpleAppCacheSystem()
    : io_message_loop_(NULL), ui_message_loop_(NULL),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          backend_proxy_(new SimpleBackendProxy(this))),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          frontend_proxy_(new SimpleFrontendProxy(this))),
      backend_impl_(NULL), service_(NULL), db_thread_("AppCacheDBThread") {
  DCHECK(!instance_);
  instance_ = this;
}

static void SignalEvent(base::WaitableEvent* event) {
  event->Signal();
}

SimpleAppCacheSystem::~SimpleAppCacheSystem() {
  DCHECK(!io_message_loop_ && !backend_impl_ && !service_);
  frontend_proxy_->clear_appcache_system();  // in case a task is in transit
  instance_ = NULL;

  if (db_thread_.IsRunning()) {
    // We pump a task thru the db thread to ensure any tasks previously
    // scheduled on that thread have been performed prior to return.
    base::WaitableEvent event(false, false);
    db_thread_.message_loop()->PostTask(
        FROM_HERE, base::Bind(&SignalEvent, &event));
    event.Wait();
  }
}

void SimpleAppCacheSystem::InitOnUIThread(const FilePath& cache_directory) {
  DCHECK(!ui_message_loop_);
  ui_message_loop_ = MessageLoop::current();
  cache_directory_ = cache_directory;
}

void SimpleAppCacheSystem::InitOnIOThread(
    net::URLRequestContext* request_context) {
  if (!is_initailized_on_ui_thread())
    return;

  DCHECK(!io_message_loop_);
  io_message_loop_ = MessageLoop::current();

  if (!db_thread_.IsRunning())
    db_thread_.Start();

  // Recreate and initialize per each IO thread.
  service_ = new appcache::AppCacheService(NULL);
  backend_impl_ = new appcache::AppCacheBackendImpl();
  service_->Initialize(cache_directory_,
                       db_thread_.message_loop_proxy(),
                       SimpleResourceLoaderBridge::GetCacheThread());
  service_->set_request_context(request_context);
  backend_impl_->Initialize(service_, frontend_proxy_.get(), kSingleProcessId);

  AppCacheInterceptor::EnsureRegistered();
}

void SimpleAppCacheSystem::CleanupIOThread() {
  DCHECK(is_io_thread());

  delete backend_impl_;
  delete service_;
  backend_impl_ = NULL;
  service_ = NULL;
  io_message_loop_ = NULL;

  // Just in case the main thread is waiting on it.
  backend_proxy_->SignalEvent();
}

WebApplicationCacheHost* SimpleAppCacheSystem::CreateCacheHostForWebKit(
    WebApplicationCacheHostClient* client) {
  if (!is_initailized_on_ui_thread())
    return NULL;

  DCHECK(is_ui_thread());

  // The IO thread needs to be running for this system to work.
  SimpleResourceLoaderBridge::EnsureIOThread();

  if (!is_initialized())
    return NULL;
  return new WebApplicationCacheHostImpl(client, backend_proxy_.get());
}

void SimpleAppCacheSystem::SetExtraRequestBits(
    net::URLRequest* request, int host_id, ResourceType::Type resource_type) {
  if (is_initialized()) {
    DCHECK(is_io_thread());
    AppCacheInterceptor::SetExtraRequestInfo(
        request, service_, kSingleProcessId, host_id, resource_type);
  }
}

void SimpleAppCacheSystem::GetExtraResponseBits(
    net::URLRequest* request, int64* cache_id, GURL* manifest_url) {
  if (is_initialized()) {
    DCHECK(is_io_thread());
    AppCacheInterceptor::GetExtraResponseInfo(
        request, cache_id, manifest_url);
  }
}
