1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/services/storage/test_api/test_api.h"
6
7 #include "base/bind.h"
8 #include "base/check.h"
9 #include "base/immediate_crash.h"
10 #include "base/no_destructor.h"
11 #include "base/task/task_traits.h"
12 #include "base/task/thread_pool.h"
13 #include "base/threading/sequenced_task_runner_handle.h"
14 #include "components/services/storage/filesystem_proxy_factory.h"
15 #include "components/services/storage/public/mojom/test_api.test-mojom.h"
16 #include "components/services/storage/test_api_stubs.h"
17 #include "mojo/public/cpp/bindings/receiver_set.h"
18 #include "third_party/leveldatabase/env_chromium.h"
19 #include "third_party/leveldatabase/src/include/leveldb/db.h"
20
21 namespace storage {
22
23 namespace {
24
25 class TestApiDatabaseEnv : public leveldb_env::ChromiumEnv {
26 public:
TestApiDatabaseEnv()27 TestApiDatabaseEnv()
28 : ChromiumEnv("ChromiumEnv.TestApi", CreateFilesystemProxy()) {}
29 TestApiDatabaseEnv(const TestApiDatabaseEnv&) = delete;
30 TestApiDatabaseEnv& operator=(const TestApiDatabaseEnv&) = delete;
31 };
32
GetTestApiDatabaseEnv()33 TestApiDatabaseEnv* GetTestApiDatabaseEnv() {
34 static base::NoDestructor<TestApiDatabaseEnv> env;
35 return env.get();
36 }
37
CreateAndCompactDatabase(const std::string & name,scoped_refptr<base::SequencedTaskRunner> callback_task_runner,mojom::TestApi::ForceLeveldbDatabaseCompactionCallback callback)38 void CreateAndCompactDatabase(
39 const std::string& name,
40 scoped_refptr<base::SequencedTaskRunner> callback_task_runner,
41 mojom::TestApi::ForceLeveldbDatabaseCompactionCallback callback) {
42 leveldb_env::Options options;
43 options.create_if_missing = true;
44 options.env = GetTestApiDatabaseEnv();
45 std::unique_ptr<leveldb::DB> db;
46 leveldb::Status status = leveldb_env::OpenDB(options, name, &db);
47 CHECK(status.ok()) << status.ToString();
48 db->CompactRange(nullptr, nullptr);
49 db.reset();
50 callback_task_runner->PostTask(FROM_HERE, std::move(callback));
51 }
52
53 class TestApiImpl : public mojom::TestApi {
54 public:
55 TestApiImpl() = default;
56 ~TestApiImpl() override = default;
57
AddReceiver(mojo::PendingReceiver<mojom::TestApi> receiver)58 void AddReceiver(mojo::PendingReceiver<mojom::TestApi> receiver) {
59 receivers_.Add(this, std::move(receiver));
60 }
61
62 // mojom::TestApi implementation:
CrashNow()63 void CrashNow() override { IMMEDIATE_CRASH(); }
64
ForceLeveldbDatabaseCompaction(const std::string & name,ForceLeveldbDatabaseCompactionCallback callback)65 void ForceLeveldbDatabaseCompaction(
66 const std::string& name,
67 ForceLeveldbDatabaseCompactionCallback callback) override {
68 // Note that we post to a SequencedTaskRunner because the task will use Mojo
69 // bindings, and by default Mojo bindings assume there is a current
70 // SequencedTaskRunnerHandle they can use for scheduling.
71 base::ThreadPool::CreateSequencedTaskRunner(
72 {base::MayBlock(), base::WithBaseSyncPrimitives()})
73 ->PostTask(FROM_HERE,
74 base::BindOnce(&CreateAndCompactDatabase, name,
75 base::SequencedTaskRunnerHandle::Get(),
76 std::move(callback)));
77 }
78
79 private:
80 mojo::ReceiverSet<mojom::TestApi> receivers_;
81 };
82
BindTestApi(mojo::ScopedMessagePipeHandle test_api_receiver)83 void BindTestApi(mojo::ScopedMessagePipeHandle test_api_receiver) {
84 static base::NoDestructor<TestApiImpl> impl;
85 impl->AddReceiver(
86 mojo::PendingReceiver<mojom::TestApi>(std::move(test_api_receiver)));
87 }
88
89 } // namespace
90
InjectTestApiImplementation()91 void InjectTestApiImplementation() {
92 SetTestApiBinderForTesting(base::BindRepeating(&BindTestApi));
93 }
94
95 } // namespace storage
96