// Copyright 2016 Google Inc. 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 "cobalt/storage/upgrade/upgrade_reader.h"

#include <string>

#include "base/i18n/time_formatting.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/string_number_conversions.h"
#include "googleurl/src/gurl.h"

namespace cobalt {
namespace storage {
namespace upgrade {

namespace {

// The header at the start of upgrade data.
const int kHeaderSize = 4;
const char kHeader[] = "UPG0";

// Used as a sanity check.
const int kMaxUpgradeDataSize = 10 * 1024 * 1024;

// Deseralize a time value encoded as a possibly empty ASCII decimal string.
base::Time StringToTime(const std::string& time_as_string,
                        const base::Time& default_time) {
  if (!time_as_string.empty()) {
    int64 time_as_int64;
    if (base::StringToInt64(time_as_string, &time_as_int64)) {
      return base::Time::FromInternalValue(time_as_int64);
    }
  }

  return default_time;
}

base::Time GetSerializedTime(const base::DictionaryValue* dictionary,
                             const std::string& field_name,
                             const base::Time& default_time) {
  std::string time_string;
  dictionary->GetString(field_name, &time_string);
  return StringToTime(time_string, default_time);
}

// Get a list contained in a dictionary.
const base::ListValue* GetList(const base::DictionaryValue* dictionary,
                               const std::string& list_name) {
  if (!dictionary) {
    return NULL;
  }

  const base::ListValue* list = NULL;
  if (!dictionary->GetList(list_name, &list)) {
    return NULL;
  }

  return list;
}

// Get the size of a list contained in a dictionary.
int GetListSize(const base::DictionaryValue* dictionary,
                const std::string& list_name) {
  const base::ListValue* list = GetList(dictionary, list_name);
  if (!list) {
    return 0;
  }

  return static_cast<int>(list->GetSize());
}

// Get a dictionary in a list contained in a dictionary.
const base::DictionaryValue* GetListItem(
    const base::DictionaryValue* dictionary, const std::string& list_name,
    int index) {
  const base::ListValue* list = GetList(dictionary, list_name);
  if (!list) {
    return NULL;
  }

  if (index < 0 || index >= static_cast<int>(list->GetSize())) {
    return NULL;
  }

  const base::DictionaryValue* list_item = NULL;
  if (!list->GetDictionary(static_cast<size_t>(index), &list_item)) {
    return NULL;
  }

  return list_item;
}

}  // namespace

void UpgradeReader::Parse(const char* data, int size) {
  DCHECK(data);
  DCHECK_GE(size, kHeaderSize);
  DCHECK_LE(size, kMaxUpgradeDataSize);

  // Check the header and offset the data.
  DCHECK(IsUpgradeData(data, size));
  data += kHeaderSize;
  size -= kHeaderSize;

  base::JSONReader json_reader;
  scoped_ptr<base::Value> parsed(
      json_reader.ReadToValue(std::string(data, static_cast<size_t>(size))));
  base::DictionaryValue* valid_dictionary = NULL;
  if (parsed) {
    parsed->GetAsDictionary(&valid_dictionary);
  }

  if (valid_dictionary) {
    ProcessValues(valid_dictionary);
  } else {
    DLOG(ERROR) << "Cannot parse upgrade save data: "
                << base::JSONReader::ErrorCodeToString(
                       json_reader.error_code());
  }
}

int UpgradeReader::GetNumCookies() const {
  return static_cast<int>(cookies_.size());
}

int UpgradeReader::GetNumLocalStorageEntries() const {
  return static_cast<int>(local_storage_entries_.size());
}

const net::CanonicalCookie* UpgradeReader::GetCookie(int index) const {
  if (index >= 0 && index < static_cast<int>(cookies_.size())) {
    return &cookies_[static_cast<size_t>(index)];
  } else {
    return static_cast<const net::CanonicalCookie*>(NULL);
  }
}

void UpgradeReader::AddCookieIfValid(const base::DictionaryValue* cookie) {
  DCHECK(cookie);

  // Required attributes.
  std::string url;
  std::string name;
  std::string value;
  cookie->GetString("url", &url);
  cookie->GetString("name", &name);
  cookie->GetString("value", &value);
  if (url.empty() || name.empty() || value.empty()) {
    return;
  }

  // Optional attributes with default values.
  const GURL gurl(url);
  const std::string host = gurl.host();
  std::string domain = host.empty() ? "" : host.substr(host.find("."));
  cookie->GetString("domain", &domain);
  std::string path = "/";
  cookie->GetString("path", &path);
  base::Time creation =
      GetSerializedTime(cookie, "creation", base::Time::Now());
  base::Time expiration =
      GetSerializedTime(cookie, "expiration", base::Time());
  base::Time last_access =
      GetSerializedTime(cookie, "last_access", base::Time::Now());
  bool http_only = false;
  cookie->GetBoolean("http_only", &http_only);

  // Attributes not defined in upgrade data.
  const std::string mac_key;
  const std::string mac_algorithm;
  const bool secure = true;

  if (expiration.is_null()) {
    LOG(ERROR) << "\"" << name
               << "\" cookie can not be upgraded due to null expiration.";
    OnNullExpiration();
  }
  LOG_IF(ERROR, expiration < base::Time::UnixEpoch())
      << "\"" << name << "\" upgrade cookie expiration is "
      << base::TimeFormatFriendlyDateAndTime(expiration);

  cookies_.push_back(net::CanonicalCookie(
      gurl, name, value, domain, path, mac_key, mac_algorithm, creation,
      expiration, last_access, secure, http_only));
}

const UpgradeReader::LocalStorageEntry* UpgradeReader::GetLocalStorageEntry(
    int index) const {
  if (index >= 0 && index < static_cast<int>(local_storage_entries_.size())) {
    return &local_storage_entries_[static_cast<size_t>(index)];
  } else {
    return static_cast<const LocalStorageEntry*>(NULL);
  }
}

void UpgradeReader::AddLocalStorageEntryIfValid(
    const base::DictionaryValue* local_storage_entry) {
  DCHECK(local_storage_entry);
  std::string key;
  std::string value;
  if (!local_storage_entry->GetString("key", &key) ||
      !local_storage_entry->GetString("value", &value) || key.empty() ||
      value.empty()) {
    return;
  }

  local_storage_entries_.push_back(LocalStorageEntry(key, value));
}

// static
bool UpgradeReader::IsUpgradeData(const char* data, int size) {
  return size >= kHeaderSize && memcmp(data, kHeader, kHeaderSize) == 0;
}

void UpgradeReader::ProcessValues(const base::DictionaryValue* dictionary) {
  DCHECK(dictionary);

  const int num_cookies = GetListSize(dictionary, "cookies");
  for (int n = 0; n < num_cookies; n++) {
    const base::DictionaryValue* cookie = GetListItem(dictionary, "cookies", n);
    if (cookie) {
      AddCookieIfValid(cookie);
    }
  }

  const int num_local_storage_entries =
      GetListSize(dictionary, "local_storage_entries");
  for (int n = 0; n < num_local_storage_entries; n++) {
    const base::DictionaryValue* local_storage_entry =
        GetListItem(dictionary, "local_storage_entries", n);
    if (local_storage_entry) {
      AddLocalStorageEntryIfValid(local_storage_entry);
    }
  }
}

}  // namespace upgrade
}  // namespace storage
}  // namespace cobalt
