// Copyright 2018 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 "starboard/shared/widevine/widevine_storage.h"

#include "starboard/common/log.h"
#include "starboard/file.h"
#include "starboard/shared/widevine/widevine_keybox_hash.h"
#include "starboard/types.h"

namespace starboard {
namespace shared {
namespace widevine {

// Reserved key name for referring to the Widevine Keybox checksum value.
const char WidevineStorage::kCobaltWidevineKeyboxChecksumKey[] =
    "cobalt_widevine_keybox_checksum";

namespace {

void ReadFile(const std::string& path_name, std::vector<uint8_t>* content) {
  SB_DCHECK(content);

  ScopedFile file(path_name.c_str(), kSbFileOpenOnly | kSbFileRead);

  if (!file.IsValid()) {
    content->clear();
    SB_LOG(INFO) << "Failed to open " << path_name
                 << ", returning empty content.";
    return;
  }

  auto size = file.GetSize();
  if (size < 0) {
    content->clear();
    SB_LOG(INFO) << "Failed to get size of " << path_name
                 << ", returning empty content.";
    return;
  }

  content->resize(size);
  if (file.ReadAll(reinterpret_cast<char*>(content->data()), size) != size) {
    content->clear();
    SB_LOG(INFO) << "Failed to read content of " << path_name
                 << ", returning empty content.";
    return;
  }
}

bool WriteFile(const std::string& path_name,
               const std::vector<uint8_t>& content) {
  ScopedFile file(path_name.c_str(), kSbFileCreateAlways | kSbFileWrite);

  if (!file.IsValid()) {
    SB_LOG(INFO) << "Failed to create " << path_name << " for writing.";
    return false;
  }

  if (file.WriteAll(reinterpret_cast<const char*>(content.data()),
                    static_cast<int>(content.size())) != content.size()) {
    SB_LOG(INFO) << "Failed to write content to " << path_name << '.';
    return false;
  }

  file.Flush();

  return true;
}

bool ReadString(const std::vector<uint8_t>& data,
                size_t* offset,
                std::string* str) {
  if (*offset + sizeof(int) > data.size()) {
    SB_LOG(ERROR) << "Failed to read the size of string from |data|.";
    return false;
  }
  int size = *reinterpret_cast<const int*>(data.data() + *offset);
  *offset += sizeof(int);
  if (*offset + size > data.size()) {
    SB_LOG(ERROR) << "Failed to read " << size << " bytes from |data|.";
    return false;
  }
  str->assign(reinterpret_cast<const char*>(data.data() + *offset),
              reinterpret_cast<const char*>(data.data() + *offset + size));
  *offset += size;
  return true;
}

void WriteString(const std::string& str, std::vector<uint8_t>* content) {
  content->reserve(content->size() + sizeof(int) + str.size());
  content->resize(content->size() + sizeof(int));
  *reinterpret_cast<int*>(content->data() + content->size() - sizeof(int)) =
      static_cast<int>(str.size());
  content->insert(content->end(), reinterpret_cast<const uint8_t*>(str.c_str()),
                  reinterpret_cast<const uint8_t*>(str.c_str()) + str.size());
}

}  // namespace

WidevineStorage::WidevineStorage(const std::string& path_name)
    : path_name_(path_name) {
  std::vector<uint8_t> content;
  ReadFile(path_name_, &content);
  size_t offset = 0;

  while (offset != content.size()) {
    std::string name, value;
    if (!ReadString(content, &offset, &name) ||
        !ReadString(content, &offset, &value)) {
      cache_.clear();
      SB_LOG(WARNING) << path_name_ << " is corrupt, returns empty content.";
      return;
    }
    cache_[name] = value;
  }

  SB_LOG(INFO) << "Loaded " << cache_.size() << " records from " << path_name_;

  // Not a cryptographic hash but is sufficient for this problem space.
  std::string keybox_checksum = GetWidevineKeyboxHash();
  if (existsInternal(kCobaltWidevineKeyboxChecksumKey)) {
    std::string cached_checksum;
    readInternal(kCobaltWidevineKeyboxChecksumKey, &cached_checksum);
    if (keybox_checksum == cached_checksum) {
      return;
    }
    SB_LOG(INFO) << "Cobalt widevine keybox checksums do not match. Clearing "
                    "to force re-provisioning.";
    cache_.clear();
    // Save the new keybox checksum to be used after provisioning completes.
    writeInternal(kCobaltWidevineKeyboxChecksumKey, keybox_checksum);
    return;
  }
  SB_LOG(INFO) << "Widevine checksum is not stored on disk. Writing the "
                  "computed checksum to disk.";
  writeInternal(kCobaltWidevineKeyboxChecksumKey, keybox_checksum);
}

bool WidevineStorage::read(const std::string& name, std::string* data) {
  SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey);
  return readInternal(name, data);
}

bool WidevineStorage::write(const std::string& name, const std::string& data) {
  SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey);
  return writeInternal(name, data);
}

bool WidevineStorage::exists(const std::string& name) {
  SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey);
  return existsInternal(name);
}

bool WidevineStorage::remove(const std::string& name) {
  SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey);
  return removeInternal(name);
}

int32_t WidevineStorage::size(const std::string& name) {
  SB_DCHECK(name != kCobaltWidevineKeyboxChecksumKey);
  ScopedLock scoped_lock(lock_);
  auto iter = cache_.find(name);
  return iter == cache_.end() ? -1 : static_cast<int32_t>(iter->second.size());
}

bool WidevineStorage::list(std::vector<std::string>* records) {
  SB_DCHECK(records);
  ScopedLock scoped_lock(lock_);
  records->clear();
  for (auto item : cache_) {
    if (item.first == kCobaltWidevineKeyboxChecksumKey) {
      continue;
    }
    records->push_back(item.first);
  }
  return !records->empty();
}

bool WidevineStorage::readInternal(const std::string& name,
                                   std::string* data) const {
  SB_DCHECK(data);
  ScopedLock scoped_lock(lock_);
  auto iter = cache_.find(name);
  if (iter == cache_.end()) {
    return false;
  }
  *data = iter->second;
  return true;
}

bool WidevineStorage::writeInternal(const std::string& name,
                                    const std::string& data) {
  ScopedLock scoped_lock(lock_);
  cache_[name] = data;

  std::vector<uint8_t> content;
  for (auto iter : cache_) {
    WriteString(iter.first, &content);
    WriteString(iter.second, &content);
  }
  return WriteFile(path_name_, content);
}

bool WidevineStorage::existsInternal(const std::string& name) const {
  ScopedLock scoped_lock(lock_);
  return cache_.find(name) != cache_.end();
}

bool WidevineStorage::removeInternal(const std::string& name) {
  ScopedLock scoped_lock(lock_);
  auto iter = cache_.find(name);
  if (iter == cache_.end()) {
    return false;
  }
  cache_.erase(iter);
  return true;
}

}  // namespace widevine
}  // namespace shared
}  // namespace starboard
