// 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/external_pref_loader.h"

#include <utility>

#include "base/bind.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_file_value_serializer.h"
#include "base/json/json_string_value_serializer.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/scoped_observer.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task_scheduler/lazy_task_runner.h"
#include "build/build_config.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/prefs/pref_service_syncable_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/common/chrome_paths.h"
#include "components/browser_sync/profile_sync_service.h"
#include "components/sync/driver/sync_service_observer.h"
#include "components/sync_preferences/pref_service_syncable.h"
#include "components/sync_preferences/pref_service_syncable_observer.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/extension_file_task_runner.h"

using content::BrowserThread;

namespace {

constexpr base::FilePath::CharType kExternalExtensionJson[] =
    FILE_PATH_LITERAL("external_extensions.json");

std::set<base::FilePath> GetPrefsCandidateFilesFromFolder(
      const base::FilePath& external_extension_search_path) {
  base::AssertBlockingAllowed();

  std::set<base::FilePath> external_extension_paths;

  if (!base::PathExists(external_extension_search_path)) {
    // Does not have to exist.
    return external_extension_paths;
  }

  base::FileEnumerator json_files(
      external_extension_search_path,
      false,  // Recursive.
      base::FileEnumerator::FILES);
#if defined(OS_WIN)
  base::FilePath::StringType extension = base::UTF8ToWide(".json");
#elif defined(OS_POSIX)
  base::FilePath::StringType extension(".json");
#endif
  do {
    base::FilePath file = json_files.Next();
    if (file.BaseName().value() == kExternalExtensionJson)
      continue;  // Already taken care of elsewhere.
    if (file.empty())
      break;
    if (file.MatchesExtension(extension)) {
      external_extension_paths.insert(file.BaseName());
    } else {
      DVLOG(1) << "Not considering: " << file.LossyDisplayName()
               << " (does not have a .json extension)";
    }
  } while (true);

  return external_extension_paths;
}

}  // namespace

namespace extensions {

// Helper class to wait for priority sync to be ready.
class ExternalPrefLoader::PrioritySyncReadyWaiter
    : public sync_preferences::PrefServiceSyncableObserver,
      public syncer::SyncServiceObserver {
 public:
  explicit PrioritySyncReadyWaiter(Profile* profile)
      : profile_(profile),
        syncable_pref_observer_(this),
        sync_service_observer_(this) {}

  ~PrioritySyncReadyWaiter() override {}

  void Start(base::OnceClosure done_closure) {
    if (IsPrioritySyncing()) {
      std::move(done_closure).Run();
      // Note: |this| is deleted here.
      return;
    }
    // Start observing sync changes.
    DCHECK(profile_);
    browser_sync::ProfileSyncService* service =
        ProfileSyncServiceFactory::GetForProfile(profile_);
    DCHECK(service);
    if (service->CanSyncStart() && (service->IsFirstSetupComplete() ||
                                    browser_defaults::kSyncAutoStarts)) {
      done_closure_ = std::move(done_closure);
      AddObservers();
    } else {
      std::move(done_closure).Run();
      // Note: |this| is deleted here.
    }
  }

  // sync_preferences::PrefServiceSyncableObserver:
  void OnIsSyncingChanged() override {
    DCHECK(profile_);
    if (!IsPrioritySyncing())
      return;

    Finish();
    // Note: |this| is deleted here.
  }

  // syncer::SyncServiceObserver
  void OnStateChanged(syncer::SyncService* sync) override {
    if (!sync->CanSyncStart())
      Finish();
  }

 private:
  bool IsPrioritySyncing() {
    DCHECK(profile_);
    sync_preferences::PrefServiceSyncable* prefs =
        PrefServiceSyncableFromProfile(profile_);
    DCHECK(prefs);
    return prefs->IsPrioritySyncing();
  }

  void AddObservers() {
    sync_preferences::PrefServiceSyncable* prefs =
        PrefServiceSyncableFromProfile(profile_);
    DCHECK(prefs);
    syncable_pref_observer_.Add(prefs);

    browser_sync::ProfileSyncService* service =
        ProfileSyncServiceFactory::GetForProfile(profile_);
    sync_service_observer_.Add(service);
  }

  void Finish() { std::move(done_closure_).Run(); }

  Profile* profile_;

  base::OnceClosure done_closure_;

  // Used for registering observer for sync_preferences::PrefServiceSyncable.
  ScopedObserver<sync_preferences::PrefServiceSyncable,
                 sync_preferences::PrefServiceSyncableObserver>
      syncable_pref_observer_;
  ScopedObserver<browser_sync::ProfileSyncService, syncer::SyncServiceObserver>
      sync_service_observer_;

  DISALLOW_COPY_AND_ASSIGN(PrioritySyncReadyWaiter);
};

ExternalPrefLoader::ExternalPrefLoader(int base_path_id,
                                       Options options,
                                       Profile* profile)
    : base_path_id_(base_path_id), options_(options), profile_(profile) {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
}

ExternalPrefLoader::~ExternalPrefLoader() {
}

const base::FilePath ExternalPrefLoader::GetBaseCrxFilePath() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);

  // |base_path_| was set in LoadOnFileThread().
  return base_path_;
}

void ExternalPrefLoader::StartLoading() {
  DCHECK_CURRENTLY_ON(BrowserThread::UI);
  if ((options_ & DELAY_LOAD_UNTIL_PRIORITY_SYNC) &&
      (profile_ && profile_->IsSyncAllowed())) {
    pending_waiter_list_.push_back(
        std::make_unique<PrioritySyncReadyWaiter>(profile_));
    PrioritySyncReadyWaiter* waiter_ptr = pending_waiter_list_.back().get();
    waiter_ptr->Start(base::BindOnce(&ExternalPrefLoader::OnPrioritySyncReady,
                                     this, waiter_ptr));
  } else {
    GetExtensionFileTaskRunner()->PostTask(
        FROM_HERE, base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
  }
}

void ExternalPrefLoader::OnPrioritySyncReady(
    ExternalPrefLoader::PrioritySyncReadyWaiter* waiter) {
  // Delete |waiter| from |pending_waiter_list_|.
  pending_waiter_list_.erase(
      std::find_if(pending_waiter_list_.begin(), pending_waiter_list_.end(),
                   [waiter](const std::unique_ptr<PrioritySyncReadyWaiter>& w) {
                     return w.get() == waiter;
                   }));
  // Continue loading.
  GetExtensionFileTaskRunner()->PostTask(
      FROM_HERE, base::BindOnce(&ExternalPrefLoader::LoadOnFileThread, this));
}

// static.
std::unique_ptr<base::DictionaryValue>
ExternalPrefLoader::ExtractExtensionPrefs(base::ValueDeserializer* deserializer,
                                          const base::FilePath& path) {
  std::string error_msg;
  std::unique_ptr<base::Value> extensions =
      deserializer->Deserialize(NULL, &error_msg);
  if (!extensions) {
    LOG(WARNING) << "Unable to deserialize json data: " << error_msg
                 << " in file " << path.value() << ".";
    return std::make_unique<base::DictionaryValue>();
  }

  std::unique_ptr<base::DictionaryValue> ext_dictionary =
      base::DictionaryValue::From(std::move(extensions));
  if (ext_dictionary)
    return ext_dictionary;

  LOG(WARNING) << "Expected a JSON dictionary in file " << path.value() << ".";
  return std::make_unique<base::DictionaryValue>();
}

void ExternalPrefLoader::LoadOnFileThread() {
  base::AssertBlockingAllowed();

  auto prefs = std::make_unique<base::DictionaryValue>();

  // TODO(skerner): Some values of base_path_id_ will cause
  // PathService::Get() to return false, because the path does
  // not exist.  Find and fix the build/install scripts so that
  // this can become a CHECK().  Known examples include chrome
  // OS developer builds and linux install packages.
  // Tracked as crbug.com/70402 .
  if (PathService::Get(base_path_id_, &base_path_)) {
    ReadExternalExtensionPrefFile(prefs.get());

    if (!prefs->empty())
      LOG(WARNING) << "You are using an old-style extension deployment method "
                      "(external_extensions.json), which will soon be "
                      "deprecated. (see http://developer.chrome.com/"
                      "extensions/external_extensions.html)";

    ReadStandaloneExtensionPrefFiles(prefs.get());
  }

  if (base_path_id_ == chrome::DIR_EXTERNAL_EXTENSIONS)
    UMA_HISTOGRAM_COUNTS_100("Extensions.ExternalJsonCount", prefs->size());

  // If we have any records to process, then we must have
  // read at least one .json file.  If so, then we should have
  // set |base_path_|.
  if (!prefs->empty())
    CHECK(!base_path_.empty());

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
                          base::BindOnce(&ExternalPrefLoader::LoadFinished,
                                         this, std::move(prefs)));
}

