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