// 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 "base/bind.h"
#include "base/bind_helpers.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "content/browser/appcache/appcache.h"
#include "content/browser/appcache/appcache_backend_impl.h"
#include "content/browser/appcache/appcache_group.h"
#include "content/browser/appcache/appcache_host.h"
#include "content/browser/appcache/mock_appcache_policy.h"
#include "content/browser/appcache/mock_appcache_service.h"
#include "net/url_request/url_request.h"
#include "storage/browser/quota/quota_manager.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace content {

class AppCacheHostTest : public testing::Test {
 public:
  AppCacheHostTest() {
    get_status_callback_ =
        base::Bind(&AppCacheHostTest::GetStatusCallback,
                   base::Unretained(this));
    start_update_callback_ =
        base::Bind(&AppCacheHostTest::StartUpdateCallback,
                   base::Unretained(this));
    swap_cache_callback_ =
        base::Bind(&AppCacheHostTest::SwapCacheCallback,
                   base::Unretained(this));
  }

  class MockFrontend : public AppCacheFrontend {
   public:
    MockFrontend()
        : last_host_id_(-222), last_cache_id_(-222),
          last_status_(APPCACHE_STATUS_OBSOLETE),
          last_status_changed_(APPCACHE_STATUS_OBSOLETE),
          last_event_id_(APPCACHE_OBSOLETE_EVENT),
          content_blocked_(false) {
    }

    virtual void OnCacheSelected(
        int host_id, const AppCacheInfo& info) override {
      last_host_id_ = host_id;
      last_cache_id_ = info.cache_id;
      last_status_ = info.status;
    }

    virtual void OnStatusChanged(const std::vector<int>& host_ids,
                                 AppCacheStatus status) override {
      last_status_changed_ = status;
    }

    virtual void OnEventRaised(const std::vector<int>& host_ids,
                               AppCacheEventID event_id) override {
      last_event_id_ = event_id;
    }

    virtual void OnErrorEventRaised(
        const std::vector<int>& host_ids,
        const AppCacheErrorDetails& details) override {
      last_event_id_ = APPCACHE_ERROR_EVENT;
    }

    virtual void OnProgressEventRaised(const std::vector<int>& host_ids,
                                       const GURL& url,
                                       int num_total,
                                       int num_complete) override {
      last_event_id_ = APPCACHE_PROGRESS_EVENT;
    }

    virtual void OnLogMessage(int host_id,
                              AppCacheLogLevel log_level,
                              const std::string& message) override {
    }

    virtual void OnContentBlocked(int host_id,
                                  const GURL& manifest_url) override {
      content_blocked_ = true;
    }

    int last_host_id_;
    int64 last_cache_id_;
    AppCacheStatus last_status_;
    AppCacheStatus last_status_changed_;
    AppCacheEventID last_event_id_;
    bool content_blocked_;
  };

  class MockQuotaManagerProxy : public storage::QuotaManagerProxy {
   public:
    MockQuotaManagerProxy() : QuotaManagerProxy(NULL, NULL) {}

    // Not needed for our tests.
    virtual void RegisterClient(storage::QuotaClient* client) override {}
    virtual void NotifyStorageAccessed(storage::QuotaClient::ID client_id,
                                       const GURL& origin,
                                       storage::StorageType type) override {}
    virtual void NotifyStorageModified(storage::QuotaClient::ID client_id,
                                       const GURL& origin,
                                       storage::StorageType type,
                                       int64 delta) override {}
    virtual void SetUsageCacheEnabled(storage::QuotaClient::ID client_id,
                                      const GURL& origin,
                                      storage::StorageType type,
                                      bool enabled) override {}
    virtual void GetUsageAndQuota(
        base::SequencedTaskRunner* original_task_runner,
        const GURL& origin,
        storage::StorageType type,
        const GetUsageAndQuotaCallback& callback) override {}

    virtual void NotifyOriginInUse(const GURL& origin) override {
      inuse_[origin] += 1;
    }

    virtual void NotifyOriginNoLongerInUse(const GURL& origin) override {
      inuse_[origin] -= 1;
    }

    int GetInUseCount(const GURL& origin) {
      return inuse_[origin];
    }

    void reset() {
      inuse_.clear();
    }

    // Map from origin to count of inuse notifications.
    std::map<GURL, int> inuse_;

