1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
// Copyright 2024 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/skyvault/local_files_migration_page_handler.h"
#include "base/functional/callback.h"
#include "base/i18n/time_formatting.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/timer/wall_clock_timer.h"
#include "chrome/browser/ash/policy/skyvault/policy_utils.h"
#include "chrome/browser/ui/webui/ash/skyvault/local_files_migration.mojom-forward.h"
#include "chrome/browser/ui/webui/ash/skyvault/local_files_migration.mojom-shared.h"
#include "chrome/browser/ui/webui/ash/skyvault/local_files_migration.mojom.h"
namespace policy::local_user_files {
namespace {
// Converts a CloudProvider enum value to its corresponding Mojo representation.
mojom::CloudProvider ConvertCloudProviderToMojo(
MigrationDestination destination) {
switch (destination) {
case MigrationDestination::kNotSpecified:
NOTREACHED()
<< "Case should not be reached, cloud provider must be specified.";
case MigrationDestination::kDelete:
return mojom::CloudProvider::kDelete;
case MigrationDestination::kGoogleDrive:
return mojom::CloudProvider::kGoogleDrive;
case MigrationDestination::kOneDrive:
return mojom::CloudProvider::kOneDrive;
}
}
// Rounds up the remaining time to the nearest displayable unit.
//
// If the remaining time is:
// * >= 59.5 minutes: Rounds up to the nearest hour
// * Otherwise: Rounds up to the nearest minute
base::TimeDelta RoundUpRemainingTime(base::TimeDelta remaining_time) {
// Round to the nearest second for precise calculations.
remaining_time = base::Seconds(std::round(remaining_time.InSecondsF()));
// Round up to hours if at least 59.5 minutes remain
if (remaining_time >= base::Seconds(59 * 60 + 30)) {
return base::Hours((remaining_time + base::Minutes(30)).InHours());
}
// Otherwise, round up to minutes
return base::Minutes((remaining_time + base::Seconds(30)).InMinutes());
}
// Calculates the time interval until the next UI update.
base::TimeDelta ComputeNextUIUpdateTime(const base::TimeDelta& remaining_time) {
base::TimeDelta rounded_remaining_time = RoundUpRemainingTime(remaining_time);
base::TimeDelta delta;
if (rounded_remaining_time.InHours() > 1) {
delta = base::Hours(rounded_remaining_time.InHours() - 1);
} else {
delta = base::Minutes(rounded_remaining_time.InMinutes() - 1);
}
return remaining_time - delta;
}
// Converts the remaining time to a Mojo representation, rounding up to the
// nearest appropriate unit (hour or minute).
mojom::TimeUnitAndValuePtr ConvertRemainingTimeToMojo(
const base::TimeDelta& remaining_time) {
const base::TimeDelta rounded_remaining_time =
RoundUpRemainingTime(remaining_time);
if (rounded_remaining_time.InHours() >= 1) {
return mojom::TimeUnitAndValue::New(mojom::TimeUnit::kHours,
rounded_remaining_time.InHours());
} else {
return mojom::TimeUnitAndValue::New(mojom::TimeUnit::kMinutes,
rounded_remaining_time.InMinutes());
}
}
} // namespace
LocalFilesMigrationPageHandler::LocalFilesMigrationPageHandler(
content::WebUI* web_ui,
Profile* profile,
MigrationDestination destination,
base::Time migration_start_time,
DialogActionCallback callback,
mojo::PendingRemote<mojom::Page> page,
mojo::PendingReceiver<mojom::PageHandler> receiver)
: profile_(profile),
web_ui_(web_ui),
destination_(destination),
migration_start_time_(migration_start_time),
callback_(std::move(callback)),
receiver_(this, std::move(receiver)),
page_(std::move(page)) {
base::TimeDelta remaining_time = migration_start_time - base::Time::Now();
base::TimeDelta ui_update_interval = ComputeNextUIUpdateTime(remaining_time);
ui_update_timer_.Start(
FROM_HERE, base::Time::Now() + ui_update_interval,
base::BindOnce(&LocalFilesMigrationPageHandler::UpdateRemainingTime,
weak_factory_.GetWeakPtr()));
}
LocalFilesMigrationPageHandler::~LocalFilesMigrationPageHandler() = default;
void LocalFilesMigrationPageHandler::GetInitialDialogInfo(
GetInitialDialogInfoCallback callback) {
base::TimeDelta remaining_time = migration_start_time_ - base::Time::Now();
if (remaining_time <= base::TimeDelta()) {
// TODO(aidazolic): Define error behavior.
return;
}
mojom::CloudProvider cloud_provider =
ConvertCloudProviderToMojo(destination_);
mojom::TimeUnitAndValuePtr remaining_time_ptr =
ConvertRemainingTimeToMojo(remaining_time);
std::string formatted_date_time = base::UTF16ToUTF8(
base::TimeFormatShortDateAndTimeWithTimeZone(migration_start_time_));
std::move(callback).Run(cloud_provider, std::move(remaining_time_ptr),
formatted_date_time);
}
void LocalFilesMigrationPageHandler::UploadOrDeleteNow() {
if (callback_) {
std::move(callback_).Run(DialogAction::kUploadNow);
}
}
void LocalFilesMigrationPageHandler::Close() {
if (callback_) {
std::move(callback_).Run(DialogAction::kUploadLater);
}
}
void LocalFilesMigrationPageHandler::UpdateRemainingTime() {
base::Time time_now = base::Time::Now();
base::TimeDelta remaining_time = migration_start_time_ - time_now;
// Don't schedule an update if the time is up.
if (remaining_time <= base::TimeDelta()) {
return;
}
base::TimeDelta ui_update_interval = ComputeNextUIUpdateTime(remaining_time);
ui_update_timer_.Start(
FROM_HERE, time_now + ui_update_interval,
base::BindOnce(&LocalFilesMigrationPageHandler::UpdateRemainingTime,
weak_factory_.GetWeakPtr()));
page_->UpdateRemainingTime(ConvertRemainingTimeToMojo(remaining_time));
}
} // namespace policy::local_user_files
|