Commit c96bf224 authored by Nancy Wang's avatar Nancy Wang Committed by Chromium LUCI CQ

Implement the writing function to save the restore data.

This CL implements below functions:
1. Save the app launch information to local variable
|file_path_to_restore_data_|.

2. Add flags |ShouldUpdate| per profile path to record whether there
are updates to be saved to the full restore file.

3. Add a timer to delay and cache the restore data writing.

4. Call FullRestoreFileHandler to write the restore data from
|file_path_to_restore_data_| to the full restore file on a background
task.

There will be a separate CL to add tests.

Bug: 1146900
Change-Id: Icf7a674d0d474005eb8dc33b39b5660ab6436153
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2589613
Commit-Queue: Nancy Wang <nancylingwang@chromium.org>
Reviewed-by: default avatarDominick Ng <dominickn@chromium.org>
Cr-Commit-Position: refs/heads/master@{#837880}
parent 5228b8ba
......@@ -138,6 +138,48 @@ AppRestoreData::AppRestoreData(base::Value&& value) {
AppRestoreData::~AppRestoreData() = default;
std::unique_ptr<AppRestoreData> AppRestoreData::Clone() const {
std::unique_ptr<AppRestoreData> data = std::make_unique<AppRestoreData>();
if (event_flag.has_value())
data->event_flag = event_flag.value();
if (container.has_value())
data->container = container.value();
if (disposition.has_value())
data->disposition = disposition.value();
if (display_id.has_value())
data->display_id = display_id.value();
if (url.has_value())
data->url = url.value();
if (intent.has_value() && intent.value())
data->intent = intent.value()->Clone();
if (file_paths.has_value())
data->file_paths = file_paths.value();
if (activation_index.has_value())
data->activation_index = activation_index.value();
if (desk_id.has_value())
data->desk_id = desk_id.value();
if (restored_bounds.has_value())
data->restored_bounds = restored_bounds.value();
if (current_bounds.has_value())
data->current_bounds = current_bounds.value();
if (window_state_type.has_value())
data->window_state_type = window_state_type.value();
return data;
}
base::Value AppRestoreData::ConvertToValue() const {
base::Value launch_info_dict(base::Value::Type::DICTIONARY);
......
......@@ -34,6 +34,8 @@ struct COMPONENT_EXPORT(FULL_RESTORE) AppRestoreData {
AppRestoreData(const AppRestoreData&) = delete;
AppRestoreData& operator=(const AppRestoreData&) = delete;
std::unique_ptr<AppRestoreData> Clone() const;
// Converts the struct LaunchAndWindowInfo to base::Value, e.g.:
// {
// "event_flag": 0,
......
......@@ -4,12 +4,25 @@
#include "components/full_restore/full_restore_save_handler.h"
#include "base/bind.h"
#include "base/files/file_path.h"
#include "base/no_destructor.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "components/full_restore/app_launch_info.h"
#include "components/full_restore/full_restore_file_handler.h"
#include "components/full_restore/restore_data.h"
namespace full_restore {
namespace {
// Delay between when an update is received, and when we save it to the
// full restore file.
constexpr base::TimeDelta kSaveDelay = base::TimeDelta::FromMilliseconds(2500);
} // namespace
FullRestoreSaveHandler* FullRestoreSaveHandler::GetInstance() {
static base::NoDestructor<FullRestoreSaveHandler> full_restore_save_handler;
return full_restore_save_handler.get();
......@@ -20,10 +33,64 @@ FullRestoreSaveHandler::FullRestoreSaveHandler() = default;
FullRestoreSaveHandler::~FullRestoreSaveHandler() = default;
void FullRestoreSaveHandler::SaveAppLaunchInfo(
const base::FilePath& profile_dir,
const base::FilePath& file_path,
std::unique_ptr<AppLaunchInfo> app_launch_info) {
// TODO(crbug.com/1146900): Save the app launch parameters to the full restore
// file.
if (!app_launch_info)
return;
// Each user should have one full restore file saving the restore data in the
// profile directory |file_path|. So |app_launch_info| is saved to the restore
// data for the user with the profile path |file_path|.
file_path_to_restore_data_[file_path].AddAppLaunchInfo(
std::move(app_launch_info));
should_update_.insert(file_path);
MaybeStartSaveTimer();
}
void FullRestoreSaveHandler::MaybeStartSaveTimer() {
if (!save_timer_.IsRunning() && save_running_.empty()) {
save_timer_.Start(FROM_HERE, kSaveDelay,
base::BindOnce(&FullRestoreSaveHandler::Save,
weak_factory_.GetWeakPtr()));
}
}
void FullRestoreSaveHandler::Save() {
if (should_update_.empty())
return;
for (const auto& file_path : should_update_) {
save_running_.insert(file_path);
BackendTaskRunner(file_path)->PostTaskAndReply(
FROM_HERE,
base::BindOnce(&FullRestoreFileHandler::WriteToFile,
GetFileHandler(file_path),
file_path_to_restore_data_[file_path].Clone()),
base::BindOnce(&FullRestoreSaveHandler::OnSaveFinished,
weak_factory_.GetWeakPtr(), file_path));
}
should_update_.clear();
}
void FullRestoreSaveHandler::OnSaveFinished(const base::FilePath& file_path) {
save_running_.erase(file_path);
}
FullRestoreFileHandler* FullRestoreSaveHandler::GetFileHandler(
const base::FilePath& file_path) {
if (file_path_to_file_handler_.find(file_path) ==
file_path_to_file_handler_.end()) {
file_path_to_file_handler_[file_path] =
base::MakeRefCounted<FullRestoreFileHandler>(file_path);
}
return file_path_to_file_handler_[file_path].get();
}
base::SequencedTaskRunner* FullRestoreSaveHandler::BackendTaskRunner(
const base::FilePath& file_path) {
return GetFileHandler(file_path)->owning_task_runner();
}
} // namespace full_restore
......@@ -5,17 +5,25 @@
#ifndef COMPONENTS_FULL_RESTORE_FULL_RESTORE_SAVE_HANDLER_H_
#define COMPONENTS_FULL_RESTORE_FULL_RESTORE_SAVE_HANDLER_H_
#include <map>
#include <memory>
#include <set>
#include "base/component_export.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
namespace base {
class FilePath;
class SequencedTaskRunner;
}
namespace full_restore {
struct AppLaunchInfo;
class FullRestoreFileHandler;
class RestoreData;
// FullRestoreSaveHandler is responsible for writing both the app launch
// information and the app window information to disk. FullRestoreSaveHandler
......@@ -23,10 +31,6 @@ struct AppLaunchInfo;
// background task runner) for the actual writing. To minimize IO,
// FullRestoreSaveHandler starts a timer that invokes restore data saving at a
// later time.
//
// TODO(crbug.com/1146900):
// 1. Implement the restore data writing function.
// 2. Add a timer to delay the restore data saving.
class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreSaveHandler {
public:
static FullRestoreSaveHandler* GetInstance();
......@@ -37,8 +41,43 @@ class COMPONENT_EXPORT(FULL_RESTORE) FullRestoreSaveHandler {
FullRestoreSaveHandler(const FullRestoreSaveHandler&) = delete;
FullRestoreSaveHandler& operator=(const FullRestoreSaveHandler&) = delete;
// Save |app_launch_info| to the full restore file in |profile_dir|.
void SaveAppLaunchInfo(const base::FilePath& profile_dir,
std::unique_ptr<AppLaunchInfo> app_launch_info);
private:
// Starts the timer that invokes Save (if timer isn't already running).
void MaybeStartSaveTimer();
// Passes |file_path_to_file_handler_| to the backend for saving.
void Save();
// Invoked when write to file operation for |file_path| is finished.
void OnSaveFinished(const base::FilePath& file_path);
FullRestoreFileHandler* GetFileHandler(const base::FilePath& file_path);
base::SequencedTaskRunner* BackendTaskRunner(const base::FilePath& file_path);
// Records whether there are new updates for saving between each saving delay.
// |ShouldUpdate| is cleared when Save is invoked.
std::set<base::FilePath> should_update_;
// The restore data for each user's profile. The key is the profile path.
std::map<base::FilePath, RestoreData> file_path_to_restore_data_;
// The file handler for each user's profile to write the restore data to the
// full restore file for each user. The key is the profile path.
std::map<base::FilePath, scoped_refptr<FullRestoreFileHandler>>
file_path_to_file_handler_;
// Timer used to delay the restore data writing to the full restore file.
base::OneShotTimer save_timer_;
// Records whether the saving process is running for a full restore file.
std::set<base::FilePath> save_running_;
base::WeakPtrFactory<FullRestoreSaveHandler> weak_factory_{this};
};
} // namespace full_restore
......
......@@ -52,6 +52,17 @@ RestoreData::RestoreData(std::unique_ptr<base::Value> restore_data_value) {
RestoreData::~RestoreData() = default;
std::unique_ptr<RestoreData> RestoreData::Clone() const {
std::unique_ptr<RestoreData> restore_data = std::make_unique<RestoreData>();
for (const auto& it : app_id_to_launch_list_) {
for (const auto& data_it : it.second) {
restore_data->app_id_to_launch_list_[it.first][data_it.first] =
data_it.second->Clone();
}
}
return restore_data;
}
base::Value RestoreData::ConvertToValue() const {
base::Value restore_data_dict(base::Value::Type::DICTIONARY);
for (const auto& it : app_id_to_launch_list_) {
......
......@@ -43,6 +43,8 @@ class COMPONENT_EXPORT(FULL_RESTORE) RestoreData {
RestoreData(const RestoreData&) = delete;
RestoreData& operator=(const RestoreData&) = delete;
std::unique_ptr<RestoreData> Clone() const;
// Converts |app_id_to_launch_list_| to base::Value, e.g.:
// {
// "odknhmnlageboeamepcngndbggdpaobj": // app_id
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment