chromium/chrome/browser/ui/webui/ash/crostini_upgrader/crostini_upgrader_dialog.cc

// Copyright 2019 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/ui/webui/ash/crostini_upgrader/crostini_upgrader_dialog.h"

#include "ash/public/cpp/shelf_types.h"
#include "ash/public/cpp/window_properties.h"
#include "base/metrics/histogram_functions.h"
#include "chrome/browser/ash/crostini/crostini_manager.h"
#include "chrome/browser/ash/crostini/crostini_simple_types.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/ash/crostini_upgrader/crostini_upgrader_ui.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/grit/chrome_unscaled_resources.h"
#include "chrome/grit/generated_resources.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

namespace {
// The dialog content area size. Note that the height is less than the design
// spec to compensate for title bar height.
constexpr int kDialogWidth = 768;
constexpr int kDialogHeight = 608;

GURL GetUrl() {
  return GURL{chrome::kChromeUICrostiniUpgraderUrl};
}
}  // namespace

namespace ash {

void CrostiniUpgraderDialog::Show(Profile* profile,
                                  base::OnceClosure launch_closure,
                                  bool only_run_launch_closure_on_restart) {
  if (Reshow()) {
    return;
  }

  auto* instance = new CrostiniUpgraderDialog(
      profile, std::move(launch_closure), only_run_launch_closure_on_restart);
  instance->ShowSystemDialog();
  EmitUpgradeDialogEventHistogram(crostini::UpgradeDialogEvent::kDialogShown);
}

bool CrostiniUpgraderDialog::Reshow() {
  auto* instance = SystemWebDialogDelegate::FindInstance(GetUrl().spec());
  if (instance) {
    instance->Focus();
    return true;
  }
  return false;
}

CrostiniUpgraderDialog::CrostiniUpgraderDialog(
    Profile* profile,
    base::OnceClosure launch_closure,
    bool only_run_launch_closure_on_restart)
    : SystemWebDialogDelegate(GetUrl(), /*title=*/{}),
      profile_(profile),
      only_run_launch_closure_on_restart_(only_run_launch_closure_on_restart),
      launch_closure_{std::move(launch_closure)} {
  DCHECK(profile_);
  crostini::CrostiniManager::GetForProfile(profile_)->SetCrostiniDialogStatus(
      crostini::DialogType::UPGRADER, true);
  set_can_minimize(true);
  set_can_resize(false);
}

CrostiniUpgraderDialog::~CrostiniUpgraderDialog() {
  if (deletion_closure_for_testing_) {
    std::move(deletion_closure_for_testing_).Run();
  }
  crostini::CrostiniManager::GetForProfile(profile_)->SetCrostiniDialogStatus(
      crostini::DialogType::UPGRADER, false);
}

void CrostiniUpgraderDialog::GetDialogSize(gfx::Size* size) const {
  size->SetSize(::kDialogWidth, ::kDialogHeight);
}

bool CrostiniUpgraderDialog::ShouldShowCloseButton() const {
  return false;
}

bool CrostiniUpgraderDialog::ShouldShowDialogTitle() const {
  return true;
}

bool CrostiniUpgraderDialog::ShouldCloseDialogOnEscape() const {
  return false;
}

void CrostiniUpgraderDialog::AdjustWidgetInitParams(
    views::Widget::InitParams* params) {
  params->z_order = ui::ZOrderLevel::kNormal;

  const ShelfID shelf_id(Id());
  params->init_properties_container.SetProperty(kShelfIDKey,
                                                shelf_id.Serialize());
  params->init_properties_container.SetProperty<int>(kShelfItemTypeKey,
                                                     TYPE_DIALOG);

  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
  params->init_properties_container.SetProperty(
      aura::client::kAppIconKey,
      rb.GetImageNamed(IDR_LOGO_CROSTINI_DEFAULT).AsImageSkia());
}

void CrostiniUpgraderDialog::SetDeletionClosureForTesting(
    base::OnceClosure deletion_closure_for_testing) {
  deletion_closure_for_testing_ = std::move(deletion_closure_for_testing);
}

bool CrostiniUpgraderDialog::OnDialogCloseRequested() {
  if (deletion_closure_for_testing_) {
    // Running in a test.
    return true;
  }
  return !upgrader_ui_ || upgrader_ui_->RequestClosePage();
}

namespace {
void RunLaunchClosure(base::WeakPtr<crostini::CrostiniManager> crostini_manager,
                      base::OnceClosure launch_closure,
                      bool only_run_launch_closure_on_restart,
                      bool restart_required) {
  if (!crostini_manager) {
    return;
  }
  if (!restart_required) {
    if (!only_run_launch_closure_on_restart) {
      std::move(launch_closure).Run();
    }
    return;
  }
  crostini_manager->RestartCrostini(
      crostini::DefaultContainerId(),
      base::BindOnce(
          [](base::OnceClosure launch_closure,
             crostini::CrostiniResult result) {
            if (result != crostini::CrostiniResult::SUCCESS) {
              LOG(ERROR)
                  << "Failed to restart crostini after upgrade. Error code: "
                  << static_cast<int>(result);
              return;
            }
            if (launch_closure.is_null() || launch_closure.IsCancelled()) {
              return;
            }
            std::move(launch_closure).Run();
          },
          std::move(launch_closure)));
}
}  // namespace

void CrostiniUpgraderDialog::OnDialogShown(content::WebUI* webui) {
  upgrader_ui_ =
      static_cast<CrostiniUpgraderUI*>(webui->GetController())->GetWeakPtr();
  upgrader_ui_->set_launch_callback(base::BindOnce(
      &RunLaunchClosure,
      crostini::CrostiniManager::GetForProfile(profile_)->GetWeakPtr(),
      std::move(launch_closure_), only_run_launch_closure_on_restart_));
  return SystemWebDialogDelegate::OnDialogShown(webui);
}

void CrostiniUpgraderDialog::EmitUpgradeDialogEventHistogram(
    crostini::UpgradeDialogEvent event) {
  base::UmaHistogramEnumeration("Crostini.UpgradeDialogEvent", event);
}

void CrostiniUpgraderDialog::OnWebContentsFinishedLoad() {
  DCHECK(dialog_window());
  dialog_window()->SetTitle(
      l10n_util::GetStringUTF16(IDS_CROSTINI_UPGRADER_TITLE));
}

}  // namespace ash