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

#include <algorithm>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/file_util.h"
#include "base/files/file_path.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.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/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/customization_wallpaper_downloader.h"
#include "chrome/browser/chromeos/extensions/default_app_order.h"
#include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
#include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/chromeos/net/delay_network_call.h"
#include "chrome/browser/extensions/external_loader.h"
#include "chrome/browser/extensions/external_provider_impl.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service.h"
#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chromeos/system/statistics_provider.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_status_code.h"
#include "net/url_request/url_fetcher.h"
#include "ui/base/l10n/l10n_util.h"

using content::BrowserThread;

namespace chromeos {
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 kAcceptedManifestVersion[] = "1.0";

// Path to OEM partner startup customization manifest.
const char kStartupCustomizationManifestPath[] =
    "/opt/oem/etc/startup_manifest.json";

// 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\" }";

// Global overrider for ServicesCustomizationDocument for tests.
ServicesCustomizationDocument* g_test_services_customization_document = NULL;

// 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::DictionaryValue* root,
    const std::string& locale,
    const std::string& dictionary_name,
    const std::string& entry_name) {
  const base::DictionaryValue* dictionary_content = NULL;
  if (!root || !root->GetDictionary(dictionary_name, &dictionary_content))
    return std::string();

  const base::DictionaryValue* locale_dictionary = NULL;
  if (dictionary_content->GetDictionary(locale, &locale_dictionary)) {
    std::string result;
    if (locale_dictionary->GetString(entry_name, &result))
      return result;
  }

  const base::DictionaryValue* default_dictionary = NULL;
  if (dictionary_content->GetDictionary(kDefaultAttr, &default_dictionary)) {
    std::string result;
    if (default_dictionary->GetString(entry_name, &result))
      return result;
  }

  return std::string();
}

void CheckWallpaperCacheExists(const base::FilePath& path, bool* exists) {
  DCHECK(content::BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
  DCHECK(exists);
  *exists = base::PathExists(path);
}

}  // 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)
      : is_apps_set_(false), profile_(profile) {}

  Profile* profile() { return profile_; }

  // Used by the ServicesCustomizationDocument to update the current apps.
  void SetCurrentApps(scoped_ptr<base::DictionaryValue> prefs) {
    apps_.Swap(prefs.get());
    is_apps_set_ = true;
    StartLoading();
  }

  // Implementation of extensions::ExternalLoader:
  virtual 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;
    }

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

 protected:
  virtual ~ServicesCustomizationExternalLoader() {}

 private:
  bool is_apps_set_;
  base::DictionaryValue apps_;
  Profile* profile_;

  DISALLOW_COPY_AND_ASSIGN(ServicesCustomizationExternalLoader);
};

// 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) {
  int error_code = 0;
  std::string error;
  scoped_ptr<base::Value> root(base::JSONReader::ReadAndReturnError(manifest,
      base::JSON_ALLOW_TRAILING_COMMAS, &error_code, &error));
  if (error_code != base::JSONReader::JSON_NO_ERROR)
    LOG(ERROR) << error;
  DCHECK(root.get() != NULL);
  if (root.get() == NULL)
    return false;
  DCHECK(root->GetType() == base::Value::TYPE_DICTIONARY);
  if (root->GetType() == base::Value::TYPE_DICTIONARY) {
    root_.reset(static_cast<base::DictionaryValue*>(root.release()));
    std::string result;
    if (root_->GetString(kVersionAttr, &result) &&
        result == accepted_version_)
      return true;

    LOG(ERROR) << "Wrong customization manifest version";
    root_.reset(NULL);
  }
  return false;
}

std::string CustomizationDocument::GetLocaleSpecificString(
    const std::string& locale,
    const std::string& dictionary_name,
    const std::string& entry_name) const {
  return GetLocaleSpecificStringImpl(
      root_.get(), 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::ThreadRestrictions::ScopedAllowIO allow_io;
    LoadManifestFromFile(base::FilePath(kStartupCustomizationManifestPath));
  }
  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 Singleton<StartupCustomizationDocument,
      DefaultSingletonTraits<StartupCustomizationDocument> >::get();
}

