// Copyright 2019 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/web_applications/manifest_update_task.h"

#include <map>
#include <memory>
#include <utility>
#include <vector>

#include "base/containers/contains.h"
#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/browser_features.h"
#include "chrome/browser/web_applications/os_integration_manager.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/browser/web_applications/web_app_constants.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_icon_manager.h"
#include "chrome/browser/web_applications/web_app_install_manager.h"
#include "chrome/browser/web_applications/web_app_install_utils.h"
#include "chrome/browser/web_applications/web_app_installation_utils.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_registry_update.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/browser/web_applications/web_app_ui_manager.h"
#include "chrome/browser/web_applications/web_application_info.h"
#include "chrome/common/chrome_features.h"
#include "components/webapps/browser/installable/installable_manager.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/manifest/manifest_util.h"
#include "ui/gfx/skia_util.h"

namespace web_app {

namespace {

void HaveIconContentsChanged(
    const std::map<SquareSizePx, SkBitmap>& disk_icon_bitmaps,
    const std::map<SquareSizePx, SkBitmap>& downloaded_icon_bitmaps,
    IconDiff* icon_diff,
    const std::vector<SquareSizePx>& on_disk_sizes,
    const std::vector<SquareSizePx>& downloaded_sizes,
    bool end_when_mismatch_detected) {
  if (downloaded_icon_bitmaps.size() != disk_icon_bitmaps.size()) {
    icon_diff->diff_results |= MISMATCHED_IMAGE_SIZES;
    if (end_when_mismatch_detected)
      return;
  }

  if (on_disk_sizes != downloaded_sizes) {
    icon_diff->diff_results |= MISMATCHED_IMAGE_SIZES;
    if (end_when_mismatch_detected)
      return;
  }

  for (const std::pair<const SquareSizePx, SkBitmap>& entry :
       downloaded_icon_bitmaps) {
    SquareSizePx size = entry.first;
    const SkBitmap& downloaded_bitmap = entry.second;

    auto it = disk_icon_bitmaps.find(size);
    if (it == disk_icon_bitmaps.end()) {
      icon_diff->diff_results |= MISMATCHED_IMAGE_SIZES;
      if (end_when_mismatch_detected)
        return;
      continue;
    }

    const SkBitmap& disk_bitmap = it->second;
    if (!gfx::BitmapsAreEqual(downloaded_bitmap, disk_bitmap)) {
      if (end_when_mismatch_detected) {
        icon_diff->diff_results |= ONE_OR_MORE_ICONS_CHANGED;
        return;
      } else {
        // Icons that are specified in new manifest are of special interest, the
        // rest is auto-generated.
        bool important_icon =
            std::find(downloaded_sizes.begin(), downloaded_sizes.end(), size) !=
            downloaded_sizes.end();
        if (!important_icon) {
          icon_diff->diff_results |= GENERATED_ICON_CHANGED;
        } else if ((icon_diff->diff_results & SINGLE_ICON_CHANGED) == 0 &&
                   (icon_diff->diff_results & MULTIPLE_ICONS_CHANGED) == 0) {
          icon_diff->diff_results |= SINGLE_ICON_CHANGED;
          icon_diff->before = disk_bitmap;
          icon_diff->after = downloaded_bitmap;
        } else if (icon_diff->diff_results & SINGLE_ICON_CHANGED) {
          icon_diff->diff_results &= ~SINGLE_ICON_CHANGED;
          icon_diff->diff_results |= MULTIPLE_ICONS_CHANGED;
          // The UI can only handle showing one image at a time, at the moment.
          icon_diff->before = SkBitmap();
          icon_diff->after = SkBitmap();
          return;
        }
      }
    }
  }
}

// Some apps, such as pre-installed apps, have been vetted and are therefore
// considered safe and permitted to update their names.
bool AllowUnpromptedNameUpdate(const AppId& app_id,
                               const WebAppRegistrar& registrar) {
  const WebApp* web_app = registrar.GetAppById(app_id);
  if (!web_app)
    return false;
  return CanWebAppUpdateIdentity(web_app);
}

// Some apps, such as pre-installed apps, have been vetted and are therefore
// considered safe and permitted to update their icon. For others, the feature
// flag needs to be on.
bool AllowUnpromptedIconUpdate(const AppId& app_id,
                               const WebAppRegistrar& registrar) {
  const WebApp* web_app = registrar.GetAppById(app_id);
  if (!web_app)
    return false;
  return CanWebAppUpdateIdentity(web_app) ||
         base::FeatureList::IsEnabled(features::kWebAppManifestIconUpdating);
}

bool NeedsAppIdentityUpdateDialog(bool title_changing,
                                  bool icons_changing,
                                  const AppId& app_id,
                                  const WebAppRegistrar& registrar) {
  if (title_changing && !AllowUnpromptedNameUpdate(app_id, registrar))
    return true;
  if (icons_changing && !AllowUnpromptedIconUpdate(app_id, registrar))
    return true;
  return false;
}

}  // namespace

IconDiff HaveIconBitmapsChanged(
    const IconBitmaps& disk_icon_bitmaps,
    const IconBitmaps& downloaded_icon_bitmaps,
    const std::vector<apps::IconInfo>& disk_icon_info,
    const std::vector<apps::IconInfo>& downloaded_icon_info,
    bool end_when_mismatch_detected) {
  // The manifest information associated with the icons is a flat vector of
  // IconInfo types. This needs to be split into vectors and keyed by purpose
  // (any, masked, monochrome) so that it can be read by the icon diff.
  std::map<apps::IconInfo::Purpose, std::vector<SquareSizePx>> on_disk_sizes;
  std::map<apps::IconInfo::Purpose, std::vector<SquareSizePx>> downloaded_sizes;
  on_disk_sizes[apps::IconInfo::Purpose::kAny] = std::vector<SquareSizePx>();
  downloaded_sizes[apps::IconInfo::Purpose::kAny] = std::vector<SquareSizePx>();
  on_disk_sizes[apps::IconInfo::Purpose::kMaskable] =
      std::vector<SquareSizePx>();
  downloaded_sizes[apps::IconInfo::Purpose::kMaskable] =
      std::vector<SquareSizePx>();
  on_disk_sizes[apps::IconInfo::Purpose::kMonochrome] =
      std::vector<SquareSizePx>();
  downloaded_sizes[apps::IconInfo::Purpose::kMonochrome] =
      std::vector<SquareSizePx>();
  // Put each entry found into the right map (sort by purpose).
  for (auto entry : disk_icon_info) {
    on_disk_sizes[entry.purpose].push_back(entry.square_size_px.value_or(-1));
  }
  for (auto entry : downloaded_icon_info) {
    downloaded_sizes[entry.purpose].push_back(
        entry.square_size_px.value_or(-1));
  }

  IconDiff icon_diff;
  HaveIconContentsChanged(disk_icon_bitmaps.any, downloaded_icon_bitmaps.any,
                          &icon_diff,
                          on_disk_sizes[apps::IconInfo::Purpose::kAny],
                          downloaded_sizes[apps::IconInfo::Purpose::kAny],
                          end_when_mismatch_detected);
  if (icon_diff.mismatch() && end_when_mismatch_detected)
    return icon_diff;

  HaveIconContentsChanged(disk_icon_bitmaps.maskable,
                          downloaded_icon_bitmaps.maskable, &icon_diff,
                          on_disk_sizes[apps::IconInfo::Purpose::kMaskable],
                          downloaded_sizes[apps::IconInfo::Purpose::kMaskable],
                          end_when_mismatch_detected);
  if (icon_diff.mismatch() && end_when_mismatch_detected)
    return icon_diff;

  HaveIconContentsChanged(
      disk_icon_bitmaps.monochrome, downloaded_icon_bitmaps.monochrome,
      &icon_diff, on_disk_sizes[apps::IconInfo::Purpose::kMonochrome],
      downloaded_sizes[apps::IconInfo::Purpose::kMonochrome],
      end_when_mismatch_detected);
  return icon_diff;
}

ManifestUpdateTask::ManifestUpdateTask(
    const GURL& url,
    const AppId& app_id,
    content::WebContents* web_contents,
    StoppedCallback stopped_callback,
    bool hang_for_testing,
    const WebAppRegistrar& registrar,
    const WebAppIconManager& icon_manager,
    WebAppUiManager* ui_manager,
    WebAppInstallManager* install_manager,
    OsIntegrationManager& os_integration_manager,
    WebAppSyncBridge* sync_bridge)
    : content::WebContentsObserver(web_contents),
      registrar_(registrar),
      icon_manager_(icon_manager),
      ui_manager_(*ui_manager),
      install_manager_(*install_manager),
      os_integration_manager_(os_integration_manager),
      sync_bridge_(sync_bridge),
      url_(url),
      app_id_(app_id),
      stopped_callback_(std::move(stopped_callback)),
      hang_for_testing_(hang_for_testing) {
  // Task starts by waiting for DidFinishLoad() to be called.
  stage_ = Stage::kPendingPageLoad;
}

ManifestUpdateTask::~ManifestUpdateTask() {
#if DCHECK_IS_ON()
  if (destructor_called_ptr_) {
    DCHECK(!(*destructor_called_ptr_));
    *destructor_called_ptr_ = true;
  }
#endif
}

// content::WebContentsObserver:
void ManifestUpdateTask::DidFinishLoad(
    content::RenderFrameHost* render_frame_host,
    const GURL& validated_url) {
  if (stage_ != Stage::kPendingPageLoad || hang_for_testing_)
    return;

  if (render_frame_host->GetParent() != nullptr)
    return;

  stage_ = Stage::kPendingInstallableData;
  webapps::InstallableParams params;
  params.valid_primary_icon = true;
  params.valid_manifest = true;
  params.check_webapp_manifest_display = false;
  webapps::InstallableManager::FromWebContents(web_contents())
      ->GetData(params,
                base::BindOnce(&ManifestUpdateTask::OnDidGetInstallableData,
                               AsWeakPtr()));
}

// content::WebContentsObserver:
void ManifestUpdateTask::WebContentsDestroyed() {
  switch (stage_) {
    case Stage::kPendingPageLoad:
    case Stage::kPendingInstallableData:
    case Stage::kPendingIconDownload:
    case Stage::kPendingIconReadFromDisk:
    case Stage::kPendingAppIdentityCheck:
      DestroySelf(ManifestUpdateResult::kWebContentsDestroyed);
      return;
    case Stage::kPendingWindowsClosed:
    case Stage::kPendingMaybeReadExistingIcons:
    case Stage::kPendingInstallation:
    case Stage::kPendingAssociationsUpdate:
      // These stages should have stopped listening to the web contents.
      NOTREACHED() << static_cast<int>(stage_);
      Observe(nullptr);
      break;
  }
}

void ManifestUpdateTask::OnDidGetInstallableData(
    const webapps::InstallableData& data) {
  DCHECK_EQ(stage_, Stage::kPendingInstallableData);

  if (!data.NoBlockingErrors()) {
    DestroySelf(ManifestUpdateResult::kAppNotEligible);
    return;
  }

  web_application_info_.emplace();
  UpdateWebAppInfoFromManifest(data.manifest, data.manifest_url,
                               &web_application_info_.value());

  // We cannot allow the app ID to change via the manifest changing. We rely on
  // fixed app IDs to determine whether web apps installed in the user sync
  // profile has been sync installed across devices. If we allowed the app ID to
  // change then the sync system would try to redeploy the old app indefinitely,
  // additionally the new app ID would get added to the sync profile. This has
  // the potential to flood the user sync profile with an infinite number of
  // apps should the site be serving a random start_url on every navigation.
  if (app_id_ != GenerateAppId(web_application_info_->manifest_id,
                               web_application_info_->start_url)) {
    DestroySelf(ManifestUpdateResult::kAppIdMismatch);
    return;
  }

  if (IsUpdateNeededForManifest()) {
    UpdateAfterWindowsClose();
    return;
  }

  LoadAndCheckIconContents();
}

bool ManifestUpdateTask::IsUpdateNeededForManifest() const {
  DCHECK(web_application_info_.has_value());
  const WebApp* app = registrar_.GetAppById(app_id_);
  DCHECK(app);

  bool title_changing =
      web_application_info_->title != base::UTF8ToUTF16(app->name());
  bool icons_changing =
      web_application_info_->manifest_icons != app->manifest_icons();
  if (!NeedsAppIdentityUpdateDialog(title_changing, icons_changing, app_id_,
                                    registrar_)) {
    if (title_changing && AllowUnpromptedNameUpdate(app_id_, registrar_)) {
      return true;
    }
    if (icons_changing && AllowUnpromptedIconUpdate(app_id_, registrar_)) {
      return true;
    }
  }

  // Allows updating start_url and manifest_id when kWebAppEnableManifestId is
  // enabled. Both fields are allowed to change as long as the app_id generated
  // from them doesn't change.
  if (base::FeatureList::IsEnabled(blink::features::kWebAppEnableManifestId)) {
    if (web_application_info_->manifest_id != app->manifest_id())
      return true;
    if (web_application_info_->start_url != app->start_url())
      return true;
  }

  if (web_application_info_->theme_color != app->theme_color())
    return true;

  if (web_application_info_->scope != app->scope())
    return true;

  if (web_application_info_->display_mode != app->display_mode())
    return true;

  if (web_application_info_->display_override != app->display_mode_override())
    return true;

  if (web_application_info_->shortcuts_menu_item_infos !=
      app->shortcuts_menu_item_infos()) {
    return true;
  }

  if (web_application_info_->share_target != app->share_target())
    return true;

  if (web_application_info_->protocol_handlers != app->protocol_handlers())
    return true;

  if (web_application_info_->url_handlers != app->url_handlers())
    return true;

  if (web_application_info_->note_taking_new_note_url !=
      app->note_taking_new_note_url()) {
    return true;
  }

  if (web_application_info_->capture_links != app->capture_links())
    return true;

  if (os_integration_manager_.IsFileHandlingAPIAvailable(app_id_) &&
      app->file_handlers() != web_application_info_->file_handlers) {
    return true;
  }

  if (web_application_info_->background_color != app->background_color())
    return true;

  if (web_application_info_->dark_mode_theme_color !=
      app->dark_mode_theme_color()) {
    return true;
  }

  if (web_application_info_->manifest_url != app->manifest_url())
    return true;

  if (web_application_info_->launch_handler != app->launch_handler())
    return true;

  // TODO(crbug.com/1212849): Handle changes to is_storage_isolated.

  // TODO(crbug.com/926083): Check more manifest fields.
  return false;
}

void ManifestUpdateTask::UpdateAfterWindowsClose() {
  DCHECK(stage_ == Stage::kPendingInstallableData ||
         stage_ == Stage::kPendingAppIdentityCheck);
  stage_ = Stage::kPendingWindowsClosed;
  Observe(nullptr);

  ui_manager_.NotifyOnAllAppWindowsClosed(
      app_id_,
      base::BindOnce(&ManifestUpdateTask::OnAllAppWindowsClosed, AsWeakPtr()));
}

void ManifestUpdateTask::LoadAndCheckIconContents() {
  DCHECK_EQ(stage_, Stage::kPendingInstallableData);
  stage_ = Stage::kPendingIconDownload;

  DCHECK(web_application_info_.has_value());
  std::vector<GURL> icon_urls =
      GetValidIconUrlsToDownload(*web_application_info_);
  icon_downloader_.emplace(
      web_contents(), std::move(icon_urls),
      WebAppIconDownloader::Histogram::kForUpdate,
      base::BindOnce(&ManifestUpdateTask::OnIconsDownloaded, AsWeakPtr()));
  icon_downloader_->SkipPageFavicons();
  icon_downloader_->FailAllIfAnyFail();
  icon_downloader_->Start();
}

void ManifestUpdateTask::OnIconsDownloaded(
    IconsDownloadedResult result,
    IconsMap icons_map,
    DownloadedIconsHttpResults icons_http_results) {
  DCHECK_EQ(stage_, Stage::kPendingIconDownload);

  if (result != IconsDownloadedResult::kCompleted) {
    DestroySelf(ManifestUpdateResult::kIconDownloadFailed);
    return;
  }
  // TODO(crbug.com/1238622): Report `result` and `DownloadedIconsHttpResults`in
  // UMA and internals.

  stage_ = Stage::kPendingIconReadFromDisk;
  icon_manager_.ReadAllIcons(
      app_id_, base::BindOnce(&ManifestUpdateTask::OnAllIconsRead, AsWeakPtr(),
                              std::move(icons_map)));
}

void ManifestUpdateTask::OnAllIconsRead(IconsMap downloaded_icons_map,
                                        IconBitmaps disk_icon_bitmaps) {
  DCHECK_EQ(stage_, Stage::kPendingIconReadFromDisk);

  if (disk_icon_bitmaps.empty()) {
    DestroySelf(ManifestUpdateResult::kIconReadFromDiskFailed);
    return;
  }
  DCHECK(web_application_info_.has_value());

  stage_ = Stage::kPendingAppIdentityCheck;

  // These calls populate the |web_application_info_| with all icon bitmap
  // data.
  // If this data does not match what we already have on disk, then an update
  // is necessary.
  // TODO(https://crbug.com/1184911): Reuse this data in the web app install
  // task.
  PopulateOtherIcons(&web_application_info_.value(), downloaded_icons_map);
  PopulateProductIcons(&web_application_info_.value(), &downloaded_icons_map);

  if (!base::FeatureList::IsEnabled(features::kPwaUpdateDialogForNameAndIcon)) {
    OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped);
    return;
  }

