// Copyright 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/extensions/extension_sync_service.h"

#include <iterator>

#include "base/basictypes.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_restrictions.h"
#include "chrome/browser/extensions/app_sync_data.h"
#include "chrome/browser/extensions/bookmark_app_helper.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/extension_sync_data.h"
#include "chrome/browser/extensions/extension_sync_service_factory.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/launch_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/glue/sync_start_util.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/extensions/sync_helper.h"
#include "chrome/common/web_application_info.h"
#include "components/sync_driver/sync_prefs.h"
#include "extensions/browser/app_sorting.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_icon_set.h"
#include "extensions/common/feature_switch.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
#include "sync/api/sync_change.h"
#include "sync/api/sync_error_factory.h"
#include "ui/gfx/image/image_family.h"

using extensions::Extension;
using extensions::ExtensionPrefs;
using extensions::ExtensionRegistry;
using extensions::FeatureSwitch;

namespace {

void OnWebApplicationInfoLoaded(
    WebApplicationInfo synced_info,
    base::WeakPtr<ExtensionService> extension_service,
    const WebApplicationInfo& loaded_info) {
  DCHECK_EQ(synced_info.app_url, loaded_info.app_url);

  if (!extension_service)
    return;

  // Use the old icons if they exist.
  synced_info.icons = loaded_info.icons;
  CreateOrUpdateBookmarkApp(extension_service.get(), synced_info);
}

}  // namespace

ExtensionSyncService::ExtensionSyncService(Profile* profile,
                                           ExtensionPrefs* extension_prefs,
                                           ExtensionService* extension_service)
    : profile_(profile),
      extension_prefs_(extension_prefs),
      extension_service_(extension_service),
      app_sync_bundle_(this),
      extension_sync_bundle_(this),
      pending_app_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
                               extension_prefs_->pref_service())),
                           &app_sync_bundle_,
                           syncer::APPS),
      pending_extension_enables_(make_scoped_ptr(new sync_driver::SyncPrefs(
                                     extension_prefs_->pref_service())),
                                 &extension_sync_bundle_,
                                 syncer::EXTENSIONS) {
  SetSyncStartFlare(sync_start_util::GetFlareForSyncableService(
      profile_->GetPath()));

  extension_service_->set_extension_sync_service(this);
  extension_prefs_->app_sorting()->SetExtensionSyncService(this);
}

ExtensionSyncService::~ExtensionSyncService() {}

// static
ExtensionSyncService* ExtensionSyncService::Get(Profile* profile) {
  return ExtensionSyncServiceFactory::GetForProfile(profile);
}

syncer::SyncChange ExtensionSyncService::PrepareToSyncUninstallExtension(
    const extensions::Extension* extension, bool extensions_ready) {
  // Extract the data we need for sync now, but don't actually sync until we've
  // completed the uninstallation.
  // TODO(tim): If we get here and IsSyncing is false, this will cause
  // "back from the dead" style bugs, because sync will add-back the extension
  // that was uninstalled here when MergeDataAndStartSyncing is called.
  // See crbug.com/256795.
  if (extensions::util::ShouldSyncApp(extension, profile_)) {
    if (app_sync_bundle_.IsSyncing())
      return app_sync_bundle_.CreateSyncChangeToDelete(extension);
    else if (extensions_ready && !flare_.is_null())
      flare_.Run(syncer::APPS);  // Tell sync to start ASAP.
  } else if (extensions::sync_helper::IsSyncableExtension(extension)) {
    if (extension_sync_bundle_.IsSyncing())
      return extension_sync_bundle_.CreateSyncChangeToDelete(extension);
    else if (extensions_ready && !flare_.is_null())
      flare_.Run(syncer::EXTENSIONS);  // Tell sync to start ASAP.
  }

  return syncer::SyncChange();
}

void ExtensionSyncService::ProcessSyncUninstallExtension(
    const std::string& extension_id,
    const syncer::SyncChange& sync_change) {
  if (app_sync_bundle_.HasExtensionId(extension_id) &&
      sync_change.sync_data().GetDataType() == syncer::APPS) {
    app_sync_bundle_.ProcessDeletion(extension_id, sync_change);
  } else if (extension_sync_bundle_.HasExtensionId(extension_id) &&
             sync_change.sync_data().GetDataType() == syncer::EXTENSIONS) {
    extension_sync_bundle_.ProcessDeletion(extension_id, sync_change);
  }
}

void ExtensionSyncService::SyncEnableExtension(
    const extensions::Extension& extension) {

  // Syncing may not have started yet, so handle pending enables.
  if (extensions::util::ShouldSyncApp(&extension, profile_))
    pending_app_enables_.OnExtensionEnabled(extension.id());

  if (extensions::util::ShouldSyncExtension(&extension, profile_))
    pending_extension_enables_.OnExtensionEnabled(extension.id());

  SyncExtensionChangeIfNeeded(extension);
}

void ExtensionSyncService::SyncDisableExtension(
    const extensions::Extension& extension) {

  // Syncing may not have started yet, so handle pending enables.
  if (extensions::util::ShouldSyncApp(&extension, profile_))
    pending_app_enables_.OnExtensionDisabled(extension.id());

  if (extensions::util::ShouldSyncExtension(&extension, profile_))
    pending_extension_enables_.OnExtensionDisabled(extension.id());

  SyncExtensionChangeIfNeeded(extension);
}

syncer::SyncMergeResult ExtensionSyncService::MergeDataAndStartSyncing(
    syncer::ModelType type,
    const syncer::SyncDataList& initial_sync_data,
    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
    scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
  CHECK(sync_processor.get());
  CHECK(sync_error_factory.get());

  switch (type) {
    case syncer::EXTENSIONS:
      extension_sync_bundle_.SetupSync(sync_processor.release(),
                                       sync_error_factory.release(),
                                       initial_sync_data);
      pending_extension_enables_.OnSyncStarted(extension_service_);
      break;

    case syncer::APPS:
      app_sync_bundle_.SetupSync(sync_processor.release(),
                                 sync_error_factory.release(),
                                 initial_sync_data);
      pending_app_enables_.OnSyncStarted(extension_service_);
      break;

    default:
      LOG(FATAL) << "Got " << type << " ModelType";
  }

  // Process local extensions.
  // TODO(yoz): Determine whether pending extensions should be considered too.
  //            See crbug.com/104399.
  syncer::SyncDataList sync_data_list = GetAllSyncData(type);
  syncer::SyncChangeList sync_change_list;
  for (syncer::SyncDataList::const_iterator i = sync_data_list.begin();
       i != sync_data_list.end();
       ++i) {
    switch (type) {
        case syncer::EXTENSIONS:
          sync_change_list.push_back(
              extension_sync_bundle_.CreateSyncChange(*i));
          break;
        case syncer::APPS:
          sync_change_list.push_back(app_sync_bundle_.CreateSyncChange(*i));
          break;
      default:
        LOG(FATAL) << "Got " << type << " ModelType";
    }
  }


  if (type == syncer::EXTENSIONS) {
    extension_sync_bundle_.ProcessSyncChangeList(sync_change_list);
  } else if (type == syncer::APPS) {
    app_sync_bundle_.ProcessSyncChangeList(sync_change_list);
  }

  return syncer::SyncMergeResult(type);
}

void ExtensionSyncService::StopSyncing(syncer::ModelType type) {
  if (type == syncer::APPS) {
    app_sync_bundle_.Reset();
  } else if (type == syncer::EXTENSIONS) {
    extension_sync_bundle_.Reset();
  }
}

syncer::SyncDataList ExtensionSyncService::GetAllSyncData(
    syncer::ModelType type) const {
  if (type == syncer::EXTENSIONS)
    return extension_sync_bundle_.GetAllSyncData();
  if (type == syncer::APPS)
    return app_sync_bundle_.GetAllSyncData();

  // We should only get sync data for extensions and apps.
  NOTREACHED();

  return syncer::SyncDataList();
}