void StartupCustomizationDocument::Init(
    system::StatisticsProvider* statistics_provider) {
  if (IsReady()) {
    root_->GetString(kInitialLocaleAttr, &initial_locale_);
    root_->GetString(kInitialTimezoneAttr, &initial_timezone_);
    root_->GetString(kKeyboardLayoutAttr, &keyboard_layout_);

    std::string hwid;
    if (statistics_provider->GetMachineStatistic(
            system::kHardwareClassKey, &hwid)) {
      base::ListValue* hwid_list = NULL;
      if (root_->GetList(kHwidMapAttr, &hwid_list)) {
        for (size_t i = 0; i < hwid_list->GetSize(); ++i) {
          base::DictionaryValue* hwid_dictionary = NULL;
          std::string hwid_mask;
          if (hwid_list->GetDictionary(i, &hwid_dictionary) &&
              hwid_dictionary->GetString(kHwidMaskAttr, &hwid_mask)) {
            if (MatchPattern(hwid, hwid_mask)) {
              // If HWID for this machine matches some mask, use HWID specific
              // settings.
              std::string result;
              if (hwid_dictionary->GetString(kInitialLocaleAttr, &result))
                initial_locale_ = result;

              if (hwid_dictionary->GetString(kInitialTimezoneAttr, &result))
                initial_timezone_ = result;

              if (hwid_dictionary->GetString(kKeyboardLayoutAttr, &result))
                keyboard_layout_ = result;
            }
            // 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.
  statistics_provider->GetMachineStatistic(kInitialLocaleAttr,
                                           &initial_locale_);
  statistics_provider->GetMachineStatistic(kInitialTimezoneAttr,
                                           &initial_timezone_);
  statistics_provider->GetMachineStatistic(kKeyboardLayoutAttr,
                                           &keyboard_layout_);
  configured_locales_.resize(0);
  base::SplitString(initial_locale_, ',', &configured_locales_);

  // Convert ICU locale to chrome ("en_US" to "en-US", etc.).
  std::for_each(configured_locales_.begin(),
                configured_locales_.end(),
                l10n_util::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(configured_locales_.size() > 0);
  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:
  ServicesCustomizationDocument* 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),
      fetch_started_(false),
      network_delay_(
          base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)),
      apply_tasks_started_(0),
      apply_tasks_finished_(0),
      apply_tasks_success_(0),
      weak_ptr_factory_(this) {
}

ServicesCustomizationDocument::ServicesCustomizationDocument(
    const std::string& manifest)
    : CustomizationDocument(kAcceptedManifestVersion),
      network_delay_(
          base::TimeDelta::FromMilliseconds(kDefaultNetworkRetryDelayMS)),
      apply_tasks_started_(0),
      apply_tasks_finished_(0),
      apply_tasks_success_(0),
      weak_ptr_factory_(this) {
  LoadManifestFromString(manifest);
}

ServicesCustomizationDocument::~ServicesCustomizationDocument() {}

// static
ServicesCustomizationDocument* ServicesCustomizationDocument::GetInstance() {
  if (g_test_services_customization_document)
    return g_test_services_customization_document;

  return Singleton<ServicesCustomizationDocument,
      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,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

// 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 (!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::Closure
ServicesCustomizationDocument::EnsureCustomizationAppliedClosure() {
  return base::Bind(&ServicesCustomizationDocument::EnsureCustomizationApplied,
                    weak_ptr_factory_.GetWeakPtr());
}

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

  if (!url_.is_valid()) {
    std::string customization_id;
    chromeos::system::StatisticsProvider* provider =
        chromeos::system::StatisticsProvider::GetInstance();
    if (provider->GetMachineStatistic(system::kCustomizationIdKey,
                                      &customization_id) &&
        !customization_id.empty()) {
      url_ = GURL(base::StringPrintf(
          kManifestUrl, base::StringToLowerASCII(customization_id).c_str()));
    } else {
      // Remember that there is no customization ID in VPD.
      OnCustomizationNotFound();
      return;
    }
  }

  if (url_.is_valid()) {
    fetch_started_ = true;
    if (url_.SchemeIsFile()) {
      BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
          base::Bind(&ServicesCustomizationDocument::ReadFileInBackground,
                     weak_ptr_factory_.GetWeakPtr(),
                     base::FilePath(url_.path())));
    } else {
      StartFileFetch();
    }
  }
}

// static
void ServicesCustomizationDocument::ReadFileInBackground(
    base::WeakPtr<ServicesCustomizationDocument> self,
    const base::FilePath& file) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));

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

  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(&ServicesCustomizationDocument::OnManifesteRead,
                 self,
                 manifest));
}

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

  fetch_started_ = false;
}

