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

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/+/2603467Reviewed-by: default avatarSergei Datsenko <dats@chromium.org>
Reviewed-by: default avatarDavid Black <dmblack@google.com>
Commit-Queue: Toni Baržić <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#839697}
parent cbb77bc7
...@@ -18,6 +18,11 @@ void FileChangeService::RemoveObserver(FileChangeServiceObserver* observer) { ...@@ -18,6 +18,11 @@ void FileChangeService::RemoveObserver(FileChangeServiceObserver* observer) {
observer_list_.RemoveObserver(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, void FileChangeService::NotifyFileCopied(const storage::FileSystemURL& src,
const storage::FileSystemURL& dst) { const storage::FileSystemURL& dst) {
for (FileChangeServiceObserver& observer : observer_list_) for (FileChangeServiceObserver& observer : observer_list_)
......
...@@ -25,6 +25,9 @@ class FileChangeService : public KeyedService { ...@@ -25,6 +25,9 @@ class FileChangeService : public KeyedService {
void AddObserver(FileChangeServiceObserver* observer); void AddObserver(FileChangeServiceObserver* observer);
void RemoveObserver(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`. // Notifies the service that a file has been copied from `src` to `dst`.
void NotifyFileCopied(const storage::FileSystemURL& src, void NotifyFileCopied(const storage::FileSystemURL& src,
const storage::FileSystemURL& dst); const storage::FileSystemURL& dst);
......
...@@ -16,6 +16,10 @@ namespace chromeos { ...@@ -16,6 +16,10 @@ namespace chromeos {
// An interface for an observer which receives `FileChangeService` events. // An interface for an observer which receives `FileChangeService` events.
class FileChangeServiceObserver : public base::CheckedObserver { class FileChangeServiceObserver : public base::CheckedObserver {
public: 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`. // Invoked when a file has been copied from `src` to `dst`.
virtual void OnFileCopied(const storage::FileSystemURL& src, virtual void OnFileCopied(const storage::FileSystemURL& src,
const storage::FileSystemURL& dst) {} const storage::FileSystemURL& dst) {}
......
...@@ -16,6 +16,7 @@ namespace chromeos { ...@@ -16,6 +16,7 @@ namespace chromeos {
namespace { namespace {
using StatusCallback = storage::FileSystemOperation::StatusCallback; using StatusCallback = storage::FileSystemOperation::StatusCallback;
using WriteCallback = storage::FileSystemOperation::WriteCallback;
// Helpers --------------------------------------------------------------------- // Helpers ---------------------------------------------------------------------
...@@ -34,8 +35,10 @@ void NotifyFileCopiedOnUiThread(const AccountId& account_id, ...@@ -34,8 +35,10 @@ void NotifyFileCopiedOnUiThread(const AccountId& account_id,
const storage::FileSystemURL& dst) { const storage::FileSystemURL& dst) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
FileChangeService* service = GetFileChangeService(account_id); FileChangeService* service = GetFileChangeService(account_id);
if (service) if (service) {
service->NotifyFileModified(dst);
service->NotifyFileCopied(src, dst); service->NotifyFileCopied(src, dst);
}
} }
// Notifies the `FileChangeService` associated with the given `account_id` of a // Notifies the `FileChangeService` associated with the given `account_id` of a
...@@ -50,6 +53,28 @@ void NotifyFileMovedOnUiThread(const AccountId& account_id, ...@@ -50,6 +53,28 @@ void NotifyFileMovedOnUiThread(const AccountId& account_id,
service->NotifyFileMoved(src, dst); 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. // Returns a `StatusCallback` which runs the specified callbacks in order.
StatusCallback RunInOrderCallback(StatusCallback a, StatusCallback b) { StatusCallback RunInOrderCallback(StatusCallback a, StatusCallback b) {
return base::BindOnce( return base::BindOnce(
...@@ -73,6 +98,21 @@ StatusCallback RunOnUiThreadOnSuccessCallback(base::OnceClosure closure) { ...@@ -73,6 +98,21 @@ StatusCallback RunOnUiThreadOnSuccessCallback(base::OnceClosure closure) {
std::move(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 } // namespace
// ObservableFileSystemOperationImpl ------------------------------------------- // ObservableFileSystemOperationImpl -------------------------------------------
...@@ -144,4 +184,39 @@ void ObservableFileSystemOperationImpl::MoveFileLocal( ...@@ -144,4 +184,39 @@ void ObservableFileSystemOperationImpl::MoveFileLocal(
std::move(callback))); 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 } // namespace chromeos
...@@ -49,6 +49,17 @@ class ObservableFileSystemOperationImpl ...@@ -49,6 +49,17 @@ class ObservableFileSystemOperationImpl
const storage::FileSystemURL& dst, const storage::FileSystemURL& dst,
CopyOrMoveOption option, CopyOrMoveOption option,
StatusCallback callback) override; 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_; const AccountId account_id_;
base::WeakPtrFactory<ObservableFileSystemOperationImpl> weak_factory_{this}; 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