  IconDiff icon_diff = IsUpdateNeededForIconContents(disk_icon_bitmaps);
  std::u16string old_title =
      base::UTF8ToUTF16(registrar_.GetAppShortName(app_id_));
  std::u16string new_title = web_application_info_->title;

  bool title_change = old_title != new_title;
  bool icon_change = icon_diff.mismatch();

  if (!title_change && !icon_change) {
    OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped);
    return;
  }

  if (!NeedsAppIdentityUpdateDialog(title_change, icon_change, app_id_,
                                    registrar_)) {
    // The app identity update can be skipped, because any update not requiring
    // the AppIdentityUpdate dialog should have been triggered already by
    // running IsUpdateNeededForManifest. It doesn't matter a great deal whether
    // kSkipped or kAllowed is used here, except that updating should also work
    // without approval here. So to be safe we return kSkipped.
    OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped);
    return;
  }

  if (icon_change && !icon_diff.supported_for_app_identity_check()) {
    OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped);
    return;
  }

  // Note: If icon and name changes are to be actually used later and not
  // overridden, then OnPostAppIdentityUpdateCheck must be called with
  // |AppIdentityUpdate::kAllowed| so |app_identity_update_allowed_| is true.
  SkBitmap* before_icon = nullptr;
  SkBitmap* after_icon = nullptr;
  if (icon_diff.mismatch()) {
    before_icon = &icon_diff.before;
    after_icon = &icon_diff.after;
  } else {
    auto it = disk_icon_bitmaps.any.find(web_app::kWebAppIconSmall);
    if (it != disk_icon_bitmaps.any.end()) {
      before_icon = &it->second;
      after_icon = &it->second;
    }
  }

  if (before_icon == nullptr || after_icon == nullptr ||
      before_icon->drawsNothing() || after_icon->drawsNothing()) {
    OnPostAppIdentityUpdateCheck(AppIdentityUpdate::kSkipped);
    return;
  }

  content::WebContents* web_contents = WebContentsObserver::web_contents();
  ui_manager_.ShowWebAppIdentityUpdateDialog(
      app_id_, title_change, icon_diff.mismatch(), old_title, new_title,
      *before_icon, *after_icon, web_contents,
      base::BindOnce(&ManifestUpdateTask::OnPostAppIdentityUpdateCheck,
                     AsWeakPtr()));

  // Flow continues in OnPostAppIdentityUpdateCheck, once an action has been
  // taken in the dialog.
}

