// Copyright 2013 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 "chrome/browser/chromeos/app_mode/kiosk_app_data.h"

#include <vector>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
#include "base/memory/ref_counted_memory.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/scoped_user_pref_update.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_data_delegate.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager.h"
#include "chrome/browser/extensions/webstore_data_fetcher.h"
#include "chrome/browser/extensions/webstore_install_helper.h"
#include "chrome/browser/image_decoder.h"
#include "chrome/common/extensions/extension_constants.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/manifest.h"
#include "extensions/common/manifest_constants.h"
#include "ui/gfx/codec/png_codec.h"

using content::BrowserThread;

namespace chromeos {

namespace {

// Keys for local state data. See sample layout in KioskAppManager.
const char kKeyName[] = "name";
const char kKeyIcon[] = "icon";

// Web store data keys.
const char kManifestKey[] = "manifest";
const char kIconUrlKey[] = "icon_url";
const char kLocalizedNameKey[] = "localized_name";

const char kInvalidWebstoreResponseError[] = "Invalid Chrome Web Store reponse";

// Icon file extension.
const char kIconFileExtension[] = ".png";

// Save |raw_icon| for given |app_id|.
void SaveIconToLocalOnBlockingPool(
    const base::FilePath& icon_path,
    scoped_refptr<base::RefCountedString> raw_icon) {
  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());

  base::FilePath dir = icon_path.DirName();
  if (!base::PathExists(dir))
    CHECK(base::CreateDirectory(dir));

