// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ash/customization/customization_document.h"

#include <memory>
#include <utility>

#include "ash/constants/ash_paths.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/i18n/rtl.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram_macros.h"
#include "base/path_service.h"
#include "base/ranges/algorithm.h"
#include "base/strings/pattern.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/time/time.h"
#include "chrome/browser/ash/app_list/app_list_syncable_service.h"
#include "chrome/browser/ash/app_list/app_list_syncable_service_factory.h"
#include "chrome/browser/ash/customization/customization_wallpaper_downloader.h"
#include "chrome/browser/ash/customization/customization_wallpaper_util.h"
#include "chrome/browser/ash/extensions/default_app_order.h"
#include "chrome/browser/ash/login/wizard_controller.h"
#include "chrome/browser/ash/net/delay_network_call.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/extensions/external_loader.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/pref_names.h"
#include "chromeos/ash/components/system/statistics_provider.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/common/extension_urls.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/shared_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"

namespace ash {
namespace {

  // Manifest attributes names.
const char kVersionAttr[] = "version";
const char kDefaultAttr[] = "default";
const char kInitialLocaleAttr[] = "initial_locale";
const char kInitialTimezoneAttr[] = "initial_timezone";
const char kKeyboardLayoutAttr[] = "keyboard_layout";
const char kHwidMapAttr[] = "hwid_map";
const char kHwidMaskAttr[] = "hwid_mask";
const char kSetupContentAttr[] = "setup_content";
const char kEulaPageAttr[] = "eula_page";
const char kDefaultWallpaperAttr[] = "default_wallpaper";
const char kDefaultAppsAttr[] = "default_apps";
const char kLocalizedContent[] = "localized_content";
const char kDefaultAppsFolderName[] = "default_apps_folder_name";
const char kIdAttr[] = "id";

const char kAcceptedManifestVersion[] = "1.0";

// This is subdirectory relative to PathService(DIR_CHROMEOS_CUSTOM_WALLPAPERS),
// where downloaded (and resized) wallpaper is stored.
const char kCustomizationDefaultWallpaperDir[] = "customization";

// The original downloaded image file is stored under this name.
const char kCustomizationDefaultWallpaperDownloadedFile[] =
    "default_downloaded_wallpaper.bin";

// Name of local state option that tracks if services customization has been
// applied.
const char kServicesCustomizationAppliedPref[] = "ServicesCustomizationApplied";

// Maximum number of retries to fetch file if network is not available.
const int kMaxFetchRetries = 3;

// Delay between file fetch retries if network is not available.
const int kRetriesDelayInSec = 2;

// Name of profile option that tracks cached version of service customization.
const char kServicesCustomizationKey[] = "customization.manifest_cache";

// Empty customization document that doesn't customize anything.
const char kEmptyServicesCustomizationManifest[] = "{ \"version\": \"1.0\" }";

constexpr net::NetworkTrafficAnnotationTag kCustomizationDocumentNetworkTag =
    net::DefineNetworkTrafficAnnotation("customization_document",
                                        R"(
        semantics {
          sender: "Customization document"
          description:
            "Get OEM customization manifest from OEM specific URLs that "
            "provide custom configuration locales, wallpaper etc."
          trigger:
            "Triggered on OOBE after user accepts EULA and everytime the "
            "device boots in. Expected to run only once at OOBE. If the "
            "network request fails, retried each boot until it succeeds."
          data: "None."
          destination: GOOGLE_OWNED_SERVICE
        }
        policy {
         cookies_allowed: NO
         setting:
           "This feature is set by OEMs and can be overridden by users."
         policy_exception_justification:
           "This request is made based on OEM customization and does not "
           "send/store any sensitive data."
        })");

struct CustomizationDocumentTestOverride {
  raw_ptr<ServicesCustomizationDocument, ExperimentalAsh>
      customization_document = nullptr;
  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory;
};

// Global overrider for ServicesCustomizationDocument for tests.
CustomizationDocumentTestOverride* g_test_overrides = nullptr;

// Services customization document load results reported via the
// "ServicesCustomization.LoadResult" histogram.
// It is append-only enum due to use in a histogram!
enum HistogramServicesCustomizationLoadResult {
  HISTOGRAM_LOAD_RESULT_SUCCESS = 0,
  HISTOGRAM_LOAD_RESULT_FILE_NOT_FOUND = 1,
  HISTOGRAM_LOAD_RESULT_PARSING_ERROR = 2,
  HISTOGRAM_LOAD_RESULT_RETRIES_FAIL = 3,
  HISTOGRAM_LOAD_RESULT_MAX_VALUE = 4
};

void LogManifestLoadResult(HistogramServicesCustomizationLoadResult result) {
  UMA_HISTOGRAM_ENUMERATION("ServicesCustomization.LoadResult",
                            result,
                            HISTOGRAM_LOAD_RESULT_MAX_VALUE);
}

std::string GetLocaleSpecificStringImpl(const base::Value::Dict& root,
                                        const std::string& locale,
                                        const std::string& dictionary_name,
                                        const std::string& entry_name) {
  const base::Value::Dict* dictionary_content = root.FindDict(dictionary_name);
  if (!dictionary_content)
    return std::string();

  const base::Value::Dict* locale_dictionary =
      dictionary_content->FindDict(locale);
  if (locale_dictionary) {
    const std::string* result = locale_dictionary->FindString(entry_name);
    if (result)
      return *result;
  }

  const base::Value::Dict* default_dictionary =
      dictionary_content->FindDict(kDefaultAttr);
  if (default_dictionary) {
    const std::string* result = default_dictionary->FindString(entry_name);
    if (result)
      return *result;
  }

  return std::string();
}

void CheckWallpaperCacheExists(const base::FilePath& path, bool* exists) {
  DCHECK(exists);
  *exists = base::PathExists(path);
}

std::string ReadFileInBackground(const base::FilePath& file) {
  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                base::BlockingType::MAY_BLOCK);