void ManifestUpdateTask::OnPostAppIdentityUpdateCheck(
    AppIdentityUpdate app_identity_update_allowed) {
  DCHECK_EQ(stage_, Stage::kPendingAppIdentityCheck);
  Observe(nullptr);
  app_identity_update_allowed_ =
      app_identity_update_allowed == AppIdentityUpdate::kAllowed;
  if (app_identity_update_allowed_) {
    UpdateAfterWindowsClose();
    return;
  }

  icon_manager_.ReadAllShortcutsMenuIcons(
      app_id_, base::BindOnce(&ManifestUpdateTask::OnAllShortcutsMenuIconsRead,
                              AsWeakPtr()));
}

IconDiff ManifestUpdateTask::IsUpdateNeededForIconContents(
    const IconBitmaps& disk_icon_bitmaps) const {
  DCHECK(web_application_info_.has_value());
  const WebApp* app = registrar_.GetAppById(app_id_);
  DCHECK(app);

  return HaveIconBitmapsChanged(
      disk_icon_bitmaps, web_application_info_->icon_bitmaps,
      web_application_info_->manifest_icons, app->manifest_icons(),
      /* end_when_mismatch_detected= */ false);
}

void ManifestUpdateTask::OnAllShortcutsMenuIconsRead(
    ShortcutsMenuIconBitmaps disk_shortcuts_menu_icon_bitmaps) {
  DCHECK_EQ(stage_, Stage::kPendingAppIdentityCheck);

  DCHECK(web_application_info_.has_value());

  if (IsUpdateNeededForShortcutsMenuIconsContents(
          disk_shortcuts_menu_icon_bitmaps)) {
    UpdateAfterWindowsClose();
    return;
  }

  NoManifestUpdateRequired();
}