   protected:
    virtual ~MockQuotaManagerProxy() {}
  };

  void GetStatusCallback(AppCacheStatus status, void* param) {
    last_status_result_ = status;
    last_callback_param_ = param;
  }

  void StartUpdateCallback(bool result, void* param) {
    last_start_result_ = result;
    last_callback_param_ = param;
  }

  void SwapCacheCallback(bool result, void* param) {
    last_swap_result_ = result;
    last_callback_param_ = param;
  }

  base::MessageLoop message_loop_;

  // Mock classes for the 'host' to work with
  MockAppCacheService service_;
  MockFrontend mock_frontend_;

  // Mock callbacks we expect to receive from the 'host'
  content::GetStatusCallback get_status_callback_;
  content::StartUpdateCallback start_update_callback_;
  content::SwapCacheCallback swap_cache_callback_;

  AppCacheStatus last_status_result_;
  bool last_swap_result_;
  bool last_start_result_;
  void* last_callback_param_;
};

TEST_F(AppCacheHostTest, Basic) {
  // Construct a host and test what state it appears to be in.
  AppCacheHost host(1, &mock_frontend_, &service_);
  EXPECT_EQ(1, host.host_id());
  EXPECT_EQ(&service_, host.service());
  EXPECT_EQ(&mock_frontend_, host.frontend());
  EXPECT_EQ(NULL, host.associated_cache());
  EXPECT_FALSE(host.is_selection_pending());

  // See that the callbacks are delivered immediately
  // and respond as if there is no cache selected.
  last_status_result_ = APPCACHE_STATUS_OBSOLETE;
  host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_);
  EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);

  last_start_result_ = true;
  host.StartUpdateWithCallback(start_update_callback_,
                               reinterpret_cast<void*>(2));
  EXPECT_FALSE(last_start_result_);
  EXPECT_EQ(reinterpret_cast<void*>(2), last_callback_param_);

  last_swap_result_ = true;
  host.SwapCacheWithCallback(swap_cache_callback_, reinterpret_cast<void*>(3));
  EXPECT_FALSE(last_swap_result_);
  EXPECT_EQ(reinterpret_cast<void*>(3), last_callback_param_);
}

TEST_F(AppCacheHostTest, SelectNoCache) {
  scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
      new MockQuotaManagerProxy);
  service_.set_quota_manager_proxy(mock_quota_proxy.get());

  // Reset our mock frontend
  mock_frontend_.last_cache_id_ = -333;
  mock_frontend_.last_host_id_ = -333;
  mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE;

  const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
  {
    AppCacheHost host(1, &mock_frontend_, &service_);
    host.SelectCache(kDocAndOriginUrl, kAppCacheNoCacheId, GURL());
    EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));

    // We should have received an OnCacheSelected msg
    EXPECT_EQ(1, mock_frontend_.last_host_id_);
    EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
    EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

    // Otherwise, see that it respond as if there is no cache selected.
    EXPECT_EQ(1, host.host_id());
    EXPECT_EQ(&service_, host.service());
    EXPECT_EQ(&mock_frontend_, host.frontend());
    EXPECT_EQ(NULL, host.associated_cache());
    EXPECT_FALSE(host.is_selection_pending());
    EXPECT_TRUE(host.preferred_manifest_url().is_empty());
  }
  EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
  service_.set_quota_manager_proxy(NULL);
}

TEST_F(AppCacheHostTest, ForeignEntry) {
  // Reset our mock frontend
  mock_frontend_.last_cache_id_ = -333;
  mock_frontend_.last_host_id_ = -333;
  mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE;

  // Precondition, a cache with an entry that is not marked as foreign.
  const int kCacheId = 22;
  const GURL kDocumentURL("http://origin/document");
  scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
  cache->AddEntry(kDocumentURL, AppCacheEntry(AppCacheEntry::EXPLICIT));

  AppCacheHost host(1, &mock_frontend_, &service_);
  host.MarkAsForeignEntry(kDocumentURL, kCacheId);

  // We should have received an OnCacheSelected msg for kAppCacheNoCacheId.
  EXPECT_EQ(1, mock_frontend_.last_host_id_);
  EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

  // See that it respond as if there is no cache selected.
  EXPECT_EQ(1, host.host_id());
  EXPECT_EQ(&service_, host.service());
  EXPECT_EQ(&mock_frontend_, host.frontend());
  EXPECT_EQ(NULL, host.associated_cache());
  EXPECT_FALSE(host.is_selection_pending());

  // See that the entry was marked as foreign.
  EXPECT_TRUE(cache->GetEntry(kDocumentURL)->IsForeign());
}