  std::string manifest;
  if (!base::ReadFileToString(file, &manifest)) {
    manifest.clear();
    LOG(ERROR) << "Failed to load services customization manifest from: "
               << file.value();
  }

  return manifest;
}

}  // anonymous namespace

// Template URL where to fetch OEM services customization manifest from.
const char ServicesCustomizationDocument::kManifestUrl[] =
    "https://ssl.gstatic.com/chrome/chromeos-customization/%s.json";

// A custom extensions::ExternalLoader that the ServicesCustomizationDocument
// creates and uses to publish OEM default apps to the extensions system.
class ServicesCustomizationExternalLoader
    : public extensions::ExternalLoader,
      public base::SupportsWeakPtr<ServicesCustomizationExternalLoader> {
 public:
  explicit ServicesCustomizationExternalLoader(Profile* profile)
      : profile_(profile) {}

  ServicesCustomizationExternalLoader(
      const ServicesCustomizationExternalLoader&) = delete;
  ServicesCustomizationExternalLoader& operator=(
      const ServicesCustomizationExternalLoader&) = delete;

  Profile* profile() { return profile_; }

  // Used by the ServicesCustomizationDocument to update the current apps.
  void SetCurrentApps(base::Value::Dict prefs) {
    apps_ = std::move(prefs);
    is_apps_set_ = true;
    StartLoading();
  }

  // Implementation of extensions::ExternalLoader:
  void StartLoading() override {
    if (!is_apps_set_) {
      ServicesCustomizationDocument::GetInstance()->StartFetching();
      // In case of missing customization ID, SetCurrentApps will be called
      // synchronously from StartFetching and this function will be called
      // recursively so we need to return to avoid calling LoadFinished twice.
      // In case of async load it is safe to return empty list because this
      // provider didn't install any app yet so no app can be removed due to
      // returning empty list.
      if (is_apps_set_)
        return;
    }

    VLOG(1) << "ServicesCustomization extension loader publishing "
            << apps_.size() << " apps.";
    LoadFinished(apps_.Clone());
  }

 protected:
  ~ServicesCustomizationExternalLoader() override {}

 private:
  bool is_apps_set_ = false;
  base::Value::Dict apps_;
  raw_ptr<Profile, ExperimentalAsh> profile_;
};

// CustomizationDocument implementation. ---------------------------------------

CustomizationDocument::CustomizationDocument(
    const std::string& accepted_version)
    : accepted_version_(accepted_version) {}

CustomizationDocument::~CustomizationDocument() {}

bool CustomizationDocument::LoadManifestFromFile(
    const base::FilePath& manifest_path) {
  std::string manifest;
  if (!base::ReadFileToString(manifest_path, &manifest))
    return false;
  return LoadManifestFromString(manifest);
}