bool ManifestUpdateTask::IsUpdateNeededForShortcutsMenuIconsContents(
    const ShortcutsMenuIconBitmaps& disk_shortcuts_menu_icon_bitmaps) const {
  DCHECK(web_application_info_.has_value());
  const ShortcutsMenuIconBitmaps& downloaded_shortcuts_menu_icon_bitmaps =
      web_application_info_->shortcuts_menu_icon_bitmaps;
  if (downloaded_shortcuts_menu_icon_bitmaps.size() !=
      disk_shortcuts_menu_icon_bitmaps.size()) {
    return true;
  }

  const WebApp* app = registrar_.GetAppById(app_id_);
  DCHECK(app);
  for (size_t i = 0; i < downloaded_shortcuts_menu_icon_bitmaps.size(); ++i) {
    const IconBitmaps& downloaded_icon_bitmaps =
        downloaded_shortcuts_menu_icon_bitmaps[i];
    const IconBitmaps& disk_icon_bitmaps = disk_shortcuts_menu_icon_bitmaps[i];
    if (HaveIconBitmapsChanged(disk_icon_bitmaps, downloaded_icon_bitmaps,
                               web_application_info_->manifest_icons,
                               app->manifest_icons(),
                               /* end_when_mismatch_detected= */ true)
            .mismatch())
      return true;
  }

  return false;
}

