blob: 1f86a39ae8cb8bd2dc825410f319b58c2bc5b009 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/public/test/test_fileapi_operation_waiter.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/observer_list.h"
#include "content/public/browser/browser_thread.h"
#include "storage/browser/fileapi/file_system_context.h"
#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
namespace content {
using storage::FileSystemContext;
using storage::FileSystemURL;
using storage::FileUpdateObserver;
namespace {
// Because of how fileapi internally creates copies of its observer lists,
// removing an observer is not a supported operation. So to support temporary,
// test-style observers, we create one long-lived global observer instance that
// dispatches to a list of short-lived observers.
//
// This object operates on the UI thread, though it registers itself as an
// observer on the IO thread.
class FileUpdateObserverMultiplexer : public FileUpdateObserver {
public:
FileUpdateObserverMultiplexer() {}
void AddObserver(FileSystemContext* context, FileUpdateObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
// On first initialization, install ourself as an observer. We never
// uninstall, because we expect to leak.
if (!context_) {
// Currently we only listen to kFileSystemTypeTemporary; it should be fine
// to add other filesystem types as needed.
context_ = context;
base::Closure task = base::Bind(
&storage::SandboxFileSystemBackendDelegate::AddFileUpdateObserver,
base::Unretained(context_->sandbox_delegate()),
storage::kFileSystemTypeTemporary, base::Unretained(this),
base::RetainedRef(
BrowserThread::GetTaskRunnerForThread(BrowserThread::UI)));
BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task);
}
CHECK_EQ(context, context_) << "Multiprofile is not implemented";
observers_.AddObserver(observer);
}
void RemoveObserver(FileUpdateObserver* observer) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
observers_.RemoveObserver(observer);
}
// FileUpdateObserver overrides:
void OnStartUpdate(const FileSystemURL& url) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (auto& observer : observers_)
observer.OnStartUpdate(url);
}
void OnUpdate(const FileSystemURL& url, int64_t delta) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (auto& observer : observers_)
observer.OnUpdate(url, delta);
}
void OnEndUpdate(const FileSystemURL& url) override {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (auto& observer : observers_)
observer.OnEndUpdate(url);
}
private:
FileSystemContext* context_ = nullptr;
base::ObserverList<FileUpdateObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(FileUpdateObserverMultiplexer);
};
static base::LazyInstance<FileUpdateObserverMultiplexer>::Leaky g_multiplexer =
LAZY_INSTANCE_INITIALIZER;
} // namespace
TestFileapiOperationWaiter::TestFileapiOperationWaiter(
FileSystemContext* context) {
g_multiplexer.Get().AddObserver(context, this);
}
TestFileapiOperationWaiter::~TestFileapiOperationWaiter() {
g_multiplexer.Get().RemoveObserver(this);
}
void TestFileapiOperationWaiter::WaitForEndUpdate() {
run_loop_.Run();
}
void TestFileapiOperationWaiter::OnStartUpdate(const FileSystemURL& url) {
did_start_update_ = true;
}
void TestFileapiOperationWaiter::OnUpdate(const FileSystemURL& url,
int64_t delta) {}
void TestFileapiOperationWaiter::OnEndUpdate(const FileSystemURL& url) {
run_loop_.Quit();
}
} // namespace content