bool CustomizationDocument::LoadManifestFromString(
    const std::string& manifest) {
  auto parsed_json = base::JSONReader::ReadAndReturnValueWithError(
      manifest,
      base::JSON_ALLOW_TRAILING_COMMAS | base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  if (!parsed_json.has_value()) {
    LOG(ERROR) << parsed_json.error().message;
    NOTREACHED();
    return false;
  }

  if (!parsed_json->is_dict()) {
    NOTREACHED();
    return false;
  }

  root_ =
      std::make_unique<base::Value::Dict>(std::move(*parsed_json).TakeDict());

  const std::string* result = root_->FindString(kVersionAttr);
  if (!result || *result != accepted_version_) {
    LOG(ERROR) << "Wrong customization manifest version";
    root_.reset();
    return false;
  }

  return true;
}

std::string CustomizationDocument::GetLocaleSpecificString(
    const std::string& locale,
    const std::string& dictionary_name,
    const std::string& entry_name) const {
  return GetLocaleSpecificStringImpl(*root_, locale, dictionary_name,
                                     entry_name);
}

// StartupCustomizationDocument implementation. --------------------------------

StartupCustomizationDocument::StartupCustomizationDocument()
    : CustomizationDocument(kAcceptedManifestVersion) {
  {
    // Loading manifest causes us to do blocking IO on UI thread.
    // Temporarily allow it until we fix http://crosbug.com/11103
    base::ScopedAllowBlocking allow_blocking;
    base::FilePath startup_customization_manifest;
    base::PathService::Get(FILE_STARTUP_CUSTOMIZATION_MANIFEST,
                           &startup_customization_manifest);
    LoadManifestFromFile(startup_customization_manifest);
  }
  Init(system::StatisticsProvider::GetInstance());
}

StartupCustomizationDocument::StartupCustomizationDocument(
    system::StatisticsProvider* statistics_provider,
    const std::string& manifest)
    : CustomizationDocument(kAcceptedManifestVersion) {
  LoadManifestFromString(manifest);
  Init(statistics_provider);
}

StartupCustomizationDocument::~StartupCustomizationDocument() {}

StartupCustomizationDocument* StartupCustomizationDocument::GetInstance() {
  return base::Singleton<
      StartupCustomizationDocument,
      base::DefaultSingletonTraits<StartupCustomizationDocument>>::get();
}

void StartupCustomizationDocument::Init(
    system::StatisticsProvider* statistics_provider) {
  if (IsReady()) {
    const std::string* initial_locale_ptr =
        root_->FindString(kInitialLocaleAttr);
    if (initial_locale_ptr)
      initial_locale_ = *initial_locale_ptr;

    const std::string* initial_timezone_ptr =
        root_->FindString(kInitialTimezoneAttr);
    if (initial_timezone_ptr)
      initial_timezone_ = *initial_timezone_ptr;

    const std::string* keyboard_layout_ptr =
        root_->FindString(kKeyboardLayoutAttr);
    if (keyboard_layout_ptr)
      keyboard_layout_ = *keyboard_layout_ptr;

    if (const absl::optional<base::StringPiece> hwid =
            statistics_provider->GetMachineStatistic(
                system::kHardwareClassKey)) {
      base::Value::List* hwid_list = root_->FindList(kHwidMapAttr);
      if (hwid_list) {
        for (const base::Value& hwid_value : *hwid_list) {
          const base::Value::Dict* hwid_dictionary = nullptr;
          if (hwid_value.is_dict())
            hwid_dictionary = &hwid_value.GetDict();

          const std::string* hwid_mask =
              hwid_dictionary ? hwid_dictionary->FindString(kHwidMaskAttr)
                              : nullptr;
          if (hwid_mask) {
            if (base::MatchPattern(hwid.value(), *hwid_mask)) {
              // If HWID for this machine matches some mask, use HWID specific
              // settings.
              const std::string* initial_locale =
                  hwid_dictionary->FindString(kInitialLocaleAttr);
              if (initial_locale)
                initial_locale_ = *initial_locale;

              const std::string* initial_timezone =
                  hwid_dictionary->FindString(kInitialTimezoneAttr);
              if (initial_timezone)
                initial_timezone_ = *initial_timezone;

              const std::string* keyboard_layout =
                  hwid_dictionary->FindString(kKeyboardLayoutAttr);
              if (keyboard_layout)
                keyboard_layout_ = *keyboard_layout;
            }
            // Don't break here to allow other entires to be applied if match.
          } else {
            LOG(ERROR) << "Syntax error in customization manifest";
          }
        }
      }
    } else {
      LOG(ERROR) << "HWID is missing in machine statistics";
    }
  }

  // If manifest doesn't exist still apply values from VPD.
  if (const absl::optional<base::StringPiece> locale_statistic =
          statistics_provider->GetMachineStatistic(system::kInitialLocaleKey)) {
    initial_locale_ = std::string(locale_statistic.value());
  }
  if (const absl::optional<base::StringPiece> timezone_statistic =
          statistics_provider->GetMachineStatistic(
              system::kInitialTimezoneKey)) {
    initial_timezone_ = std::string(timezone_statistic.value());
  }
  if (const absl::optional<base::StringPiece> keyboard_statistic =
          statistics_provider->GetMachineStatistic(
              system::kKeyboardLayoutKey)) {
    keyboard_layout_ = std::string(keyboard_statistic.value());
  }
  configured_locales_ = base::SplitString(
      initial_locale_, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);

  // Convert ICU locale to chrome ("en_US" to "en-US", etc.).
  base::ranges::for_each(configured_locales_, base::i18n::GetCanonicalLocale);

  // Let's always have configured_locales_.front() a valid entry.
  if (configured_locales_.size() == 0)
    configured_locales_.push_back(std::string());
}

const std::vector<std::string>&
StartupCustomizationDocument::configured_locales() const {
  return configured_locales_;
}

const std::string& StartupCustomizationDocument::initial_locale_default()
    const {
  DCHECK_GT(configured_locales_.size(), 0UL);
  return configured_locales_.front();
}

std::string StartupCustomizationDocument::GetEULAPage(
    const std::string& locale) const {
  return GetLocaleSpecificString(locale, kSetupContentAttr, kEulaPageAttr);
}

// ServicesCustomizationDocument implementation. -------------------------------

class ServicesCustomizationDocument::ApplyingTask {
 public:
  // Registers in ServicesCustomizationDocument;
  explicit ApplyingTask(ServicesCustomizationDocument* document);

  // Do not automatically deregister as we might be called on invalid thread.
  ~ApplyingTask();

  // Mark task finished and check for customization applied.
  void Finished(bool success);

 private:
  raw_ptr<ServicesCustomizationDocument, ExperimentalAsh> document_;

  // This is error-checking flag to prevent destroying unfinished task
  // or double finish.
  bool engaged_;
};

ServicesCustomizationDocument::ApplyingTask::ApplyingTask(
    ServicesCustomizationDocument* document)
    : document_(document), engaged_(true) {
  document->ApplyingTaskStarted();
}

ServicesCustomizationDocument::ApplyingTask::~ApplyingTask() {
  DCHECK(!engaged_);
}

void ServicesCustomizationDocument::ApplyingTask::Finished(bool success) {
  DCHECK(engaged_);
  if (engaged_) {
    engaged_ = false;
    document_->ApplyingTaskFinished(success);
  }
}

ServicesCustomizationDocument::ServicesCustomizationDocument()
    : CustomizationDocument(kAcceptedManifestVersion),
      num_retries_(0),
      load_started_(false),
      apply_tasks_started_(0),
      apply_tasks_finished_(0),
      apply_tasks_success_(0) {}

ServicesCustomizationDocument::ServicesCustomizationDocument(
    const std::string& manifest)
    : CustomizationDocument(kAcceptedManifestVersion),
      apply_tasks_started_(0),
      apply_tasks_finished_(0),
      apply_tasks_success_(0) {
  LoadManifestFromString(manifest);
}

ServicesCustomizationDocument::~ServicesCustomizationDocument() = default;

// static
ServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() {
  if (g_test_overrides)
    return g_test_overrides->customization_document;

  return base::Singleton<
      ServicesCustomizationDocument,
      base::DefaultSingletonTraits<ServicesCustomizationDocument>>::get();
}

// static
void ServicesCustomizationDocument::RegisterPrefs(
    PrefRegistrySimple* registry) {
  registry->RegisterBooleanPref(kServicesCustomizationAppliedPref, false);
  registry->RegisterStringPref(prefs::kCustomizationDefaultWallpaperURL,
                               std::string());
}

// static
void ServicesCustomizationDocument::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterDictionaryPref(kServicesCustomizationKey);
}

// static
bool ServicesCustomizationDocument::WasOOBECustomizationApplied() {
  PrefService* prefs = g_browser_process->local_state();
  // prefs can be NULL in some tests.
  if (prefs)
    return prefs->GetBoolean(kServicesCustomizationAppliedPref);
  else
    return false;
}

// static
void ServicesCustomizationDocument::SetApplied(bool val) {
  PrefService* prefs = g_browser_process->local_state();
  // prefs can be NULL in some tests.
  if (prefs)
    prefs->SetBoolean(kServicesCustomizationAppliedPref, val);
}

// static
base::FilePath ServicesCustomizationDocument::GetCustomizedWallpaperCacheDir() {
  base::FilePath custom_wallpaper_dir;
  if (!base::PathService::Get(chrome::DIR_CHROMEOS_CUSTOM_WALLPAPERS,
                              &custom_wallpaper_dir)) {
    LOG(DFATAL) << "Unable to get custom wallpaper dir.";
    return base::FilePath();
  }
  return custom_wallpaper_dir.Append(kCustomizationDefaultWallpaperDir);
}

// static
base::FilePath
ServicesCustomizationDocument::GetCustomizedWallpaperDownloadedFileName() {
  const base::FilePath dir = GetCustomizedWallpaperCacheDir();
  if (dir.empty()) {
    NOTREACHED();
    return dir;
  }
  return dir.Append(kCustomizationDefaultWallpaperDownloadedFile);
}

void ServicesCustomizationDocument::EnsureCustomizationApplied() {
  if (WasOOBECustomizationApplied())
    return;

  // When customization manifest is fetched, applying will start automatically.
  if (IsReady())
    return;

  StartFetching();
}

base::OnceClosure
ServicesCustomizationDocument::EnsureCustomizationAppliedClosure() {
  return base::BindOnce(
      &ServicesCustomizationDocument::EnsureCustomizationApplied,
      weak_ptr_factory_.GetWeakPtr());
}

void ServicesCustomizationDocument::StartFetching() {
  if (IsReady() || load_started_)
    return;

  if (!url_.is_valid()) {
    system::StatisticsProvider* provider =
        system::StatisticsProvider::GetInstance();
    const absl::optional<base::StringPiece> customization_id =
        provider->GetMachineStatistic(system::kCustomizationIdKey);
    if (customization_id && !customization_id->empty()) {
      url_ = GURL(base::StringPrintf(
          kManifestUrl, base::ToLowerASCII(customization_id.value()).c_str()));
    } else {
      // Remember that there is no customization ID in VPD.
      OnCustomizationNotFound();
      return;
    }
  }

  if (url_.is_valid()) {
    load_started_ = true;
    if (url_.SchemeIsFile()) {
      base::ThreadPool::PostTaskAndReplyWithResult(
          FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
          base::BindOnce(&ReadFileInBackground, base::FilePath(url_.path())),
          base::BindOnce(&ServicesCustomizationDocument::OnManifestRead,
                         weak_ptr_factory_.GetWeakPtr()));
    } else {
      StartFileFetch();
    }
  }
}

void ServicesCustomizationDocument::OnManifestRead(
    const std::string& manifest) {
  if (!manifest.empty())
    LoadManifestFromString(manifest);

  load_started_ = false;
}

void ServicesCustomizationDocument::StartFileFetch() {
  if (custom_network_delay_) {
    DelayNetworkCallWithCustomDelay(
        base::BindOnce(&ServicesCustomizationDocument::DoStartFileFetch,
                       weak_ptr_factory_.GetWeakPtr()),
        custom_network_delay_.value());
  } else {
    DelayNetworkCall(
        base::BindOnce(&ServicesCustomizationDocument::DoStartFileFetch,
                       weak_ptr_factory_.GetWeakPtr()));
  }
}

void ServicesCustomizationDocument::DoStartFileFetch() {
  auto request = std::make_unique<network::ResourceRequest>();
  request->url = url_;
  request->load_flags = net::LOAD_DISABLE_CACHE;
  request->credentials_mode = network::mojom::CredentialsMode::kOmit;
  request->headers.SetHeader("Accept", "application/json");

  url_loader_ = network::SimpleURLLoader::Create(
      std::move(request), kCustomizationDocumentNetworkTag);

  url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
      g_test_overrides ? g_test_overrides->url_loader_factory.get()
                       : g_browser_process->shared_url_loader_factory().get(),
      base::BindOnce(&ServicesCustomizationDocument::OnSimpleLoaderComplete,
                     base::Unretained(this)));
}

bool ServicesCustomizationDocument::LoadManifestFromString(
    const std::string& manifest) {
  if (CustomizationDocument::LoadManifestFromString(manifest)) {
    LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_SUCCESS);
    OnManifestLoaded();
    return true;
  }

  LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_PARSING_ERROR);
  return false;
}