TEST_F(AppCacheHostTest, ForeignFallbackEntry) {
  // Reset our mock frontend
  mock_frontend_.last_cache_id_ = -333;
  mock_frontend_.last_host_id_ = -333;
  mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE;

  // Precondition, a cache with a fallback entry that is not marked as foreign.
  const int kCacheId = 22;
  const GURL kFallbackURL("http://origin/fallback_resource");
  scoped_refptr<AppCache> cache = new AppCache(service_.storage(), kCacheId);
  cache->AddEntry(kFallbackURL, AppCacheEntry(AppCacheEntry::FALLBACK));

  AppCacheHost host(1, &mock_frontend_, &service_);
  host.NotifyMainResourceIsNamespaceEntry(kFallbackURL);
  host.MarkAsForeignEntry(GURL("http://origin/missing_document"), kCacheId);

  // We should have received an OnCacheSelected msg for kAppCacheNoCacheId.
  EXPECT_EQ(1, mock_frontend_.last_host_id_);
  EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

  // See that the fallback entry was marked as foreign.
  EXPECT_TRUE(cache->GetEntry(kFallbackURL)->IsForeign());
}

TEST_F(AppCacheHostTest, FailedCacheLoad) {
  // Reset our mock frontend
  mock_frontend_.last_cache_id_ = -333;
  mock_frontend_.last_host_id_ = -333;
  mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE;

  AppCacheHost host(1, &mock_frontend_, &service_);
  EXPECT_FALSE(host.is_selection_pending());

  const int kMockCacheId = 333;

  // Put it in a state where we're waiting on a cache
  // load prior to finishing cache selection.
  host.pending_selected_cache_id_ = kMockCacheId;
  EXPECT_TRUE(host.is_selection_pending());

  // The callback should not occur until we finish cache selection.
  last_status_result_ = APPCACHE_STATUS_OBSOLETE;
  last_callback_param_ = reinterpret_cast<void*>(-1);
  host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
  EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, last_status_result_);
  EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_);

  // Satisfy the load with NULL, a failure.
  host.OnCacheLoaded(NULL, kMockCacheId);

  // Cache selection should have finished
  EXPECT_FALSE(host.is_selection_pending());
  EXPECT_EQ(1, mock_frontend_.last_host_id_);
  EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

  // Callback should have fired upon completing the cache load too.
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_);
  EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);
}

TEST_F(AppCacheHostTest, FailedGroupLoad) {
  AppCacheHost host(1, &mock_frontend_, &service_);

  const GURL kMockManifestUrl("http://foo.bar/baz");

  // Put it in a state where we're waiting on a cache
  // load prior to finishing cache selection.
  host.pending_selected_manifest_url_ = kMockManifestUrl;
  EXPECT_TRUE(host.is_selection_pending());

  // The callback should not occur until we finish cache selection.
  last_status_result_ = APPCACHE_STATUS_OBSOLETE;
  last_callback_param_ = reinterpret_cast<void*>(-1);
  host.GetStatusWithCallback(get_status_callback_, reinterpret_cast<void*>(1));
  EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, last_status_result_);
  EXPECT_EQ(reinterpret_cast<void*>(-1), last_callback_param_);

  // Satisfy the load will NULL, a failure.
  host.OnGroupLoaded(NULL, kMockManifestUrl);

  // Cache selection should have finished
  EXPECT_FALSE(host.is_selection_pending());
  EXPECT_EQ(1, mock_frontend_.last_host_id_);
  EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

  // Callback should have fired upon completing the group load.
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, last_status_result_);
  EXPECT_EQ(reinterpret_cast<void*>(1), last_callback_param_);
}