bool ManifestUpdateTask::IsUpdateNeededForWebAppOriginAssociations() const {
  // Web app origin association update is tied to the manifest update process.
  // If there are url handlers for the current app, associations need to be
  // revalidated.
  DCHECK(web_application_info_.has_value());
  return !web_application_info_->url_handlers.empty();
}

void ManifestUpdateTask::NoManifestUpdateRequired() {
  DCHECK_EQ(stage_, Stage::kPendingAppIdentityCheck);
  stage_ = Stage::kPendingAssociationsUpdate;
  if (!IsUpdateNeededForWebAppOriginAssociations()) {
    DestroySelf(ManifestUpdateResult::kAppUpToDate);
    return;
  }

  os_integration_manager_.UpdateUrlHandlers(
      app_id_,
      base::BindOnce(&ManifestUpdateTask::OnWebAppOriginAssociationsUpdated,
                     AsWeakPtr()));
}

void ManifestUpdateTask::OnWebAppOriginAssociationsUpdated(bool success) {
  DCHECK_EQ(stage_, Stage::kPendingAssociationsUpdate);
  success ? DestroySelf(ManifestUpdateResult::kAppAssociationsUpdated)
          : DestroySelf(ManifestUpdateResult::kAppAssociationsUpdateFailed);
}

void ManifestUpdateTask::OnAllAppWindowsClosed() {
  DCHECK_EQ(stage_, Stage::kPendingWindowsClosed);

  DCHECK(web_application_info_.has_value());

  if (!AllowUnpromptedNameUpdate(app_id_, registrar_) &&
      !app_identity_update_allowed_) {
    // The app's name must not change due to an automatic update, except for
    // default installed apps (that have been vetted).
    // TODO(crbug.com/1088338): Provide a safe way for apps to update their
    // name.
    web_application_info_->title =
        base::UTF8ToUTF16(registrar_.GetAppShortName(app_id_));
  }

  // Preserve the user's choice of form factor to open the app with.
  web_application_info_->user_display_mode =
      registrar_.GetAppUserDisplayMode(app_id_);

  stage_ = Stage::kPendingMaybeReadExistingIcons;
  // If icon updating is disabled, then read the existing icons so they can be
  // populated on the WebApplicationInfo.
  if (AllowUnpromptedIconUpdate(app_id_, registrar_) ||
      app_identity_update_allowed_) {
    OnExistingIconsRead(IconBitmaps());
    return;
  }
  icon_manager_.ReadAllIcons(
      app_id_,
      base::BindOnce(&ManifestUpdateTask::OnExistingIconsRead, AsWeakPtr()));
}

