// Copyright (c) 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/extensions/external_pref_cache_loader.h"

#include <map>
#include <utility>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/values.h"
#include "base/version.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/extensions/external_cache.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_system.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chromeos/chromeos_switches.h"
#include "content/public/browser/browser_thread.h"

namespace chromeos {

namespace {

// Directory where the extensions are cached.
const char kPreinstalledAppsCacheDir[] = "/var/cache/external_cache";

}  // namespace

// Ref-counted class that holds ExternalCache and dispatches cache update events
// to per-profile instances of ExternalPrefCacheLoader. This multiplexing
// is required for multi-profile case.
class ExternalCacheDispatcher
    : public ExternalCache::Delegate,
      public base::RefCounted<ExternalCacheDispatcher> {
 public:
  static ExternalCacheDispatcher* GetInstance() {
    if (!ExternalCacheDispatcher::instance_)
      ExternalCacheDispatcher::instance_ = new ExternalCacheDispatcher;
    return instance_;
  }

  // Implementation of ExternalCache::Delegate:
  virtual void OnExtensionListsUpdated(
      const base::DictionaryValue* prefs) OVERRIDE {
    is_extensions_list_ready_ = true;
    for (LoadersMap::iterator it = pref_loaders_.begin();
         it != pref_loaders_.end(); ++it) {
      it->first->OnExtensionListsUpdated(prefs);
    }
  }

  virtual std::string GetInstalledExtensionVersion(
      const std::string& id) OVERRIDE {
    // Return lowest installed version. Updater will download an update if
    // CWS has higher version. Version returned here matters only if file is
    // missing in .crx cache.
    base::Version version;
    for (LoadersMap::iterator it = pref_loaders_.begin();
         it != pref_loaders_.end(); ++it) {
      ExtensionServiceInterface* extension_service =
          extensions::ExtensionSystem::Get(it->second)->extension_service();
      const extensions::Extension* extension = extension_service ?
          extension_service->GetExtensionById(id, true) : NULL;
      if (extension) {
        if (!version.IsValid() || extension->version()->CompareTo(version) < 0)
          version = *extension->version();
      }
    }
    return version.IsValid() ? version.GetString() : std::string();
  }

  void UpdateExtensionsList(scoped_ptr<base::DictionaryValue> prefs) {
    DCHECK(!is_extensions_list_ready_);
    external_cache_.UpdateExtensionsList(prefs.Pass());
  }

  // Return false if cache doesn't have list of extensions and it needs to
  // be provided via UpdateExtensionsList.
  bool RegisterExternalPrefCacheLoader(ExternalPrefCacheLoader* observer,
                                       int base_path_id,
                                       Profile* profile) {
    pref_loaders_.insert(std::make_pair(observer, profile));

    if (base_path_id_ == 0) {
      // First ExternalPrefCacheLoader is registered.
      base_path_id_ = base_path_id;
      return false;
    } else {
      CHECK_EQ(base_path_id_, base_path_id);
      if (is_extensions_list_ready_) {
        // If list of extensions is not ready, |observer| will be notified later
        // in OnExtensionListsUpdated.
        observer->OnExtensionListsUpdated(external_cache_.cached_extensions());
      }
      return true;
    }
  }

  void UnregisterExternalPrefCacheLoader(ExternalPrefCacheLoader* observer) {
    pref_loaders_.erase(observer);
  }

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

  typedef std::map<ExternalPrefCacheLoader*, Profile*> LoadersMap;

  ExternalCacheDispatcher()
    : external_cache_(base::FilePath(kPreinstalledAppsCacheDir),
                      g_browser_process->system_request_context(),
                      content::BrowserThread::GetBlockingPool()->
                          GetSequencedTaskRunnerWithShutdownBehavior(
                              content::BrowserThread::GetBlockingPool()->
                                  GetSequenceToken(),
                              base::SequencedWorkerPool::SKIP_ON_SHUTDOWN),
                      this,
                      true,
                      true),
      base_path_id_(0),
      is_extensions_list_ready_(false) {
    DCHECK(!ExternalCacheDispatcher::instance_);
  }

  virtual ~ExternalCacheDispatcher() {
    ExternalCacheDispatcher::instance_ = NULL;
  }

  ExternalCache external_cache_;
  LoadersMap pref_loaders_;
  int base_path_id_;
  bool is_extensions_list_ready_;

  static ExternalCacheDispatcher* instance_;

  DISALLOW_COPY_AND_ASSIGN(ExternalCacheDispatcher);
};

ExternalCacheDispatcher* ExternalCacheDispatcher::instance_ = NULL;

ExternalPrefCacheLoader::ExternalPrefCacheLoader(int base_path_id,
                                                 Profile* profile)
  : ExternalPrefLoader(base_path_id, ExternalPrefLoader::NONE),
    profile_(profile),
    cache_dispatcher_(ExternalCacheDispatcher::GetInstance()) {
}

ExternalPrefCacheLoader::~ExternalPrefCacheLoader() {
  cache_dispatcher_->UnregisterExternalPrefCacheLoader(this);
}

void ExternalPrefCacheLoader::OnExtensionListsUpdated(
    const base::DictionaryValue* prefs) {
  prefs_.reset(prefs->DeepCopy());
  ExternalPrefLoader::LoadFinished();
}

void ExternalPrefCacheLoader::StartLoading() {
  if (!cache_dispatcher_->RegisterExternalPrefCacheLoader(
          this, base_path_id_, profile_)) {
    // ExternalCacheDispatcher doesn't know list of extensions load it.
    ExternalPrefLoader::StartLoading();
  }
}

void ExternalPrefCacheLoader::LoadFinished() {
  // TODO(dzhioev): Remove "Tips & Tricks" app from default apps till M33.
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kDisableFirstRunUI) &&
      prefs_.get() && prefs_->HasKey(extension_misc::kTipsAndTricksAppId)) {
    prefs_->Remove(extension_misc::kTipsAndTricksAppId, NULL);
  }
  cache_dispatcher_->UpdateExtensionsList(prefs_.Pass());
}

}  // namespace chromeos