syncer::SyncError ExtensionSyncService::ProcessSyncChanges(
    const tracked_objects::Location& from_here,
    const syncer::SyncChangeList& change_list) {
  for (syncer::SyncChangeList::const_iterator i = change_list.begin();
      i != change_list.end();
      ++i) {
    syncer::ModelType type = i->sync_data().GetDataType();
    if (type == syncer::EXTENSIONS) {
      extension_sync_bundle_.ProcessSyncChange(
          extensions::ExtensionSyncData(*i));
    } else if (type == syncer::APPS) {
      app_sync_bundle_.ProcessSyncChange(extensions::AppSyncData(*i));
    }
  }

  extension_prefs_->app_sorting()->FixNTPOrdinalCollisions();

  return syncer::SyncError();
}

extensions::ExtensionSyncData ExtensionSyncService::GetExtensionSyncData(
    const Extension& extension) const {
  return extensions::ExtensionSyncData(
      extension,
      extension_service_->IsExtensionEnabled(extension.id()),
      extensions::util::IsIncognitoEnabled(extension.id(), profile_),
      extension_prefs_->HasDisableReason(extension.id(),
                                         Extension::DISABLE_REMOTE_INSTALL));
}

extensions::AppSyncData ExtensionSyncService::GetAppSyncData(
    const Extension& extension) const {
  return extensions::AppSyncData(
      extension,
      extension_service_->IsExtensionEnabled(extension.id()),
      extensions::util::IsIncognitoEnabled(extension.id(), profile_),
      extension_prefs_->HasDisableReason(extension.id(),
                                         Extension::DISABLE_REMOTE_INSTALL),
      extension_prefs_->app_sorting()->GetAppLaunchOrdinal(extension.id()),
      extension_prefs_->app_sorting()->GetPageOrdinal(extension.id()),
      extensions::GetLaunchTypePrefValue(extension_prefs_, extension.id()));
}

std::vector<extensions::ExtensionSyncData>
  ExtensionSyncService::GetExtensionSyncDataList() const {
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
  std::vector<extensions::ExtensionSyncData> extension_sync_list;
  extension_sync_bundle_.GetExtensionSyncDataListHelper(
      registry->enabled_extensions(), &extension_sync_list);
  extension_sync_bundle_.GetExtensionSyncDataListHelper(
      registry->disabled_extensions(), &extension_sync_list);
  extension_sync_bundle_.GetExtensionSyncDataListHelper(
      registry->terminated_extensions(), &extension_sync_list);

  std::vector<extensions::ExtensionSyncData> pending_extensions =
      extension_sync_bundle_.GetPendingData();
  extension_sync_list.insert(extension_sync_list.begin(),
                             pending_extensions.begin(),
                             pending_extensions.end());

  return extension_sync_list;
}

std::vector<extensions::AppSyncData> ExtensionSyncService::GetAppSyncDataList()
    const {
  ExtensionRegistry* registry = ExtensionRegistry::Get(profile_);
  std::vector<extensions::AppSyncData> app_sync_list;
  app_sync_bundle_.GetAppSyncDataListHelper(
      registry->enabled_extensions(), &app_sync_list);
  app_sync_bundle_.GetAppSyncDataListHelper(
      registry->disabled_extensions(), &app_sync_list);
  app_sync_bundle_.GetAppSyncDataListHelper(
      registry->terminated_extensions(), &app_sync_list);

  std::vector<extensions::AppSyncData> pending_apps =
      app_sync_bundle_.GetPendingData();
  app_sync_list.insert(app_sync_list.begin(),
                       pending_apps.begin(),
                       pending_apps.end());

  return app_sync_list;
}

bool ExtensionSyncService::ProcessExtensionSyncData(
    const extensions::ExtensionSyncData& extension_sync_data) {
  if (!ProcessExtensionSyncDataHelper(extension_sync_data,
                                      syncer::EXTENSIONS)) {
    extension_sync_bundle_.AddPendingExtension(extension_sync_data.id(),
                                               extension_sync_data);
    extension_service_->CheckForUpdatesSoon();
    return false;
  }

  return true;
}

