Commit 589df997 authored by Toni Barzic's avatar Toni Barzic Committed by Chromium LUCI CQ

Reland "Observe file modifications in FileChangeService"

This is a reland of c52857a9

The original cl missed calls to run_loop.Run() in test methods
that wrote to a file, and waited for the write to finish.

TBR=dats@chromium.org

Original change's description:
> Observe file modifications in FileChangeService
>
> Adds OnFileModified observer interface to FileChangeServiceObserver
> called when the file is written, truncated, or copied to.
>
> Fixes file change service unit tests to verify that mocked observer
> methods actually get called. The observers were previously not
> getting invoked because the test suite did not set up fake chrome
> user manager, so user account IDs were not correctly mapped to the
> associated test profile, which is something
> ObservableFileSystemOperationImpl depends on to get the
> FileChangeService to notify of file changes.
>
> BUG=1139115
>
> Change-Id: I9829db0a496eec301a7f7547ac74f61bc1a18bdf
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2603467
> Reviewed-by: Sergei Datsenko <dats@chromium.org>
> Reviewed-by: David Black <dmblack@google.com>
> Commit-Queue: Toni Baržić <tbarzic@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#839697}

Bug: 1139115
Change-Id: I70e23cd1b11c9168ee99d8ed314942d25bd4a004
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2607415
Commit-Queue: Toni Baržić <tbarzic@chromium.org>
Reviewed-by: default avatarDavid Black <dmblack@google.com>
Cr-Commit-Position: refs/heads/master@{#839780}
parent d6bfa043
......@@ -18,6 +18,11 @@ void FileChangeService::RemoveObserver(FileChangeServiceObserver* observer) {
observer_list_.RemoveObserver(observer);
}
void FileChangeService::NotifyFileModified(const storage::FileSystemURL& url) {
for (FileChangeServiceObserver& observer : observer_list_)
observer.OnFileModified(url);
}
void FileChangeService::NotifyFileCopied(const storage::FileSystemURL& src,
const storage::FileSystemURL& dst) {
for (FileChangeServiceObserver& observer : observer_list_)
......
......@@ -25,6 +25,9 @@ class FileChangeService : public KeyedService {
void AddObserver(FileChangeServiceObserver* observer);
void RemoveObserver(FileChangeServiceObserver* observer);
// Notifies the service that a file identified by `url` has been modified.
void NotifyFileModified(const storage::FileSystemURL& url);
// Notifies the service that a file has been copied from `src` to `dst`.
void NotifyFileCopied(const storage::FileSystemURL& src,
const storage::FileSystemURL& dst);
......
......@@ -16,6 +16,10 @@ namespace chromeos {
// An interface for an observer which receives `FileChangeService` events.
class FileChangeServiceObserver : public base::CheckedObserver {
public:
// Invoked when a file identified by `url` has been modified. Note that this
// will not get called on file creation or deletion.
virtual void OnFileModified(const storage::FileSystemURL& url) {}
// Invoked when a file has been copied from `src` to `dst`.
virtual void OnFileCopied(const storage::FileSystemURL& src,
const storage::FileSystemURL& dst) {}
......
......@@ -16,6 +16,7 @@ namespace chromeos {
namespace {
using StatusCallback = storage::FileSystemOperation::StatusCallback;
using WriteCallback = storage::FileSystemOperation::WriteCallback;
// Helpers ---------------------------------------------------------------------
......@@ -34,8 +35,10 @@ void NotifyFileCopiedOnUiThread(const AccountId& account_id,
const storage::FileSystemURL& dst) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
FileChangeService* service = GetFileChangeService(account_id);
if (service)
if (service) {
service->NotifyFileModified(dst);
service->NotifyFileCopied(src, dst);
}
}
// Notifies the `FileChangeService` associated with the given `account_id` of a
......@@ -50,6 +53,28 @@ void NotifyFileMovedOnUiThread(const AccountId& account_id,
service->NotifyFileMoved(src, dst);
}
// Notifies the `FileChangeService` associated with the given `account_id` of a
// file under `url` getting modified. This method may only be called from the
// browser UI thread.
void NotifyFileModifiedOnUiThread(const AccountId& account_id,
const storage::FileSystemURL& url) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
FileChangeService* service = GetFileChangeService(account_id);
if (service)
service->NotifyFileModified(url);
}
// Returns a `WriteCallback` which runs the specified callbacks in order.
WriteCallback RunInOrderCallback(WriteCallback a, WriteCallback b) {
return base::BindRepeating(
[](WriteCallback a, WriteCallback b, base::File::Error result,
int64_t bytes, bool complete) {
std::move(a).Run(result, bytes, complete);
std::move(b).Run(result, bytes, complete);
},
std::move(a), std::move(b));
}
// Returns a `StatusCallback` which runs the specified callbacks in order.
StatusCallback RunInOrderCallback(StatusCallback a, StatusCallback b) {
return base::BindOnce(
......@@ -73,6 +98,21 @@ StatusCallback RunOnUiThreadOnSuccessCallback(base::OnceClosure closure) {
std::move(closure));
}
// Returns a `WriteCallback` which runs the specified `closure` on the browser
// UI thread if `complete` is set.
WriteCallback RunOnUiThreadOnCompleteCallback(
const base::RepeatingClosure& closure) {
return base::BindRepeating(
[](const base::RepeatingClosure& closure, base::File::Error result,
int64_t bytes, bool complete) {
if (complete && result == base::File::FILE_OK) {
auto task_runner = content::GetUIThreadTaskRunner({});
task_runner->PostTask(FROM_HERE, std::move(closure));
}
},
std::move(closure));
}
} // namespace
// ObservableFileSystemOperationImpl -------------------------------------------
......@@ -144,4 +184,39 @@ void ObservableFileSystemOperationImpl::MoveFileLocal(
std::move(callback)));
}
void ObservableFileSystemOperationImpl::WriteBlob(
const storage::FileSystemURL& url,
std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
std::unique_ptr<storage::BlobReader> blob_reader,
const WriteCallback& callback) {
storage::FileSystemOperationImpl::WriteBlob(
url, std::move(writer_delegate), std::move(blob_reader),
RunInOrderCallback(RunOnUiThreadOnCompleteCallback(base::BindRepeating(
&NotifyFileModifiedOnUiThread, account_id_, url)),
std::move(callback)));
}
void ObservableFileSystemOperationImpl::Write(
const storage::FileSystemURL& url,
std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
mojo::ScopedDataPipeConsumerHandle data_pipe,
const WriteCallback& callback) {
storage::FileSystemOperationImpl::Write(
url, std::move(writer_delegate), std::move(data_pipe),
RunInOrderCallback(RunOnUiThreadOnCompleteCallback(base::BindRepeating(
&NotifyFileModifiedOnUiThread, account_id_, url)),
std::move(callback)));
}
void ObservableFileSystemOperationImpl::Truncate(
const storage::FileSystemURL& url,
int64_t length,
StatusCallback callback) {
storage::FileSystemOperationImpl::Truncate(
url, length,
RunInOrderCallback(RunOnUiThreadOnSuccessCallback(base::BindOnce(
&NotifyFileModifiedOnUiThread, account_id_, url)),
std::move(callback)));
}
} // namespace chromeos
......@@ -49,6 +49,17 @@ class ObservableFileSystemOperationImpl
const storage::FileSystemURL& dst,
CopyOrMoveOption option,
StatusCallback callback) override;
void WriteBlob(const storage::FileSystemURL& url,
std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
std::unique_ptr<storage::BlobReader> blob_reader,
const WriteCallback& callback) override;
void Write(const storage::FileSystemURL& url,
std::unique_ptr<storage::FileWriterDelegate> writer_delegate,
mojo::ScopedDataPipeConsumerHandle data_pipe,
const WriteCallback& callback) override;
void Truncate(const storage::FileSystemURL& url,
int64_t length,
StatusCallback callback) override;
const AccountId account_id_;
base::WeakPtrFactory<ObservableFileSystemOperationImpl> weak_factory_{this};
......
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