void ManifestUpdateTask::OnExistingIconsRead(IconBitmaps icon_bitmaps) {
  DCHECK_EQ(stage_, Stage::kPendingMaybeReadExistingIcons);

  bool redownload_app_icons = icon_bitmaps.empty();
  if (!redownload_app_icons)
    web_application_info_->icon_bitmaps = std::move(icon_bitmaps);

  stage_ = Stage::kPendingInstallation;
  install_manager_.UpdateWebAppFromInfo(
      app_id_, std::make_unique<WebApplicationInfo>(*web_application_info_),
      /*redownload_app_icons=*/redownload_app_icons,
      base::BindOnce(&ManifestUpdateTask::OnInstallationComplete, AsWeakPtr()));
}

void ManifestUpdateTask::OnInstallationComplete(
    const AppId& app_id,
    InstallResultCode code) {
  DCHECK_EQ(stage_, Stage::kPendingInstallation);

  if (!IsSuccess(code)) {
    DestroySelf(ManifestUpdateResult::kAppUpdateFailed);
    return;
  }

  DCHECK_EQ(app_id_, app_id);
  DCHECK(!IsUpdateNeededForManifest());
  DCHECK_EQ(code, InstallResultCode::kSuccessAlreadyInstalled);

  sync_bridge_->SetAppManifestUpdateTime(app_id, base::Time::Now());

  DestroySelf(ManifestUpdateResult::kAppUpdated);
}

void ManifestUpdateTask::DestroySelf(ManifestUpdateResult result) {
  // Asserts that calling the callback results in |this| getting deleted.
#if DCHECK_IS_ON()
  bool destructor_called = false;
  destructor_called_ptr_ = &destructor_called;
#endif
  std::move(stopped_callback_).Run(*this, result);
#if DCHECK_IS_ON()
  DCHECK(destructor_called);
#endif
}

}  // namespace web_app