TEST_F(AppCacheHostTest, SetSwappableCache) {
  AppCacheHost host(1, &mock_frontend_, &service_);
  host.SetSwappableCache(NULL);
  EXPECT_FALSE(host.swappable_cache_.get());

  scoped_refptr<AppCacheGroup> group1(new AppCacheGroup(
      service_.storage(), GURL(), service_.storage()->NewGroupId()));
  host.SetSwappableCache(group1.get());
  EXPECT_FALSE(host.swappable_cache_.get());

  AppCache* cache1 = new AppCache(service_.storage(), 111);
  cache1->set_complete(true);
  group1->AddCache(cache1);
  host.SetSwappableCache(group1.get());
  EXPECT_EQ(cache1, host.swappable_cache_.get());

  mock_frontend_.last_host_id_ = -222;  // to verify we received OnCacheSelected

  host.AssociateCompleteCache(cache1);
  EXPECT_FALSE(host.swappable_cache_.get());  // was same as associated cache
  EXPECT_EQ(APPCACHE_STATUS_IDLE, host.GetStatus());
  // verify OnCacheSelected was called
  EXPECT_EQ(host.host_id(), mock_frontend_.last_host_id_);
  EXPECT_EQ(cache1->cache_id(), mock_frontend_.last_cache_id_);
  EXPECT_EQ(APPCACHE_STATUS_IDLE, mock_frontend_.last_status_);

  AppCache* cache2 = new AppCache(service_.storage(), 222);
  cache2->set_complete(true);
  group1->AddCache(cache2);
  EXPECT_EQ(cache2, host.swappable_cache_.get());  // updated to newest

  scoped_refptr<AppCacheGroup> group2(
      new AppCacheGroup(service_.storage(), GURL("http://foo.com"),
                        service_.storage()->NewGroupId()));
  AppCache* cache3 = new AppCache(service_.storage(), 333);
  cache3->set_complete(true);
  group2->AddCache(cache3);

  AppCache* cache4 = new AppCache(service_.storage(), 444);
  cache4->set_complete(true);
  group2->AddCache(cache4);
  EXPECT_EQ(cache2, host.swappable_cache_.get());  // unchanged

  host.AssociateCompleteCache(cache3);
  EXPECT_EQ(cache4, host.swappable_cache_.get());  // newest cache in group2
  EXPECT_FALSE(group1->HasCache());  // both caches in group1 have refcount 0

  host.AssociateNoCache(GURL());
  EXPECT_FALSE(host.swappable_cache_.get());
  EXPECT_FALSE(group2->HasCache());  // both caches in group2 have refcount 0

  // Host adds reference to newest cache when an update is complete.
  AppCache* cache5 = new AppCache(service_.storage(), 555);
  cache5->set_complete(true);
  group2->AddCache(cache5);
  host.group_being_updated_ = group2;
  host.OnUpdateComplete(group2.get());
  EXPECT_FALSE(host.group_being_updated_.get());
  EXPECT_EQ(cache5, host.swappable_cache_.get());

  group2->RemoveCache(cache5);
  EXPECT_FALSE(group2->HasCache());
  host.group_being_updated_ = group2;
  host.OnUpdateComplete(group2.get());
  EXPECT_FALSE(host.group_being_updated_.get());
  EXPECT_FALSE(host.swappable_cache_.get());  // group2 had no newest cache
}

TEST_F(AppCacheHostTest, ForDedicatedWorker) {
  const int kMockProcessId = 1;
  const int kParentHostId = 1;
  const int kWorkerHostId = 2;

  AppCacheBackendImpl backend_impl;
  backend_impl.Initialize(&service_, &mock_frontend_, kMockProcessId);
  backend_impl.RegisterHost(kParentHostId);
  backend_impl.RegisterHost(kWorkerHostId);

  AppCacheHost* parent_host = backend_impl.GetHost(kParentHostId);
  EXPECT_FALSE(parent_host->is_for_dedicated_worker());

  AppCacheHost* worker_host = backend_impl.GetHost(kWorkerHostId);
  worker_host->SelectCacheForWorker(kParentHostId, kMockProcessId);
  EXPECT_TRUE(worker_host->is_for_dedicated_worker());
  EXPECT_EQ(parent_host, worker_host->GetParentAppCacheHost());

  // We should have received an OnCacheSelected msg for the worker_host.
  // The host for workers always indicates 'no cache selected' regardless
  // of its parent's state. This is OK because the worker cannot access
  // the scriptable interface, the only function available is resource
  // loading (see appcache_request_handler_unittests those tests).
  EXPECT_EQ(kWorkerHostId, mock_frontend_.last_host_id_);
  EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
  EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

  // Simulate the parent being torn down.
  backend_impl.UnregisterHost(kParentHostId);
  parent_host = NULL;
  EXPECT_EQ(NULL, backend_impl.GetHost(kParentHostId));
  EXPECT_EQ(NULL, worker_host->GetParentAppCacheHost());
}