void ServicesCustomizationDocument::OnManifestLoaded() {
  if (!WasOOBECustomizationApplied())
    ApplyOOBECustomization();

  auto prefs = GetDefaultAppsInProviderFormat(*root_);
  for (auto& external_loader : external_loaders_) {
    if (external_loader) {
      UpdateCachedManifest(external_loader->profile());
      external_loader->SetCurrentApps(prefs.Clone());
      SetOemFolderName(external_loader->profile(), *root_);
    }
  }
}

void ServicesCustomizationDocument::OnSimpleLoaderComplete(
    std::unique_ptr<std::string> response_body) {
  int response_code = -1;
  std::string mime_type;
  if (url_loader_->ResponseInfo() && url_loader_->ResponseInfo()->headers) {
    response_code = url_loader_->ResponseInfo()->headers->response_code();
    url_loader_->ResponseInfo()->headers->GetMimeType(&mime_type);
  }

  if (response_body && mime_type == "application/json") {
    LoadManifestFromString(*response_body);
  } else if (response_code == net::HTTP_NOT_FOUND) {
    LOG(ERROR) << "Customization manifest is missing on server: "
               << url_.spec();
    OnCustomizationNotFound();
  } else {
    if (num_retries_ < kMaxFetchRetries) {
      num_retries_++;
      content::GetUIThreadTaskRunner({})->PostDelayedTask(
          FROM_HERE,
          base::BindOnce(&ServicesCustomizationDocument::StartFileFetch,
                         weak_ptr_factory_.GetWeakPtr()),
          base::Seconds(kRetriesDelayInSec));
      return;
    }
    // This doesn't stop fetching manifest on next restart.
    LOG(ERROR) << "URL fetch for services customization failed:"
               << " response code = " << response_code
               << " URL = " << url_.spec();

    LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_RETRIES_FAIL);
  }
  load_started_ = false;
}

bool ServicesCustomizationDocument::ApplyOOBECustomization() {
  if (apply_tasks_started_)
    return false;

  CheckAndApplyWallpaper();
  return false;
}

bool ServicesCustomizationDocument::GetDefaultWallpaperUrl(
    GURL* out_url) const {
  if (!IsReady())
    return false;

  const std::string* url = root_->FindString(kDefaultWallpaperAttr);
  if (!url)
    return false;

  *out_url = GURL(*url);
  return true;
}

absl::optional<base::Value::Dict>
ServicesCustomizationDocument::GetDefaultApps() const {
  if (!IsReady())
    return absl::nullopt;

  return GetDefaultAppsInProviderFormat(*root_);
}

std::string ServicesCustomizationDocument::GetOemAppsFolderName(
    const std::string& locale) const {
  if (!IsReady())
    return std::string();

  return GetOemAppsFolderNameImpl(locale, *root_);
}

base::Value::Dict ServicesCustomizationDocument::GetDefaultAppsInProviderFormat(
    const base::Value::Dict& root) {
  base::Value::Dict prefs;
  const base::Value::List* apps_list = root.FindList(kDefaultAppsAttr);
  if (apps_list) {
    for (const base::Value& app_entry_value : *apps_list) {
      std::string app_id;
      base::Value::Dict entry;
      if (app_entry_value.is_string()) {
        app_id = app_entry_value.GetString();
      } else if (app_entry_value.is_dict()) {
        const base::Value::Dict& app_entry = app_entry_value.GetDict();
        const std::string* app_id_ptr = app_entry.FindString(kIdAttr);
        if (!app_id_ptr) {
          LOG(ERROR) << "Wrong format of default application list";
          prefs.clear();
          break;
        }
        app_id = *app_id_ptr;
        entry = app_entry.Clone();
        entry.Remove(kIdAttr);
      } else {
        LOG(ERROR) << "Wrong format of default application list";
        prefs.clear();
        break;
      }
      if (!entry.Find(extensions::ExternalProviderImpl::kExternalUpdateUrl)) {
        entry.Set(extensions::ExternalProviderImpl::kExternalUpdateUrl,
                  extension_urls::GetWebstoreUpdateUrl().spec());
      }
      prefs.SetByDottedPath(app_id, std::move(entry));
    }
  }

  return prefs;
}

void ServicesCustomizationDocument::UpdateCachedManifest(Profile* profile) {
  profile->GetPrefs()->SetDict(kServicesCustomizationKey, root_->Clone());
}

