// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <cstring>
#include <string>
#include <vector>

#include "base/base_paths.h"
#include "base/file_util.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/path_service.h"
#include "base/platform_file.h"
#include "cobalt/browser/storage_upgrade_handler.h"
#include "cobalt/dom/local_storage_database.h"
#include "cobalt/dom/storage_area.h"
#include "cobalt/loader/origin.h"
#include "cobalt/network/persistent_cookie_store.h"
#include "cobalt/storage/savegame_fake.h"
#include "cobalt/storage/storage_manager.h"
#include "cobalt/storage/upgrade/upgrade_reader.h"
#include "googleurl/src/gurl.h"
#include "net/cookies/canonical_cookie.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace cobalt {
namespace browser {

namespace {

class CallbackWaiter {
 public:
  CallbackWaiter() : was_called_event_(true, false) {}
  virtual ~CallbackWaiter() {}
  bool TimedWait() {
    return was_called_event_.TimedWait(base::TimeDelta::FromSeconds(5));
  }

 protected:
  void Signal() { was_called_event_.Signal(); }

 private:
  base::WaitableEvent was_called_event_;

  DISALLOW_COPY_AND_ASSIGN(CallbackWaiter);
};

class FlushWaiter : public CallbackWaiter {
 public:
  FlushWaiter() {}
  void OnFlushDone() { Signal(); }

 private:
  DISALLOW_COPY_AND_ASSIGN(FlushWaiter);
};

class CookieWaiter : public CallbackWaiter {
 public:
  CookieWaiter() {}
  ~CookieWaiter() {
    for (size_t i = 0; i < cookies_.size(); i++) {
      delete cookies_[i];
    }
  }

  void OnCookiesLoaded(const std::vector<net::CanonicalCookie*>& cookies) {
    cookies_ = cookies;
    Signal();
  }

  const std::vector<net::CanonicalCookie*>& GetCookies() const {
    return cookies_;
  }

 private:
  std::vector<net::CanonicalCookie*> cookies_;
  DISALLOW_COPY_AND_ASSIGN(CookieWaiter);
};

class LocalStorageEntryWaiter : public CallbackWaiter {
 public:
  LocalStorageEntryWaiter() {}
  ~LocalStorageEntryWaiter() {}

  void OnEntriesLoaded(scoped_ptr<dom::StorageArea::StorageMap> entries) {
    entries_ = entries.Pass();
    Signal();
  }

  dom::StorageArea::StorageMap* GetEntries() const { return entries_.get(); }

 private:
  scoped_ptr<dom::StorageArea::StorageMap> entries_;
  DISALLOW_COPY_AND_ASSIGN(LocalStorageEntryWaiter);
};

void ReadFileToString(const char* pathname, std::string* string_out) {
  EXPECT_TRUE(pathname);
  EXPECT_TRUE(string_out);
  FilePath file_path;
  EXPECT_TRUE(PathService::Get(base::DIR_TEST_DATA, &file_path));
  file_path = file_path.Append(pathname);
  EXPECT_TRUE(file_util::ReadFileToString(file_path, string_out));
  const char* data = string_out->c_str();
  const int size = static_cast<int>(string_out->length());
  EXPECT_GT(size, 0);
  EXPECT_LE(size, 10 * 1024 * 1024);
  EXPECT_TRUE(storage::upgrade::UpgradeReader::IsUpgradeData(data, size));
}

int GetNumCookies(storage::StorageManager* storage) {
  scoped_refptr<network::PersistentCookieStore> cookie_store(
      new network::PersistentCookieStore(storage));
  CookieWaiter waiter;
  cookie_store->Load(
      base::Bind(&CookieWaiter::OnCookiesLoaded, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());
  return static_cast<int>(waiter.GetCookies().size());
}

int GetNumLocalStorageEntries(storage::StorageManager* storage,
                              const loader::Origin& origin) {
  dom::LocalStorageDatabase local_storage_database(storage);
  LocalStorageEntryWaiter waiter;
  local_storage_database.ReadAll(
      origin, base::Bind(&LocalStorageEntryWaiter::OnEntriesLoaded,
                         base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());
  return static_cast<int>(waiter.GetEntries()->size());
}

}  // namespace

TEST(StorageUpgradeHandlerTest, UpgradeFullData) {
  MessageLoop message_loop_(MessageLoop::TYPE_DEFAULT);
  std::string file_contents;
  ReadFileToString("cobalt/storage/upgrade/testdata/full_data_v1.json",
                   &file_contents);
  StorageUpgradeHandler* upgrade_handler =
      new StorageUpgradeHandler(GURL("https://www.youtube.com"));
  storage::StorageManager::Options options;
  options.savegame_options.delete_on_destruction = true;
  options.savegame_options.factory = &storage::SavegameFake::Create;
  storage::StorageManager storage(
      scoped_ptr<storage::StorageManager::UpgradeHandler>(upgrade_handler),
      options);

  // Our storage should be empty at this point.
  EXPECT_EQ(GetNumCookies(&storage), 0);
  EXPECT_EQ(GetNumLocalStorageEntries(
                &storage, upgrade_handler->default_local_storage_origin()),
            0);

  upgrade_handler->OnUpgrade(&storage, file_contents.c_str(),
                             static_cast<int>(file_contents.length()));

  FlushWaiter waiter;
  storage.FlushNow(
      base::Bind(&FlushWaiter::OnFlushDone, base::Unretained(&waiter)));
  EXPECT_EQ(true, waiter.TimedWait());

  // We should now have 2 cookies and 2 local storage entries.
  EXPECT_EQ(GetNumCookies(&storage), 2);
  EXPECT_EQ(GetNumLocalStorageEntries(
                &storage, upgrade_handler->default_local_storage_origin()),
            2);

  message_loop_.RunUntilIdle();
}

}  // namespace browser
}  // namespace cobalt