  CHECK_EQ(static_cast<int>(raw_icon->size()),
           file_util::WriteFile(icon_path,
                                raw_icon->data().c_str(), raw_icon->size()));
}

// Returns true for valid kiosk app manifest.
bool IsValidKioskAppManifest(const extensions::Manifest& manifest) {
  bool kiosk_enabled;
  if (manifest.GetBoolean(extensions::manifest_keys::kKioskEnabled,
                          &kiosk_enabled)) {
    return kiosk_enabled;
  }

  return false;
}

std::string ValueToString(const base::Value* value) {
  std::string json;
  base::JSONWriter::Write(value, &json);
  return json;
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
// KioskAppData::IconLoader
// Loads locally stored icon data and decode it.

class KioskAppData::IconLoader : public ImageDecoder::Delegate {
 public:
  enum LoadResult {
    SUCCESS,
    FAILED_TO_LOAD,
    FAILED_TO_DECODE,
  };

  IconLoader(const base::WeakPtr<KioskAppData>& client,
             const base::FilePath& icon_path)
      : client_(client),
        icon_path_(icon_path),
        load_result_(SUCCESS) {}

  void Start() {
    base::SequencedWorkerPool* pool = BrowserThread::GetBlockingPool();
    base::SequencedWorkerPool::SequenceToken token = pool->GetSequenceToken();
    task_runner_ = pool->GetSequencedTaskRunnerWithShutdownBehavior(
        token,
        base::SequencedWorkerPool::CONTINUE_ON_SHUTDOWN);
    task_runner_->PostTask(FROM_HERE,
                           base::Bind(&IconLoader::LoadOnBlockingPool,
                                      base::Unretained(this)));
  }

 private:
  friend class base::RefCountedThreadSafe<IconLoader>;

  virtual ~IconLoader() {}

  // Loads the icon from locally stored |icon_path_| on the blocking pool
  void LoadOnBlockingPool() {
    DCHECK(task_runner_->RunsTasksOnCurrentThread());

    std::string data;
    if (!base::ReadFileToString(base::FilePath(icon_path_), &data)) {
      ReportResultOnBlockingPool(FAILED_TO_LOAD);
      return;
    }
    raw_icon_ = base::RefCountedString::TakeString(&data);

    scoped_refptr<ImageDecoder> image_decoder = new ImageDecoder(
        this, raw_icon_->data(), ImageDecoder::DEFAULT_CODEC);
    image_decoder->Start(task_runner_);
  }

  void ReportResultOnBlockingPool(LoadResult result) {
    DCHECK(task_runner_->RunsTasksOnCurrentThread());

    load_result_ = result;
    BrowserThread::PostTask(
        BrowserThread::UI,
        FROM_HERE,
        base::Bind(&IconLoader::ReportResultOnUIThread,
                   base::Unretained(this)));
  }

  void NotifyClient() {
    if (!client_)
      return;

    if (load_result_ == SUCCESS)
      client_->OnIconLoadSuccess(raw_icon_, icon_);
    else
      client_->OnIconLoadFailure();
  }

  void ReportResultOnUIThread() {
    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

    NotifyClient();
    delete this;
  }

  // ImageDecoder::Delegate overrides:
  virtual void OnImageDecoded(const ImageDecoder* decoder,
                              const SkBitmap& decoded_image) OVERRIDE {
    icon_ = gfx::ImageSkia::CreateFrom1xBitmap(decoded_image);
    icon_.MakeThreadSafe();
    ReportResultOnBlockingPool(SUCCESS);
  }

  virtual void OnDecodeImageFailed(const ImageDecoder* decoder) OVERRIDE {
    ReportResultOnBlockingPool(FAILED_TO_DECODE);
  }

  base::WeakPtr<KioskAppData> client_;
  base::FilePath icon_path_;

  LoadResult load_result_;
  scoped_refptr<base::SequencedTaskRunner> task_runner_;

  gfx::ImageSkia icon_;
  scoped_refptr<base::RefCountedString> raw_icon_;

  DISALLOW_COPY_AND_ASSIGN(IconLoader);
};

////////////////////////////////////////////////////////////////////////////////
// KioskAppData::WebstoreDataParser
// Use WebstoreInstallHelper to parse the manifest and decode the icon.

class KioskAppData::WebstoreDataParser
    : public extensions::WebstoreInstallHelper::Delegate {
 public:
  explicit WebstoreDataParser(const base::WeakPtr<KioskAppData>& client)
      : client_(client) {}

  void Start(const std::string& app_id,
             const std::string& manifest,
             const GURL& icon_url,
             net::URLRequestContextGetter* context_getter) {
    scoped_refptr<extensions::WebstoreInstallHelper> webstore_helper =
        new extensions::WebstoreInstallHelper(this,
                                              app_id,
                                              manifest,
                                              "",  // No icon data.
                                              icon_url,
                                              context_getter);
    webstore_helper->Start();
  }

 private:
  friend class base::RefCounted<WebstoreDataParser>;

  virtual ~WebstoreDataParser() {}

  void ReportFailure() {
    if (client_)
      client_->OnWebstoreParseFailure();

    delete this;
  }

  // WebstoreInstallHelper::Delegate overrides:
  virtual void OnWebstoreParseSuccess(
      const std::string& id,
      const SkBitmap& icon,
      base::DictionaryValue* parsed_manifest) OVERRIDE {
    // Takes ownership of |parsed_manifest|.
    extensions::Manifest manifest(
        extensions::Manifest::INVALID_LOCATION,
        scoped_ptr<base::DictionaryValue>(parsed_manifest));

    if (!IsValidKioskAppManifest(manifest)) {
      ReportFailure();
      return;
    }

    if (client_)
      client_->OnWebstoreParseSuccess(icon);
    delete this;
  }
  virtual void OnWebstoreParseFailure(
      const std::string& id,
      InstallHelperResultCode result_code,
      const std::string& error_message) OVERRIDE {
    ReportFailure();
  }

  base::WeakPtr<KioskAppData> client_;

  DISALLOW_COPY_AND_ASSIGN(WebstoreDataParser);
};

////////////////////////////////////////////////////////////////////////////////
// KioskAppData

KioskAppData::KioskAppData(KioskAppDataDelegate* delegate,
                           const std::string& app_id,
                           const std::string& user_id)
    : delegate_(delegate),
      status_(STATUS_INIT),
      app_id_(app_id),
      user_id_(user_id) {
}

KioskAppData::~KioskAppData() {}

void KioskAppData::Load() {
  SetStatus(STATUS_LOADING);

  if (LoadFromCache())
    return;

  StartFetch();
}

void KioskAppData::ClearCache() {
  PrefService* local_state = g_browser_process->local_state();

  DictionaryPrefUpdate dict_update(local_state,
                                   KioskAppManager::kKioskDictionaryName);

  std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + app_id_;
  dict_update->Remove(app_key, NULL);

  if (!icon_path_.empty()) {
    BrowserThread::PostBlockingPoolTask(
        FROM_HERE,
        base::Bind(base::IgnoreResult(&base::DeleteFile), icon_path_, false));
  }
}

bool KioskAppData::IsLoading() const {
  return status_ == STATUS_LOADING;
}

void KioskAppData::SetStatus(Status status) {
  if (status_ == status)
    return;

  status_ = status;

  if (!delegate_)
    return;

  switch (status_) {
    case STATUS_INIT:
      break;
    case STATUS_LOADING:
    case STATUS_LOADED:
      delegate_->OnKioskAppDataChanged(app_id_);
      break;
    case STATUS_ERROR:
      delegate_->OnKioskAppDataLoadFailure(app_id_);
      break;
  };
}

net::URLRequestContextGetter* KioskAppData::GetRequestContextGetter() {
  return g_browser_process->system_request_context();
}

bool KioskAppData::LoadFromCache() {
  std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + app_id_;
  std::string name_key = app_key + '.' + kKeyName;
  std::string icon_path_key = app_key + '.' + kKeyIcon;

  PrefService* local_state = g_browser_process->local_state();
  const base::DictionaryValue* dict =
      local_state->GetDictionary(KioskAppManager::kKioskDictionaryName);

  icon_path_.clear();
  std::string icon_path_string;
  if (!dict->GetString(name_key, &name_) ||
      !dict->GetString(icon_path_key, &icon_path_string)) {
    return false;
  }
  icon_path_ = base::FilePath(icon_path_string);

  // IconLoader deletes itself when done.
  (new IconLoader(AsWeakPtr(), icon_path_))->Start();
  return true;
}

void KioskAppData::SetCache(const std::string& name,
                            const base::FilePath& icon_path) {
  std::string app_key = std::string(KioskAppManager::kKeyApps) + '.' + app_id_;
  std::string name_key = app_key + '.' + kKeyName;
  std::string icon_path_key = app_key + '.' + kKeyIcon;

  PrefService* local_state = g_browser_process->local_state();
  DictionaryPrefUpdate dict_update(local_state,
                                   KioskAppManager::kKioskDictionaryName);
  dict_update->SetString(name_key, name);
  dict_update->SetString(icon_path_key, icon_path.value());
  icon_path_ = icon_path;
}

void KioskAppData::OnIconLoadSuccess(
    const scoped_refptr<base::RefCountedString>& raw_icon,
    const gfx::ImageSkia& icon) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  raw_icon_ = raw_icon;
  icon_ = icon;
  SetStatus(STATUS_LOADED);
}

void KioskAppData::OnIconLoadFailure() {
  // Re-fetch data from web store when failed to load cached data.
  StartFetch();
}

void KioskAppData::OnWebstoreParseSuccess(const SkBitmap& icon) {
  icon_ = gfx::ImageSkia::CreateFrom1xBitmap(icon);
  icon_.MakeThreadSafe();

  std::vector<unsigned char> image_data;
  CHECK(gfx::PNGCodec::EncodeBGRASkBitmap(icon, false, &image_data));
  raw_icon_ = new base::RefCountedString;
  raw_icon_->data().assign(image_data.begin(), image_data.end());

  base::FilePath cache_dir;
  if (delegate_)
    delegate_->GetKioskAppIconCacheDir(&cache_dir);

  base::FilePath icon_path =
      cache_dir.AppendASCII(app_id_).AddExtension(kIconFileExtension);
  BrowserThread::GetBlockingPool()->PostTask(
      FROM_HERE,
      base::Bind(&SaveIconToLocalOnBlockingPool, icon_path, raw_icon_));

  SetCache(name_, icon_path);
  SetStatus(STATUS_LOADED);
}

void KioskAppData::OnWebstoreParseFailure() {
  SetStatus(STATUS_ERROR);
}

void KioskAppData::StartFetch() {
  webstore_fetcher_.reset(new extensions::WebstoreDataFetcher(
      this,
      GetRequestContextGetter(),
      GURL(),
      app_id_));
  webstore_fetcher_->Start();
}

void KioskAppData::OnWebstoreRequestFailure() {
  SetStatus(STATUS_ERROR);
}

void KioskAppData::OnWebstoreResponseParseSuccess(
      scoped_ptr<base::DictionaryValue> webstore_data) {
  // Takes ownership of |webstore_data|.
  webstore_fetcher_.reset();

  std::string manifest;
  if (!CheckResponseKeyValue(webstore_data.get(), kManifestKey, &manifest))
    return;

  if (!CheckResponseKeyValue(webstore_data.get(), kLocalizedNameKey, &name_))
    return;

  std::string icon_url_string;
  if (!CheckResponseKeyValue(webstore_data.get(), kIconUrlKey,
                             &icon_url_string))
    return;

  GURL icon_url = GURL(extension_urls::GetWebstoreLaunchURL()).Resolve(
      icon_url_string);
  if (!icon_url.is_valid()) {
    LOG(ERROR) << "Webstore response error (icon url): "
               << ValueToString(webstore_data.get());
    OnWebstoreResponseParseFailure(kInvalidWebstoreResponseError);
    return;
  }

  // WebstoreDataParser deletes itself when done.
  (new WebstoreDataParser(AsWeakPtr()))->Start(app_id_,
                                               manifest,
                                               icon_url,
                                               GetRequestContextGetter());
}

void KioskAppData::OnWebstoreResponseParseFailure(const std::string& error) {
  LOG(ERROR) << "Webstore failed for kiosk app " << app_id_
             << ", " << error;
  webstore_fetcher_.reset();
  SetStatus(STATUS_ERROR);
}

bool KioskAppData::CheckResponseKeyValue(const base::DictionaryValue* response,
                                         const char* key,
                                         std::string* value) {
  if (!response->GetString(key, value)) {
    LOG(ERROR) << "Webstore response error (" << key
               << "): " << ValueToString(response);
    OnWebstoreResponseParseFailure(kInvalidWebstoreResponseError);
    return false;
  }
  return true;
}

}  // namespace chromeos