bool ExtensionSyncService::ProcessAppSyncData(
    const extensions::AppSyncData& app_sync_data) {
  const std::string& id = app_sync_data.id();

  if (app_sync_data.app_launch_ordinal().IsValid() &&
      app_sync_data.page_ordinal().IsValid()) {
    extension_prefs_->app_sorting()->SetAppLaunchOrdinal(
        id,
        app_sync_data.app_launch_ordinal());
    extension_prefs_->app_sorting()->SetPageOrdinal(
        id,
        app_sync_data.page_ordinal());
  }

  // The corresponding validation of this value during AppSyncData population
  // is in AppSyncData::PopulateAppSpecifics.
  if (app_sync_data.launch_type() >= extensions::LAUNCH_TYPE_FIRST &&
      app_sync_data.launch_type() < extensions::NUM_LAUNCH_TYPES) {
    extensions::SetLaunchType(extension_service_, id,
                              app_sync_data.launch_type());
  }

  if (!app_sync_data.bookmark_app_url().empty())
    ProcessBookmarkAppSyncData(app_sync_data);

  if (!ProcessExtensionSyncDataHelper(app_sync_data.extension_sync_data(),
                                      syncer::APPS)) {
    app_sync_bundle_.AddPendingApp(id, app_sync_data);
    extension_service_->CheckForUpdatesSoon();
    return false;
  }

  return true;
}

void ExtensionSyncService::ProcessBookmarkAppSyncData(
    const extensions::AppSyncData& app_sync_data) {
  // Process bookmark app sync if necessary.
  GURL bookmark_app_url(app_sync_data.bookmark_app_url());
  if (!bookmark_app_url.is_valid() ||
      app_sync_data.extension_sync_data().uninstalled()) {
    return;
  }

  const extensions::Extension* extension =
      extension_service_->GetInstalledExtension(
          app_sync_data.extension_sync_data().id());

  // Return if there are no bookmark app details that need updating.
  if (extension && extension->non_localized_name() ==
                       app_sync_data.extension_sync_data().name() &&
      extension->description() == app_sync_data.bookmark_app_description()) {
    return;
  }

  WebApplicationInfo web_app_info;
  web_app_info.app_url = bookmark_app_url;
  web_app_info.title =
      base::UTF8ToUTF16(app_sync_data.extension_sync_data().name());
  web_app_info.description =
      base::UTF8ToUTF16(app_sync_data.bookmark_app_description());

  // If the bookmark app already exists, keep the old icons.
  if (!extension) {
    CreateOrUpdateBookmarkApp(extension_service_, web_app_info);
  } else {
    app_sync_data.extension_sync_data().name();
    GetWebApplicationInfoFromApp(profile_,
                                 extension,
                                 base::Bind(&OnWebApplicationInfoLoaded,
                                            web_app_info,
                                            extension_service_->AsWeakPtr()));
  }
}

void ExtensionSyncService::SyncOrderingChange(const std::string& extension_id) {
  const extensions::Extension* ext = extension_service_->GetInstalledExtension(
      extension_id);

  if (ext)
    SyncExtensionChangeIfNeeded(*ext);
}

void ExtensionSyncService::SetSyncStartFlare(
    const syncer::SyncableService::StartSyncFlare& flare) {
  flare_ = flare;
}

bool ExtensionSyncService::IsCorrectSyncType(const Extension& extension,
                                         syncer::ModelType type) const {
  if (type == syncer::EXTENSIONS &&
      extensions::sync_helper::IsSyncableExtension(&extension)) {
    return true;
  }

  if (type == syncer::APPS &&
      extensions::sync_helper::IsSyncableApp(&extension)) {
    return true;
  }

  return false;
}

bool ExtensionSyncService::IsPendingEnable(
    const std::string& extension_id) const {
  return pending_app_enables_.Contains(extension_id) ||
      pending_extension_enables_.Contains(extension_id);
}

