// Copyright (c) 2009 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/appcache/web_application_cache_host_impl.h"

#include "base/compiler_specific.h"
#include "base/id_map.h"
#include "base/string_util.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURLRequest.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURLResponse.h"

using WebKit::WebApplicationCacheHost;
using WebKit::WebApplicationCacheHostClient;
using WebKit::WebURLRequest;
using WebKit::WebURL;
using WebKit::WebURLResponse;

namespace appcache {

static IDMap<WebApplicationCacheHostImpl> all_hosts;

WebApplicationCacheHostImpl* WebApplicationCacheHostImpl::FromId(int id) {
  return all_hosts.Lookup(id);
}

WebApplicationCacheHostImpl::WebApplicationCacheHostImpl(
    WebApplicationCacheHostClient* client,
    AppCacheBackend* backend)
    : client_(client),
      backend_(backend),
      ALLOW_THIS_IN_INITIALIZER_LIST(host_id_(all_hosts.Add(this))),
      has_status_(false),
      status_(UNCACHED),
      has_cached_status_(false),
      cached_status_(UNCACHED),
      is_scheme_supported_(false),
      is_get_method_(false),
      is_new_master_entry_(MAYBE) {
  DCHECK(client && backend && (host_id_ != kNoHostId));

  backend_->RegisterHost(host_id_);
}

WebApplicationCacheHostImpl::~WebApplicationCacheHostImpl() {
  backend_->UnregisterHost(host_id_);
  all_hosts.Remove(host_id_);
}

void WebApplicationCacheHostImpl::OnCacheSelected(int64 selected_cache_id,
                                                  appcache::Status status) {
  status_ = status;
  has_status_ = true;
}

void WebApplicationCacheHostImpl::OnStatusChanged(appcache::Status status) {
  if (has_status_)
    status_ = status;
}

void WebApplicationCacheHostImpl::OnEventRaised(appcache::EventID event_id) {
  // Most events change the status. Clear out what we know so that the latest
  // status will be obtained from the backend.
  if (PROGRESS_EVENT != event_id) {
    has_status_ = false;
    has_cached_status_ = false;
  }

  client_->notifyEventListener(static_cast<EventID>(event_id));
}

void WebApplicationCacheHostImpl::willStartMainResourceRequest(
    WebURLRequest& request) {
  request.setAppCacheHostID(host_id_);
  std::string method = request.httpMethod().utf8();
  is_get_method_ = (method == kHttpGETMethod);
  DCHECK(method == StringToUpperASCII(method));
}

void WebApplicationCacheHostImpl::willStartSubResourceRequest(
    WebURLRequest& request) {
  request.setAppCacheHostID(host_id_);
}

void WebApplicationCacheHostImpl::selectCacheWithoutManifest() {
  // Reset any previous status values we've received from the backend
  // since we're now selecting a new cache.
  has_status_ = false;
  has_cached_status_ = false;
  is_new_master_entry_ = NO;
  backend_->SelectCache(host_id_, document_url_,
                        document_response_.appCacheID(),
                        GURL());
}

bool WebApplicationCacheHostImpl::selectCacheWithManifest(
    const WebURL& manifest_url) {
  // Reset any previous status values we've received from the backend
  // since we're now selecting a new cache.
  has_status_ = false;
  has_cached_status_ = false;

  GURL manifest_gurl(manifest_url);
  if (manifest_gurl.has_ref()) {
    GURL::Replacements replacements;
    replacements.ClearRef();
    manifest_gurl = manifest_gurl.ReplaceComponents(replacements);
  }

  // 6.9.6 The application cache selection algorithm
  // Check for new 'master' entries.
  if (document_response_.appCacheID() == kNoCacheId) {
    if (is_scheme_supported_ && is_get_method_ &&
        (manifest_gurl.GetOrigin() == document_url_.GetOrigin())) {
      is_new_master_entry_ = YES;
    } else {
      is_new_master_entry_ = NO;
      manifest_gurl = GURL::EmptyGURL();
    }
    backend_->SelectCache(host_id_, document_url_,
                          kNoCacheId, manifest_gurl);
    return true;
  }

  DCHECK(is_new_master_entry_ = NO);

  // 6.9.6 The application cache selection algorithm
  // Check for 'foreign' entries.
  GURL document_manifest_gurl(document_response_.appCacheManifestURL());
  if (document_manifest_gurl != manifest_gurl) {
    backend_->MarkAsForeignEntry(host_id_, document_url_,
                                 document_response_.appCacheID());
    has_cached_status_ = true;
    cached_status_ = UNCACHED;
    return false;  // the navigation will be restarted
  }

  // Its a 'master' entry thats already in the cache.
  backend_->SelectCache(host_id_, document_url_,
                        document_response_.appCacheID(),
                        manifest_gurl);
  return true;
}

void WebApplicationCacheHostImpl::didReceiveResponseForMainResource(
    const WebURLResponse& response) {
  document_response_ = response;
  document_url_ = document_response_.url();
  if (document_url_.has_ref()) {
    GURL::Replacements replacements;
    replacements.ClearRef();
    document_url_ = document_url_.ReplaceComponents(replacements);
  }
  is_scheme_supported_ =  IsSchemeSupported(document_url_);
  if ((document_response_.appCacheID() != kNoCacheId) ||
      !is_scheme_supported_ || !is_get_method_)
    is_new_master_entry_ = NO;
}

void WebApplicationCacheHostImpl::didReceiveDataForMainResource(
    const char* data, int len) {
  if (is_new_master_entry_ == NO)
    return;
  // TODO(michaeln): write me
}

void WebApplicationCacheHostImpl::didFinishLoadingMainResource(bool success) {
  if (is_new_master_entry_ == NO)
    return;
  // TODO(michaeln): write me
}

WebApplicationCacheHost::Status WebApplicationCacheHostImpl::status() {
  // We're careful about the status value to avoid race conditions.
  //
  // Generally the webappcachehost sends an async stream of messages to the
  // backend, and receives an asyncronous stream of events from the backend.
  // In the backend, all operations are serialized and as state changes
  // 'events' are streamed out to relevant parties. In particular the
  // 'SelectCache' message is async. Regular page loading and navigation
  // involves two non-blocking ipc calls: RegisterHost + SelectCache.
  //
  // However, the page can call the scriptable API in advance of a cache
  // selection being complete (and/or in advance of the webappcachehost having
  // received the event about completion). In that case, we force an end-to-end
  // fetch of the 'status' value, and cache that value seperately from the
  // value we receive via the async event stream. We'll use that cached value
  // until cache selection is complete.
  if (has_status_)
    return static_cast<WebApplicationCacheHost::Status>(status_);

  if (!has_cached_status_) {
    cached_status_ = backend_->GetStatus(host_id_);
    has_cached_status_ = true;
  }
  return static_cast<WebApplicationCacheHost::Status>(cached_status_);
}

bool WebApplicationCacheHostImpl::startUpdate() {
  return backend_->StartUpdate(host_id_);
}

bool WebApplicationCacheHostImpl::swapCache() {
  // Cache status will change when cache is swapped. Clear out any saved idea
  // of status so that backend will be queried for actual status.
  has_status_ = false;
  has_cached_status_ = false;
  return backend_->SwapCache(host_id_);
}

}  // appcache namespace
