1 // Copyright 2014 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.
5 #include "extensions/browser/value_store/value_store_frontend.h"
8 #include "base/files/file_path.h"
9 #include "base/logging.h"
10 #include "base/trace_event/trace_event.h"
11 #include "content/public/browser/browser_thread.h"
12 #include "extensions/browser/value_store/leveldb_value_store.h"
14 using content::BrowserThread
;
16 class ValueStoreFrontend::Backend
: public base::RefCountedThreadSafe
<Backend
> {
18 Backend() : storage_(NULL
) {}
20 void Init(const std::string
& uma_client_name
, const base::FilePath
& db_path
) {
21 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
23 TRACE_EVENT0("ValueStoreFrontend::Backend", "Init");
25 storage_
= new LeveldbValueStore(uma_client_name
, db_path
);
28 // This variant is useful for testing (using a mock ValueStore).
29 void InitWithStore(scoped_ptr
<ValueStore
> storage
) {
30 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
32 storage_
= storage
.release();
35 void Get(const std::string
& key
,
36 const ValueStoreFrontend::ReadCallback
& callback
) {
37 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
38 ValueStore::ReadResult result
= storage_
->Get(key
);
40 // Extract the value from the ReadResult and pass ownership of it to the
42 scoped_ptr
<base::Value
> value
;
43 if (!result
->HasError()) {
44 result
->settings().RemoveWithoutPathExpansion(key
, &value
);
46 LOG(WARNING
) << "Reading " << key
<< " from " << db_path_
.value()
47 << " failed: " << result
->error().message
;
50 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
51 base::Bind(&ValueStoreFrontend::Backend::RunCallback
,
52 this, callback
, base::Passed(&value
)));
55 void Set(const std::string
& key
, scoped_ptr
<base::Value
> value
) {
56 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
57 // We don't need the old value, so skip generating changes.
58 ValueStore::WriteResult result
= storage_
->Set(
59 ValueStore::IGNORE_QUOTA
| ValueStore::NO_GENERATE_CHANGES
,
62 LOG_IF(ERROR
, result
->HasError()) << "Error while writing " << key
<< " to "
66 void Remove(const std::string
& key
) {
67 DCHECK_CURRENTLY_ON(BrowserThread::FILE);
68 storage_
->Remove(key
);
72 friend class base::RefCountedThreadSafe
<Backend
>;
75 if (BrowserThread::CurrentlyOn(BrowserThread::FILE)) {
78 BrowserThread::DeleteSoon(BrowserThread::FILE, FROM_HERE
, storage_
);
82 void RunCallback(const ValueStoreFrontend::ReadCallback
& callback
,
83 scoped_ptr
<base::Value
> value
) {
84 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
85 callback
.Run(value
.Pass());
88 // The actual ValueStore that handles persisting the data to disk. Used
89 // exclusively on the FILE thread.
92 base::FilePath db_path_
;
94 DISALLOW_COPY_AND_ASSIGN(Backend
);
97 ValueStoreFrontend::ValueStoreFrontend()
98 : backend_(new Backend()) {
101 ValueStoreFrontend::ValueStoreFrontend(const std::string
& uma_client_name
,
102 const base::FilePath
& db_path
)
103 : backend_(new Backend()) {
104 Init(uma_client_name
, db_path
);
107 ValueStoreFrontend::ValueStoreFrontend(scoped_ptr
<ValueStore
> value_store
)
108 : backend_(new Backend()) {
109 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
110 base::Bind(&ValueStoreFrontend::Backend::InitWithStore
,
111 backend_
, base::Passed(&value_store
)));
114 ValueStoreFrontend::~ValueStoreFrontend() {
115 DCHECK(CalledOnValidThread());
118 void ValueStoreFrontend::Init(const std::string
& uma_client_name
,
119 const base::FilePath
& db_path
) {
120 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
121 base::Bind(&ValueStoreFrontend::Backend::Init
,
122 backend_
, uma_client_name
, db_path
));
125 void ValueStoreFrontend::Get(const std::string
& key
,
126 const ReadCallback
& callback
) {
127 DCHECK(CalledOnValidThread());
129 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
130 base::Bind(&ValueStoreFrontend::Backend::Get
,
131 backend_
, key
, callback
));
134 void ValueStoreFrontend::Set(const std::string
& key
,
135 scoped_ptr
<base::Value
> value
) {
136 DCHECK(CalledOnValidThread());
138 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
139 base::Bind(&ValueStoreFrontend::Backend::Set
,
140 backend_
, key
, base::Passed(&value
)));
143 void ValueStoreFrontend::Remove(const std::string
& key
) {
144 DCHECK(CalledOnValidThread());
146 BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE
,
147 base::Bind(&ValueStoreFrontend::Backend::Remove
,