void ExternalPrefLoader::ReadExternalExtensionPrefFile(
    base::DictionaryValue* prefs) {
  base::AssertBlockingAllowed();
  CHECK(NULL != prefs);

  base::FilePath json_file = base_path_.Append(kExternalExtensionJson);

  if (!base::PathExists(json_file)) {
    // This is not an error.  The file does not exist by default.
    return;
  }

  if (IsOptionSet(ENSURE_PATH_CONTROLLED_BY_ADMIN)) {
#if defined(OS_MACOSX)
    if (!base::VerifyPathControlledByAdmin(json_file)) {
      LOG(ERROR) << "Can not read external extensions source.  The file "
                 << json_file.value() << " and every directory in its path, "
                 << "must be owned by root, have group \"admin\", and not be "
                 << "writable by all users. These restrictions prevent "
                 << "unprivleged users from making chrome install extensions "
                 << "on other users' accounts.";
      return;
    }
#else
    // The only platform that uses this check is Mac OS.  If you add one,
    // you need to implement base::VerifyPathControlledByAdmin() for
    // that platform.
    NOTREACHED();
#endif  // defined(OS_MACOSX)
  }

  JSONFileValueDeserializer deserializer(json_file);
  std::unique_ptr<base::DictionaryValue> ext_prefs =
      ExtractExtensionPrefs(&deserializer, json_file);
  if (ext_prefs)
    prefs->MergeDictionary(ext_prefs.get());
}

void ExternalPrefLoader::ReadStandaloneExtensionPrefFiles(
    base::DictionaryValue* prefs) {
  base::AssertBlockingAllowed();
  CHECK(NULL != prefs);

  // First list the potential .json candidates.
  std::set<base::FilePath>
      candidates = GetPrefsCandidateFilesFromFolder(base_path_);
  if (candidates.empty()) {
    DVLOG(1) << "Extension candidates list empty";
    return;
  }

  // For each file read the json description & build the proper
  // associated prefs.
  for (std::set<base::FilePath>::const_iterator it = candidates.begin();
       it != candidates.end();
       ++it) {
    base::FilePath extension_candidate_path = base_path_.Append(*it);

    std::string id =
#if defined(OS_WIN)
        base::UTF16ToASCII(
            extension_candidate_path.RemoveExtension().BaseName().value());
#elif defined(OS_POSIX)
        extension_candidate_path.RemoveExtension().BaseName().value();
#endif

    DVLOG(1) << "Reading json file: "
             << extension_candidate_path.LossyDisplayName();

    JSONFileValueDeserializer deserializer(extension_candidate_path);
    std::unique_ptr<base::DictionaryValue> ext_prefs =
        ExtractExtensionPrefs(&deserializer, extension_candidate_path);
    if (ext_prefs) {
      DVLOG(1) << "Adding extension with id: " << id;
      prefs->Set(id, std::move(ext_prefs));
    }
  }
}

}  // namespace extensions