extensions::ExternalLoader* ServicesCustomizationDocument::CreateExternalLoader(
    Profile* profile) {
  ServicesCustomizationExternalLoader* loader =
      new ServicesCustomizationExternalLoader(profile);
  external_loaders_.push_back(loader->AsWeakPtr());

  if (IsReady()) {
    UpdateCachedManifest(profile);
    loader->SetCurrentApps(GetDefaultAppsInProviderFormat(*root_));
    SetOemFolderName(profile, *root_);
  } else {
    const base::Value::Dict& root =
        profile->GetPrefs()->GetDict(kServicesCustomizationKey);
    if (root.FindString(kVersionAttr)) {
      // If version exists, profile has cached version of customization.
      loader->SetCurrentApps(GetDefaultAppsInProviderFormat(root));
      SetOemFolderName(profile, root);
    } else {
      // StartFetching will be called from ServicesCustomizationExternalLoader
      // when StartLoading is called. We can't initiate manifest fetch here
      // because caller may never call StartLoading for the provider.
    }
  }

  return loader;
}

void ServicesCustomizationDocument::OnCustomizationNotFound() {
  LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_FILE_NOT_FOUND);
  LoadManifestFromString(kEmptyServicesCustomizationManifest);
}

void ServicesCustomizationDocument::SetOemFolderName(
    Profile* profile,
    const base::Value::Dict& root) {
  std::string locale = g_browser_process->GetApplicationLocale();
  std::string name = GetOemAppsFolderNameImpl(locale, root);
  if (name.empty())
    name = chromeos::default_app_order::GetOemAppsFolderName();
  if (!name.empty()) {
    app_list::AppListSyncableService* service =
        app_list::AppListSyncableServiceFactory::GetForProfile(profile);
    if (!service) {
      LOG(WARNING) << "AppListSyncableService is not ready for setting OEM "
                      "folder name";
      return;
    }
    service->SetOemFolderName(name);
  }
}

std::string ServicesCustomizationDocument::GetOemAppsFolderNameImpl(
    const std::string& locale,
    const base::Value::Dict& root) const {
  return GetLocaleSpecificStringImpl(root, locale, kLocalizedContent,
                                     kDefaultAppsFolderName);
}

// static
void ServicesCustomizationDocument::InitializeForTesting(
    scoped_refptr<network::SharedURLLoaderFactory> factory) {
  g_test_overrides = new CustomizationDocumentTestOverride;
  g_test_overrides->customization_document = new ServicesCustomizationDocument;
  // `base::TimeDelta()` means zero time delta - i.e. the request will be
  // started immediately.
  g_test_overrides->customization_document->custom_network_delay_ =
      absl::make_optional(base::TimeDelta());
  g_test_overrides->url_loader_factory = std::move(factory);
}

// static
void ServicesCustomizationDocument::ShutdownForTesting() {
  delete g_test_overrides->customization_document;
  delete g_test_overrides;
  g_test_overrides = nullptr;
}

void ServicesCustomizationDocument::StartOEMWallpaperDownload(
    const GURL& wallpaper_url,
    std::unique_ptr<ServicesCustomizationDocument::ApplyingTask> applying) {
  DCHECK(wallpaper_url.is_valid());

  const base::FilePath dir = GetCustomizedWallpaperCacheDir();
  const base::FilePath file = GetCustomizedWallpaperDownloadedFileName();
  if (dir.empty() || file.empty()) {
    NOTREACHED();
    applying->Finished(false);
    return;
  }

  wallpaper_downloader_ = std::make_unique<CustomizationWallpaperDownloader>(
      wallpaper_url, dir, file,
      base::BindOnce(&ServicesCustomizationDocument::OnOEMWallpaperDownloaded,
                     weak_ptr_factory_.GetWeakPtr(), std::move(applying)));

  wallpaper_downloader_->Start();
}