void ServicesCustomizationDocument::StartFileFetch() {
  DelayNetworkCall(base::Bind(&ServicesCustomizationDocument::DoStartFileFetch,
                              weak_ptr_factory_.GetWeakPtr()),
      network_delay_);
}

void ServicesCustomizationDocument::DoStartFileFetch() {
  url_fetcher_.reset(net::URLFetcher::Create(
      url_, net::URLFetcher::GET, this));
  url_fetcher_->SetRequestContext(g_browser_process->system_request_context());
  url_fetcher_->AddExtraRequestHeader("Accept: application/json");
  url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
                             net::LOAD_DO_NOT_SAVE_COOKIES |
                             net::LOAD_DISABLE_CACHE |
                             net::LOAD_DO_NOT_SEND_AUTH_DATA);
  url_fetcher_->Start();
}

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();

  scoped_ptr<base::DictionaryValue> prefs =
      GetDefaultAppsInProviderFormat(*root_);
  for (ExternalLoaders::iterator it = external_loaders_.begin();
       it != external_loaders_.end(); ++it) {
    if (*it) {
      UpdateCachedManifest((*it)->profile());
      (*it)->SetCurrentApps(
          scoped_ptr<base::DictionaryValue>(prefs->DeepCopy()));
      SetOemFolderName((*it)->profile(), *root_);
    }
  }
}

void ServicesCustomizationDocument::OnURLFetchComplete(
    const net::URLFetcher* source) {
  std::string mime_type;
  std::string data;
  if (source->GetStatus().is_success() &&
      source->GetResponseCode() == net::HTTP_OK &&
      source->GetResponseHeaders()->GetMimeType(&mime_type) &&
      mime_type == "application/json" &&
      source->GetResponseAsString(&data)) {
    LoadManifestFromString(data);
  } else if (source->GetResponseCode() == net::HTTP_NOT_FOUND) {
    LOG(ERROR) << "Customization manifest is missing on server: "
               << source->GetURL().spec();
    OnCustomizationNotFound();
  } else {
    if (num_retries_ < kMaxFetchRetries) {
      num_retries_++;
      content::BrowserThread::PostDelayedTask(
          content::BrowserThread::UI,
          FROM_HERE,
          base::Bind(&ServicesCustomizationDocument::StartFileFetch,
                     weak_ptr_factory_.GetWeakPtr()),
          base::TimeDelta::FromSeconds(kRetriesDelayInSec));
      return;
    }
    // This doesn't stop fetching manifest on next restart.
    LOG(ERROR) << "URL fetch for services customization failed:"
               << " response code = " << source->GetResponseCode()
               << " URL = " << source->GetURL().spec();

    LogManifestLoadResult(HISTOGRAM_LOAD_RESULT_RETRIES_FAIL);
  }
  fetch_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;

  std::string url;
  if (!root_->GetString(kDefaultWallpaperAttr, &url))
    return false;

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

bool ServicesCustomizationDocument::GetDefaultApps(
    std::vector<std::string>* ids) const {
  ids->clear();
  if (!IsReady())
    return false;

  base::ListValue* apps_list = NULL;
  if (!root_->GetList(kDefaultAppsAttr, &apps_list))
    return false;

  for (size_t i = 0; i < apps_list->GetSize(); ++i) {
    std::string app_id;
    if (apps_list->GetString(i, &app_id)) {
      ids->push_back(app_id);
    } else {
      LOG(ERROR) << "Wrong format of default application list";
      return false;
    }
  }

  return true;
}

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

  return GetOemAppsFolderNameImpl(locale, *root_);
}

