Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1699)

Side by Side Diff: content/browser/notifications/notification_database.cc

Issue 999933002: Store the actual notification data in the notification database. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@n-db-GetNextNotificationId
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/notifications/notification_database.h" 5 #include "content/browser/notifications/notification_database.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "base/files/file_util.h" 9 #include "base/files/file_util.h"
10 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/stringprintf.h"
12 #include "content/browser/notifications/notification_database_data.h"
11 #include "content/public/browser/browser_thread.h" 13 #include "content/public/browser/browser_thread.h"
12 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 14 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
13 #include "third_party/leveldatabase/src/include/leveldb/db.h" 15 #include "third_party/leveldatabase/src/include/leveldb/db.h"
14 #include "third_party/leveldatabase/src/include/leveldb/env.h" 16 #include "third_party/leveldatabase/src/include/leveldb/env.h"
15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 17 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
18 #include "url/gurl.h"
16 19
17 // Notification LevelDB database schema (in alphabetized order) 20 // Notification LevelDB database schema (in alphabetized order)
18 // ======================= 21 // =======================
19 // 22 //
20 // key: "NEXT_NOTIFICATION_ID" 23 // key: "NEXT_NOTIFICATION_ID"
21 // value: Decimal string which fits into an int64_t. 24 // value: Decimal string which fits into an int64_t.
Bernhard Bauer 2015/03/13 17:25:35 Add the new key to the schema?
Peter Beverloo 2015/03/13 20:32:32 Done.
22 // 25 //
23 26
24 namespace content { 27 namespace content {
25 namespace { 28 namespace {
26 29
27 // Keys of the fields defined in the database. 30 // Keys of the fields defined in the database.
28 const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID"; 31 const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID";
32 const char kDataKeyPrefix[] = "DATA:";
33
34 // Separates the components of compound keys.
35 const char kKeySeparator = '\x00';
cmumford 2015/03/13 17:13:15 Not seriously suggesting this, but I've never seen
Peter Beverloo 2015/03/13 20:32:32 Heh, I didn't even know these existed. I guess \x1
29 36
30 // The first notification id which to be handed out by the database. 37 // The first notification id which to be handed out by the database.
31 const int64_t kFirstNotificationId = 1; 38 const int64_t kFirstNotificationId = 1;
32 39
33 // Converts the LevelDB |status| to one of the notification database's values. 40 // Converts the LevelDB |status| to one of the notification database's values.
34 NotificationDatabase::Status LevelDBStatusToStatus( 41 NotificationDatabase::Status LevelDBStatusToStatus(
35 const leveldb::Status& status) { 42 const leveldb::Status& status) {
36 if (status.ok()) 43 if (status.ok())
37 return NotificationDatabase::STATUS_OK; 44 return NotificationDatabase::STATUS_OK;
38 else if (status.IsNotFound()) 45 else if (status.IsNotFound())
39 return NotificationDatabase::STATUS_ERROR_NOT_FOUND; 46 return NotificationDatabase::STATUS_ERROR_NOT_FOUND;
40 else if (status.IsCorruption()) 47 else if (status.IsCorruption())
41 return NotificationDatabase::STATUS_ERROR_CORRUPTED; 48 return NotificationDatabase::STATUS_ERROR_CORRUPTED;
42 49
43 return NotificationDatabase::STATUS_ERROR_FAILED; 50 return NotificationDatabase::STATUS_ERROR_FAILED;
44 } 51 }
45 52
53 // Creates the compound data key in which notification data is stored.
54 std::string CreateDataKey(int64_t notification_id, const GURL& origin) {
55 return base::StringPrintf("%s%s%c%s",
56 kDataKeyPrefix,
57 origin.spec().c_str(),
cmumford 2015/03/13 17:13:15 Instead of using the origin directly (which may be
Peter Beverloo 2015/03/13 20:32:32 I'm all for re-using logic :). Done
58 kKeySeparator,
59 base::Int64ToString(notification_id).c_str());
60 }
61
46 } // namespace 62 } // namespace
47 63
48 NotificationDatabase::NotificationDatabase(const base::FilePath& path) 64 NotificationDatabase::NotificationDatabase(const base::FilePath& path)
49 : path_(path), 65 : path_(path),
50 state_(STATE_UNINITIALIZED) { 66 state_(STATE_UNINITIALIZED) {
51 sequence_checker_.DetachFromSequence(); 67 sequence_checker_.DetachFromSequence();
52 } 68 }
53 69
54 NotificationDatabase::~NotificationDatabase() { 70 NotificationDatabase::~NotificationDatabase() {
55 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 71 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 int64_t next_notification_id; 125 int64_t next_notification_id;
110 if (!base::StringToInt64(value, &next_notification_id) || 126 if (!base::StringToInt64(value, &next_notification_id) ||
111 next_notification_id < kFirstNotificationId) { 127 next_notification_id < kFirstNotificationId) {
112 return STATUS_ERROR_CORRUPTED; 128 return STATUS_ERROR_CORRUPTED;
113 } 129 }
114 130
115 *notification_id = next_notification_id; 131 *notification_id = next_notification_id;
116 return STATUS_OK; 132 return STATUS_OK;
117 } 133 }
118 134
135 NotificationDatabase::Status NotificationDatabase::ReadNotificationData(
136 int64_t notification_id,
137 const GURL& origin,
138 NotificationDatabaseData* notification_database_data) const {
139 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
140 DCHECK_EQ(state_, STATE_INITIALIZED);
Bernhard Bauer 2015/03/13 17:25:35 Put the expected value first :)
Peter Beverloo 2015/03/13 20:32:32 Done.
141 DCHECK_GE(notification_id, kFirstNotificationId);
142 DCHECK(origin.is_valid());
143 DCHECK(notification_database_data);
144
145 std::string key = CreateDataKey(notification_id, origin);
146 std::string serialized_data;
147
148 Status status = LevelDBStatusToStatus(
149 db_->Get(leveldb::ReadOptions(), key, &serialized_data));
150 if (status != STATUS_OK)
151 return status;
152
153 if (notification_database_data->ParseFromString(serialized_data))
154 return STATUS_OK;
155
156 DLOG(ERROR) << "Unable to deserialize data for notification "
157 << notification_id << " belonging to " << origin << ".";
158 return STATUS_ERROR_CORRUPTED;
159 }
160
161 NotificationDatabase::Status NotificationDatabase::WriteNotificationData(
162 int64_t notification_id,
163 const GURL& origin,
164 const NotificationDatabaseData& notification_database_data) {
165 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
166 DCHECK_EQ(state_, STATE_INITIALIZED);
167 DCHECK_GE(notification_id, kFirstNotificationId);
168 DCHECK(origin.is_valid());
169
170 std::string serialized_data;
171 if (!notification_database_data.SerializeToString(&serialized_data)) {
172 DLOG(ERROR) << "Unable to serialize data for notification "
173 << notification_id << " belonging to " << origin << ".";
174 return STATUS_ERROR_FAILED;
175 }
176
177 leveldb::WriteBatch batch;
178 batch.Put(kNextNotificationIdKey, base::Int64ToString(notification_id + 1));
cmumford 2015/03/13 17:13:15 I'm feeling a little less comfortable with this cl
Peter Beverloo 2015/03/13 20:32:32 Yes, this makes sense. I've changed the API.
179 batch.Put(CreateDataKey(notification_id, origin), serialized_data);
180
181 return LevelDBStatusToStatus(db_->Write(leveldb::WriteOptions(), &batch));
182 }
183
184 NotificationDatabase::Status NotificationDatabase::DeleteNotificationData(
185 int64_t notification_id,
186 const GURL& origin) {
187 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
188 DCHECK_EQ(state_, STATE_INITIALIZED);
189 DCHECK_GE(notification_id, kFirstNotificationId);
190 DCHECK(origin.is_valid());
191
192 std::string key = CreateDataKey(notification_id, origin);
193
194 // TODO(peter): Instead of validating the existence of the data by reading the
195 // notification data, the notification list for |origin| should be considered
196 // instead. That list hasn't been implemented yet, however.
197
198 std::string value;
199 Status status = LevelDBStatusToStatus(
200 db_->Get(leveldb::ReadOptions(), key, &value));
201 if (status != STATUS_OK)
202 return status;
203
204 return LevelDBStatusToStatus(db_->Delete(leveldb::WriteOptions(), key));
205 }
206
119 NotificationDatabase::Status NotificationDatabase::Destroy() { 207 NotificationDatabase::Status NotificationDatabase::Destroy() {
120 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 208 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
121 209
122 leveldb::Options options; 210 leveldb::Options options;
123 if (IsInMemoryDatabase()) { 211 if (IsInMemoryDatabase()) {
124 if (!env_) 212 if (!env_)
125 return STATUS_OK; // The database has not been initialized. 213 return STATUS_OK; // The database has not been initialized.
126 214
127 options.env = env_.get(); 215 options.env = env_.get();
128 } 216 }
129 217
130 state_ = STATE_DISABLED; 218 state_ = STATE_DISABLED;
131 db_.reset(); 219 db_.reset();
132 220
133 return LevelDBStatusToStatus( 221 return LevelDBStatusToStatus(
134 leveldb::DestroyDB(path_.AsUTF8Unsafe(), options)); 222 leveldb::DestroyDB(path_.AsUTF8Unsafe(), options));
135 } 223 }
136 224
137 void NotificationDatabase::WriteNextNotificationId(
138 leveldb::WriteBatch* batch,
139 int64_t next_notification_id) const {
140 DCHECK_GE(next_notification_id, kFirstNotificationId);
141 DCHECK(batch);
142
143 batch->Put(kNextNotificationIdKey, base::Int64ToString(next_notification_id));
144 }
145
146 } // namespace content 225 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/notifications/notification_database.h ('k') | content/browser/notifications/notification_database_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698