TEST_F(AppCacheHostTest, SelectCacheAllowed) {
  scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
      new MockQuotaManagerProxy);
  MockAppCachePolicy mock_appcache_policy;
  mock_appcache_policy.can_create_return_value_ = true;
  service_.set_quota_manager_proxy(mock_quota_proxy.get());
  service_.set_appcache_policy(&mock_appcache_policy);

  // Reset our mock frontend
  mock_frontend_.last_cache_id_ = -333;
  mock_frontend_.last_host_id_ = -333;
  mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE;
  mock_frontend_.last_event_id_ = APPCACHE_OBSOLETE_EVENT;
  mock_frontend_.content_blocked_ = false;

  const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
  const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
  {
    AppCacheHost host(1, &mock_frontend_, &service_);
    host.first_party_url_ = kDocAndOriginUrl;
    host.SelectCache(kDocAndOriginUrl, kAppCacheNoCacheId, kManifestUrl);
    EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));

    // MockAppCacheService::LoadOrCreateGroup is asynchronous, so we shouldn't
    // have received an OnCacheSelected msg yet.
    EXPECT_EQ(-333, mock_frontend_.last_host_id_);
    EXPECT_EQ(-333, mock_frontend_.last_cache_id_);
    EXPECT_EQ(APPCACHE_STATUS_OBSOLETE, mock_frontend_.last_status_);
    // No error events either
    EXPECT_EQ(APPCACHE_OBSOLETE_EVENT, mock_frontend_.last_event_id_);
    EXPECT_FALSE(mock_frontend_.content_blocked_);

    EXPECT_TRUE(host.is_selection_pending());
  }
  EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
  service_.set_quota_manager_proxy(NULL);
}

TEST_F(AppCacheHostTest, SelectCacheBlocked) {
  scoped_refptr<MockQuotaManagerProxy> mock_quota_proxy(
      new MockQuotaManagerProxy);
  MockAppCachePolicy mock_appcache_policy;
  mock_appcache_policy.can_create_return_value_ = false;
  service_.set_quota_manager_proxy(mock_quota_proxy.get());
  service_.set_appcache_policy(&mock_appcache_policy);

  // Reset our mock frontend
  mock_frontend_.last_cache_id_ = -333;
  mock_frontend_.last_host_id_ = -333;
  mock_frontend_.last_status_ = APPCACHE_STATUS_OBSOLETE;
  mock_frontend_.last_event_id_ = APPCACHE_OBSOLETE_EVENT;
  mock_frontend_.content_blocked_ = false;

  const GURL kDocAndOriginUrl(GURL("http://whatever/").GetOrigin());
  const GURL kManifestUrl(GURL("http://whatever/cache.manifest"));
  {
    AppCacheHost host(1, &mock_frontend_, &service_);
    host.first_party_url_ = kDocAndOriginUrl;
    host.SelectCache(kDocAndOriginUrl, kAppCacheNoCacheId, kManifestUrl);
    EXPECT_EQ(1, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));

    // We should have received an OnCacheSelected msg
    EXPECT_EQ(1, mock_frontend_.last_host_id_);
    EXPECT_EQ(kAppCacheNoCacheId, mock_frontend_.last_cache_id_);
    EXPECT_EQ(APPCACHE_STATUS_UNCACHED, mock_frontend_.last_status_);

    // Also, an error event was raised
    EXPECT_EQ(APPCACHE_ERROR_EVENT, mock_frontend_.last_event_id_);
    EXPECT_TRUE(mock_frontend_.content_blocked_);

    // Otherwise, see that it respond as if there is no cache selected.
    EXPECT_EQ(1, host.host_id());
    EXPECT_EQ(&service_, host.service());
    EXPECT_EQ(&mock_frontend_, host.frontend());
    EXPECT_EQ(NULL, host.associated_cache());
    EXPECT_FALSE(host.is_selection_pending());
    EXPECT_TRUE(host.preferred_manifest_url().is_empty());
  }
  EXPECT_EQ(0, mock_quota_proxy->GetInUseCount(kDocAndOriginUrl));
  service_.set_quota_manager_proxy(NULL);
}

}  // namespace content