scoped_ptr<base::DictionaryValue>
ServicesCustomizationDocument::GetDefaultAppsInProviderFormat(
    const base::DictionaryValue& root) {
  scoped_ptr<base::DictionaryValue> prefs(new base::DictionaryValue);
  const base::ListValue* apps_list = NULL;
  if (root.GetList(kDefaultAppsAttr, &apps_list)) {
    for (size_t i = 0; i < apps_list->GetSize(); ++i) {
      std::string app_id;
      if (apps_list->GetString(i, &app_id)) {
        base::DictionaryValue* entry = new base::DictionaryValue;
        entry->SetString(extensions::ExternalProviderImpl::kExternalUpdateUrl,
                         extension_urls::GetWebstoreUpdateUrl().spec());
        prefs->Set(app_id, entry);
      } else {
        LOG(ERROR) << "Wrong format of default application list";
        prefs->Clear();
        break;
      }
    }
  }

  return prefs.Pass();
}

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

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::DictionaryValue* root =
        profile->GetPrefs()->GetDictionary(kServicesCustomizationKey);
    std::string version;
    if (root && root->GetString(kVersionAttr, &version)) {
      // 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::DictionaryValue& root) {
  std::string locale = g_browser_process->GetApplicationLocale();
  std::string name = GetOemAppsFolderNameImpl(locale, root);
  if (name.empty())
    name = 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::DictionaryValue& root) const {
  return GetLocaleSpecificStringImpl(
      &root, locale, kLocalizedContent, kDefaultAppsFolderName);
}

// static
void ServicesCustomizationDocument::InitializeForTesting() {
  g_test_services_customization_document = new ServicesCustomizationDocument;
  g_test_services_customization_document->network_delay_ = base::TimeDelta();
}

// static
void ServicesCustomizationDocument::ShutdownForTesting() {
  delete g_test_services_customization_document;
  g_test_services_customization_document = NULL;
}

void ServicesCustomizationDocument::StartOEMWallpaperDownload(
    const GURL& wallpaper_url,
    scoped_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_.reset(new CustomizationWallpaperDownloader(
      g_browser_process->system_request_context(),
      wallpaper_url,
      dir,
      file,
      base::Bind(&ServicesCustomizationDocument::OnOEMWallpaperDownloaded,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(applying.Pass()))));

  wallpaper_downloader_->Start();
}

void ServicesCustomizationDocument::CheckAndApplyWallpaper() {
  if (wallpaper_downloader_.get()) {
    VLOG(1) << "CheckAndApplyWallpaper(): download has already started.";
    return;
  }
  scoped_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;
  }

  scoped_ptr<bool> exists(new bool(false));

  base::Closure check_file_exists =
      base::Bind(&CheckWallpaperCacheExists,
                 GetCustomizedWallpaperDownloadedFileName(),
                 base::Unretained(exists.get()));
  base::Closure on_checked_closure =
      base::Bind(&ServicesCustomizationDocument::OnCheckedWallpaperCacheExists,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Passed(exists.Pass()),
                 base::Passed(applying.Pass()));
  if (!content::BrowserThread::PostBlockingPoolTaskAndReply(
          FROM_HERE, check_file_exists, on_checked_closure)) {
    LOG(WARNING) << "Failed to start check Wallpaper cache exists.";
  }
}

void ServicesCustomizationDocument::OnCheckedWallpaperCacheExists(
    scoped_ptr<bool> exists,
    scoped_ptr<ServicesCustomizationDocument::ApplyingTask> applying) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
  DCHECK(exists);
  DCHECK(applying);

  ApplyWallpaper(*exists, applying.Pass());
}

void ServicesCustomizationDocument::ApplyWallpaper(
    bool default_wallpaper_file_exists,
    scoped_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(applying.Pass(), true, GURL(current_url));
  } else {
    VLOG(1)
        << "ServicesCustomizationDocument::ApplyWallpaper() : start download";
    StartOEMWallpaperDownload(wallpaper_url, applying.Pass());
  }
}

void ServicesCustomizationDocument::OnOEMWallpaperDownloaded(
    scoped_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() << "')";
    WallpaperManager::Get()->SetCustomizedDefaultWallpaper(
        wallpaper_url,
        GetCustomizedWallpaperDownloadedFileName(),
        GetCustomizedWallpaperCacheDir());
  }
  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 chromeos
