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

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/message_loop/message_loop_proxy.h"
#include "base/prefs/json_pref_store.h"
#include "base/prefs/pref_value_store.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/waitable_event.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_pref_store.h"
#include "chrome/browser/extensions/extension_pref_value_map.h"
#include "chrome/browser/extensions/extension_prefs.h"
#include "chrome/browser/prefs/pref_service_mock_builder.h"
#include "chrome/browser/prefs/pref_service_syncable.h"
#include "chrome/common/extensions/extension.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/manifest_constants.h"
#include "sync/api/string_ordinal.h"
#include "testing/gtest/include/gtest/gtest.h"

using content::BrowserThread;

namespace extensions {

namespace {

// A TimeProvider which returns an incrementally later time each time
// GetCurrentTime is called.
class IncrementalTimeProvider : public ExtensionPrefs::TimeProvider {
 public:
  IncrementalTimeProvider() : current_time_(base::Time::Now()) {
  }

  virtual ~IncrementalTimeProvider() {
  }

  virtual base::Time GetCurrentTime() const OVERRIDE {
    current_time_ += base::TimeDelta::FromSeconds(10);
    return current_time_;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(IncrementalTimeProvider);

  mutable base::Time current_time_;
};

}  // namespace

TestExtensionPrefs::TestExtensionPrefs(base::SequencedTaskRunner* task_runner)
    : task_runner_(task_runner), extensions_disabled_(false) {
  EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
  preferences_file_ = temp_dir_.path().AppendASCII("Preferences");
  extensions_dir_ = temp_dir_.path().AppendASCII("Extensions");
  EXPECT_TRUE(file_util::CreateDirectory(extensions_dir_));

  ResetPrefRegistry();
  RecreateExtensionPrefs();
}

TestExtensionPrefs::~TestExtensionPrefs() {
}

PrefService* TestExtensionPrefs::pref_service() {
  return pref_service_.get();
}

const scoped_refptr<user_prefs::PrefRegistrySyncable>&
TestExtensionPrefs::pref_registry() {
  return pref_registry_;
}

void TestExtensionPrefs::ResetPrefRegistry() {
  pref_registry_ = new user_prefs::PrefRegistrySyncable;
  ExtensionPrefs::RegisterProfilePrefs(pref_registry_.get());
}

void TestExtensionPrefs::RecreateExtensionPrefs() {
  // We persist and reload the PrefService's PrefStores because this process
  // deletes all empty dictionaries. The ExtensionPrefs implementation
  // needs to be able to handle this situation.
  if (pref_service_) {
    // Commit a pending write (which posts a task to task_runner_) and wait for
    // it to finish.
    pref_service_->CommitPendingWrite();
    base::RunLoop run_loop;
    ASSERT_TRUE(
        task_runner_->PostTaskAndReply(
            FROM_HERE,
            base::Bind(&base::DoNothing),
            run_loop.QuitClosure()));
    run_loop.Run();
  }

  extension_pref_value_map_.reset(new ExtensionPrefValueMap);
  PrefServiceMockBuilder builder;
  builder.WithUserFilePrefs(preferences_file_, task_runner_.get());
  builder.WithExtensionPrefs(
      new ExtensionPrefStore(extension_pref_value_map_.get(), false));
  pref_service_.reset(builder.CreateSyncable(pref_registry_.get()));

  prefs_.reset(ExtensionPrefs::Create(
      pref_service_.get(),
      temp_dir_.path(),
      extension_pref_value_map_.get(),
      extensions_disabled_,
      // Guarantee that no two extensions get the same installation time
      // stamp and we can reliably assert the installation order in the tests.
      scoped_ptr<ExtensionPrefs::TimeProvider>(
          new IncrementalTimeProvider())));
}

scoped_refptr<Extension> TestExtensionPrefs::AddExtension(std::string name) {
  DictionaryValue dictionary;
  dictionary.SetString(manifest_keys::kName, name);
  dictionary.SetString(manifest_keys::kVersion, "0.1");
  return AddExtensionWithManifest(dictionary, Manifest::INTERNAL);
}

scoped_refptr<Extension> TestExtensionPrefs::AddApp(std::string name) {
  DictionaryValue dictionary;
  dictionary.SetString(manifest_keys::kName, name);
  dictionary.SetString(manifest_keys::kVersion, "0.1");
  dictionary.SetString(manifest_keys::kApp, "true");
  dictionary.SetString(manifest_keys::kLaunchWebURL, "http://example.com");
  return AddExtensionWithManifest(dictionary, Manifest::INTERNAL);

}

scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifest(
    const DictionaryValue& manifest, Manifest::Location location) {
  return AddExtensionWithManifestAndFlags(manifest, location,
                                          Extension::NO_FLAGS);
}

scoped_refptr<Extension> TestExtensionPrefs::AddExtensionWithManifestAndFlags(
    const DictionaryValue& manifest,
    Manifest::Location location,
    int extra_flags) {
  std::string name;
  EXPECT_TRUE(manifest.GetString(manifest_keys::kName, &name));
  base::FilePath path =  extensions_dir_.AppendASCII(name);
  std::string errors;
  scoped_refptr<Extension> extension = Extension::Create(
      path, location, manifest, extra_flags, &errors);
  EXPECT_TRUE(extension.get()) << errors;
  if (!extension.get())
    return NULL;

  EXPECT_TRUE(Extension::IdIsValid(extension->id()));
  prefs_->OnExtensionInstalled(extension.get(),
                               Extension::ENABLED,
                               Blacklist::NOT_BLACKLISTED,
                               syncer::StringOrdinal::CreateInitialOrdinal());
  return extension;
}

std::string TestExtensionPrefs::AddExtensionAndReturnId(std::string name) {
  scoped_refptr<Extension> extension(AddExtension(name));
  return extension->id();
}

PrefService* TestExtensionPrefs::CreateIncognitoPrefService() const {
  return pref_service_->CreateIncognitoPrefService(
      new ExtensionPrefStore(extension_pref_value_map_.get(), true));
}

void TestExtensionPrefs::set_extensions_disabled(bool extensions_disabled) {
  extensions_disabled_ = extensions_disabled;
}

}  // namespace extensions