void ServicesCustomizationDocument::CheckAndApplyWallpaper() {
  if (wallpaper_downloader_.get()) {
    VLOG(1) << "CheckAndApplyWallpaper(): download has already started.";
    return;
  }
  std::unique_ptr<ServicesCustomizationDocument::ApplyingTask> applying(
      new ServicesCustomizationDocument::ApplyingTask(this));

  GURL wallpaper_url;
  if (!GetDefaultWallpaperUrl(&wallpaper_url)) {
    PrefService* pref_service = g_browser_process->local_state();
    std::string current_url =
        pref_service->GetString(prefs::kCustomizationDefaultWallpaperURL);
    if (!current_url.empty()) {
      VLOG(1) << "ServicesCustomizationDocument::CheckAndApplyWallpaper() : "
              << "No wallpaper URL attribute in customization document, "
              << "but current value is non-empty: '" << current_url
              << "'. Ignored.";
    }
    applying->Finished(true);
    return;
  }

  // Should fail if this ever happens in tests.
  DCHECK(wallpaper_url.is_valid());
  if (!wallpaper_url.is_valid()) {
    if (!wallpaper_url.is_empty()) {
      LOG(WARNING) << "Invalid Customized Wallpaper URL '"
                   << wallpaper_url.spec() << "'.";
    }
    applying->Finished(false);
    return;
  }

  std::unique_ptr<bool> exists(new bool(false));

  base::OnceClosure check_file_exists = base::BindOnce(
      &CheckWallpaperCacheExists, GetCustomizedWallpaperDownloadedFileName(),
      base::Unretained(exists.get()));
  base::OnceClosure on_checked_closure = base::BindOnce(
      &ServicesCustomizationDocument::OnCheckedWallpaperCacheExists,
      weak_ptr_factory_.GetWeakPtr(), std::move(exists), std::move(applying));
  base::ThreadPool::PostTaskAndReply(
      FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
      std::move(check_file_exists), std::move(on_checked_closure));
}

void ServicesCustomizationDocument::OnCheckedWallpaperCacheExists(
    std::unique_ptr<bool> exists,
    std::unique_ptr<ServicesCustomizationDocument::ApplyingTask> applying) {
  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
  DCHECK(exists);
  DCHECK(applying);

  ApplyWallpaper(*exists, std::move(applying));
}

void ServicesCustomizationDocument::ApplyWallpaper(
    bool default_wallpaper_file_exists,
    std::unique_ptr<ServicesCustomizationDocument::ApplyingTask> applying) {
  GURL wallpaper_url;
  const bool wallpaper_url_present = GetDefaultWallpaperUrl(&wallpaper_url);

  PrefService* pref_service = g_browser_process->local_state();

  std::string current_url =
      pref_service->GetString(prefs::kCustomizationDefaultWallpaperURL);
  if (current_url != wallpaper_url.spec()) {
    if (wallpaper_url_present) {
      VLOG(1) << "ServicesCustomizationDocument::ApplyWallpaper() : "
              << "Wallpaper URL in customization document '"
              << wallpaper_url.spec() << "' differs from current '"
              << current_url << "'."
              << (GURL(current_url).is_valid() && default_wallpaper_file_exists
                      ? " Ignored."
                      : " Will refetch.");
    } else {
      VLOG(1) << "ServicesCustomizationDocument::ApplyWallpaper() : "
              << "No wallpaper URL attribute in customization document, "
              << "but current value is non-empty: '" << current_url
              << "'. Ignored.";
    }
  }
  if (!wallpaper_url_present) {
    applying->Finished(true);
    return;
  }

  DCHECK(wallpaper_url.is_valid());

  // Never update system-wide wallpaper (i.e. do not check
  // current_url == wallpaper_url.spec() )
  if (GURL(current_url).is_valid() && default_wallpaper_file_exists) {
    VLOG(1)
        << "ServicesCustomizationDocument::ApplyWallpaper() : reuse existing";
    OnOEMWallpaperDownloaded(std::move(applying), true, GURL(current_url));
  } else {
    VLOG(1)
        << "ServicesCustomizationDocument::ApplyWallpaper() : start download";
    StartOEMWallpaperDownload(wallpaper_url, std::move(applying));
  }
}

void ServicesCustomizationDocument::OnOEMWallpaperDownloaded(
    std::unique_ptr<ServicesCustomizationDocument::ApplyingTask> applying,
    bool success,
    const GURL& wallpaper_url) {
  if (success) {
    DCHECK(wallpaper_url.is_valid());

    VLOG(1) << "Setting default wallpaper to '"
            << GetCustomizedWallpaperDownloadedFileName().value() << "' ('"
            << wallpaper_url.spec() << "')";
    customization_wallpaper_util::StartSettingCustomizedDefaultWallpaper(
        wallpaper_url, GetCustomizedWallpaperDownloadedFileName());
  }
  wallpaper_downloader_.reset();
  applying->Finished(success);
}

void ServicesCustomizationDocument::ApplyingTaskStarted() {
  ++apply_tasks_started_;
}

void ServicesCustomizationDocument::ApplyingTaskFinished(bool success) {
  DCHECK_GT(apply_tasks_started_, apply_tasks_finished_);
  ++apply_tasks_finished_;

  apply_tasks_success_ += success;

  if (apply_tasks_started_ != apply_tasks_finished_)
    return;

  if (apply_tasks_success_ == apply_tasks_finished_)
    SetApplied(true);
}

}  // namespace ash