bool ExtensionSyncService::ProcessExtensionSyncDataHelper(
    const extensions::ExtensionSyncData& extension_sync_data,
    syncer::ModelType type) {
  const std::string& id = extension_sync_data.id();
  const Extension* extension = extension_service_->GetInstalledExtension(id);

  // TODO(bolms): we should really handle this better.  The particularly bad
  // case is where an app becomes an extension or vice versa, and we end up with
  // a zombie extension that won't go away.
  if (extension && !IsCorrectSyncType(*extension, type))
    return true;

  // Handle uninstalls first.
  if (extension_sync_data.uninstalled()) {
    if (!extension_service_->UninstallExtensionHelper(extension_service_, id)) {
      LOG(WARNING) << "Could not uninstall extension " << id
                   << " for sync";
    }
    return true;
  }

  // Extension from sync was uninstalled by the user as external extensions.
  // Honor user choice and skip installation/enabling.
  if (extensions::ExtensionPrefs::Get(profile_)
          ->IsExternalExtensionUninstalled(id)) {
    LOG(WARNING) << "Extension with id " << id
                 << " from sync was uninstalled as external extension";
    return true;
  }

  // Set user settings.
  // If the extension has been disabled from sync, it may not have
  // been installed yet, so we don't know if the disable reason was a
  // permissions increase.  That will be updated once CheckPermissionsIncrease
  // is called for it.
  // However if the extension is marked as a remote install in sync, we know
  // what the disable reason is, so set it to that directly. Note that when
  // CheckPermissionsIncrease runs, it might still add permissions increase
  // as a disable reason for the extension.
  if (extension_sync_data.enabled()) {
    extension_service_->EnableExtension(id);
  } else if (!IsPendingEnable(id)) {
    if (extension_sync_data.remote_install()) {
      extension_service_->DisableExtension(id,
                                           Extension::DISABLE_REMOTE_INSTALL);
    } else {
      extension_service_->DisableExtension(
          id, Extension::DISABLE_UNKNOWN_FROM_SYNC);
    }
  }

  // We need to cache some version information here because setting the
  // incognito flag invalidates the |extension| pointer (it reloads the
  // extension).
  bool extension_installed = (extension != NULL);
  int version_compare_result = extension ?
      extension->version()->CompareTo(extension_sync_data.version()) : 0;

  // If the target extension has already been installed ephemerally, it can
  // be promoted to a regular installed extension and downloading from the Web
  // Store is not necessary.
  if (extension && extensions::util::IsEphemeralApp(id, profile_))
    extension_service_->PromoteEphemeralApp(extension, true);

  // Update the incognito flag.
  extensions::util::SetIsIncognitoEnabled(
      id, profile_, extension_sync_data.incognito_enabled());
  extension = NULL;  // No longer safe to use.

  if (extension_installed) {
    // If the extension is already installed, check if it's outdated.
    if (version_compare_result < 0) {
      // Extension is outdated.
      return false;
    }
  } else {
    // TODO(akalin): Replace silent update with a list of enabled
    // permissions.
    const bool kInstallSilently = true;

    CHECK(type == syncer::EXTENSIONS || type == syncer::APPS);
    extensions::PendingExtensionInfo::ShouldAllowInstallPredicate filter =
        (type == syncer::APPS) ? extensions::sync_helper::IsSyncableApp :
                                 extensions::sync_helper::IsSyncableExtension;

    if (!extension_service_->pending_extension_manager()->AddFromSync(
            id,
            extension_sync_data.update_url(),
            filter,
            kInstallSilently,
            extension_sync_data.remote_install())) {
      LOG(WARNING) << "Could not add pending extension for " << id;
      // This means that the extension is already pending installation, with a
      // non-INTERNAL location.  Add to pending_sync_data, even though it will
      // never be removed (we'll never install a syncable version of the
      // extension), so that GetAllSyncData() continues to send it.
    }
    // Track pending extensions so that we can return them in GetAllSyncData().
    return false;
  }

  return true;
}

void ExtensionSyncService::SyncExtensionChangeIfNeeded(
    const Extension& extension) {
  if (extensions::util::ShouldSyncApp(&extension, profile_)) {
    if (app_sync_bundle_.IsSyncing())
      app_sync_bundle_.SyncChangeIfNeeded(extension);
    else if (extension_service_->is_ready() && !flare_.is_null())
      flare_.Run(syncer::APPS);
  } else if (extensions::util::ShouldSyncExtension(&extension, profile_)) {
    if (extension_sync_bundle_.IsSyncing())
      extension_sync_bundle_.SyncChangeIfNeeded(extension);
    else if (extension_service_->is_ready() && !flare_.is_null())
      flare_.Run(syncer::EXTENSIONS);
  }
}
