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

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: comments 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"
14 #include "storage/common/database/database_identifier.h"
12 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h" 15 #include "third_party/leveldatabase/src/helpers/memenv/memenv.h"
13 #include "third_party/leveldatabase/src/include/leveldb/db.h" 16 #include "third_party/leveldatabase/src/include/leveldb/db.h"
14 #include "third_party/leveldatabase/src/include/leveldb/env.h" 17 #include "third_party/leveldatabase/src/include/leveldb/env.h"
15 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h" 18 #include "third_party/leveldatabase/src/include/leveldb/write_batch.h"
19 #include "url/gurl.h"
16 20
17 // Notification LevelDB database schema (in alphabetized order) 21 // Notification LevelDB database schema (in alphabetized order)
18 // ======================= 22 // =======================
19 // 23 //
24 // key: "DATA:" <origin identifier> '\x00' <notification_id>
25 // value: String containing the NotificationDatabaseDataProto protocol buffer
26 // in serialized form.
27 //
20 // key: "NEXT_NOTIFICATION_ID" 28 // key: "NEXT_NOTIFICATION_ID"
21 // value: Decimal string which fits into an int64_t. 29 // value: Decimal string which fits into an int64_t.
22 // 30 //
23 31
24 namespace content { 32 namespace content {
25 namespace { 33 namespace {
26 34
27 // Keys of the fields defined in the database. 35 // Keys of the fields defined in the database.
28 const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID"; 36 const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID";
37 const char kDataKeyPrefix[] = "DATA:";
38
39 // Separates the components of compound keys.
40 const char kKeySeparator = '\x00';
29 41
30 // The first notification id which to be handed out by the database. 42 // The first notification id which to be handed out by the database.
31 const int64_t kFirstNotificationId = 1; 43 const int64_t kFirstNotificationId = 1;
32 44
33 // Converts the LevelDB |status| to one of the notification database's values. 45 // Converts the LevelDB |status| to one of the notification database's values.
34 NotificationDatabase::Status LevelDBStatusToStatus( 46 NotificationDatabase::Status LevelDBStatusToStatus(
35 const leveldb::Status& status) { 47 const leveldb::Status& status) {
36 if (status.ok()) 48 if (status.ok())
37 return NotificationDatabase::STATUS_OK; 49 return NotificationDatabase::STATUS_OK;
38 else if (status.IsNotFound()) 50 else if (status.IsNotFound())
39 return NotificationDatabase::STATUS_ERROR_NOT_FOUND; 51 return NotificationDatabase::STATUS_ERROR_NOT_FOUND;
40 else if (status.IsCorruption()) 52 else if (status.IsCorruption())
41 return NotificationDatabase::STATUS_ERROR_CORRUPTED; 53 return NotificationDatabase::STATUS_ERROR_CORRUPTED;
42 54
43 return NotificationDatabase::STATUS_ERROR_FAILED; 55 return NotificationDatabase::STATUS_ERROR_FAILED;
44 } 56 }
45 57
58 // Creates the compound data key in which notification data is stored.
59 std::string CreateDataKey(int64_t notification_id, const GURL& origin) {
60 return base::StringPrintf("%s%s%c%s",
61 kDataKeyPrefix,
62 storage::GetIdentifierFromOrigin(origin).c_str(),
63 kKeySeparator,
64 base::Int64ToString(notification_id).c_str());
65 }
66
46 } // namespace 67 } // namespace
47 68
48 NotificationDatabase::NotificationDatabase(const base::FilePath& path) 69 NotificationDatabase::NotificationDatabase(const base::FilePath& path)
49 : path_(path), 70 : path_(path) {
50 state_(STATE_UNINITIALIZED) {
51 sequence_checker_.DetachFromSequence(); 71 sequence_checker_.DetachFromSequence();
52 } 72 }
53 73
54 NotificationDatabase::~NotificationDatabase() { 74 NotificationDatabase::~NotificationDatabase() {
55 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 75 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
56 } 76 }
57 77
58 NotificationDatabase::Status NotificationDatabase::Open( 78 NotificationDatabase::Status NotificationDatabase::Open(
59 bool create_if_missing) { 79 bool create_if_missing) {
60 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 80 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
(...skipping 17 matching lines...) Expand all
78 98
79 leveldb::DB* db = nullptr; 99 leveldb::DB* db = nullptr;
80 Status status = LevelDBStatusToStatus( 100 Status status = LevelDBStatusToStatus(
81 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db)); 101 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db));
82 if (status != STATUS_OK) 102 if (status != STATUS_OK)
83 return status; 103 return status;
84 104
85 state_ = STATE_INITIALIZED; 105 state_ = STATE_INITIALIZED;
86 db_.reset(db); 106 db_.reset(db);
87 107
108 return ReadNextNotificationId();
109 }
110
111 NotificationDatabase::Status NotificationDatabase::ReadNotificationData(
112 int64_t notification_id,
113 const GURL& origin,
114 NotificationDatabaseData* notification_database_data) const {
115 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
116 DCHECK_EQ(STATE_INITIALIZED, state_);
117 DCHECK_GE(notification_id, kFirstNotificationId);
118 DCHECK(origin.is_valid());
119 DCHECK(notification_database_data);
120
121 std::string key = CreateDataKey(notification_id, origin);
122 std::string serialized_data;
123
124 Status status = LevelDBStatusToStatus(
125 db_->Get(leveldb::ReadOptions(), key, &serialized_data));
126 if (status != STATUS_OK)
127 return status;
128
129 if (notification_database_data->ParseFromString(serialized_data))
130 return STATUS_OK;
131
132 DLOG(ERROR) << "Unable to deserialize data for notification "
133 << notification_id << " belonging to " << origin << ".";
134 return STATUS_ERROR_CORRUPTED;
135 }
136
137 NotificationDatabase::Status NotificationDatabase::WriteNotificationData(
138 const GURL& origin,
139 const NotificationDatabaseData& notification_database_data,
140 int64_t* notification_id) {
141 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
142 DCHECK_EQ(STATE_INITIALIZED, state_);
143 DCHECK(notification_id);
144 DCHECK(origin.is_valid());
145
146 std::string serialized_data;
147 if (!notification_database_data.SerializeToString(&serialized_data)) {
148 DLOG(ERROR) << "Unable to serialize data for a notification belonging "
149 << "to: " << origin;
150 return STATUS_ERROR_FAILED;
151 }
152
153 DCHECK_GE(next_notification_id_, kFirstNotificationId);
154
155 leveldb::WriteBatch batch;
156 batch.Put(CreateDataKey(next_notification_id_, origin), serialized_data);
157 batch.Put(kNextNotificationIdKey,
158 base::Int64ToString(next_notification_id_ + 1));
159
160 Status status = LevelDBStatusToStatus(
161 db_->Write(leveldb::WriteOptions(), &batch));
162 if (status != STATUS_OK)
163 return status;
164
165 *notification_id = next_notification_id_++;
88 return STATUS_OK; 166 return STATUS_OK;
89 } 167 }
90 168
91 NotificationDatabase::Status NotificationDatabase::GetNextNotificationId( 169 NotificationDatabase::Status NotificationDatabase::DeleteNotificationData(
92 int64_t* notification_id) const { 170 int64_t notification_id,
171 const GURL& origin) {
93 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 172 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
94 DCHECK_EQ(state_, STATE_INITIALIZED); 173 DCHECK_EQ(STATE_INITIALIZED, state_);
95 DCHECK(notification_id); 174 DCHECK_GE(notification_id, kFirstNotificationId);
175 DCHECK(origin.is_valid());
96 176
97 std::string value; 177 std::string key = CreateDataKey(notification_id, origin);
98 Status status = LevelDBStatusToStatus( 178 return LevelDBStatusToStatus(db_->Delete(leveldb::WriteOptions(), key));
99 db_->Get(leveldb::ReadOptions(), kNextNotificationIdKey, &value));
100
101 if (status == STATUS_ERROR_NOT_FOUND) {
102 *notification_id = kFirstNotificationId;
103 return STATUS_OK;
104 }
105
106 if (status != STATUS_OK)
107 return status;
108
109 int64_t next_notification_id;
110 if (!base::StringToInt64(value, &next_notification_id) ||
111 next_notification_id < kFirstNotificationId) {
112 return STATUS_ERROR_CORRUPTED;
113 }
114
115 *notification_id = next_notification_id;
116 return STATUS_OK;
117 } 179 }
118 180
119 NotificationDatabase::Status NotificationDatabase::Destroy() { 181 NotificationDatabase::Status NotificationDatabase::Destroy() {
120 DCHECK(sequence_checker_.CalledOnValidSequencedThread()); 182 DCHECK(sequence_checker_.CalledOnValidSequencedThread());
121 183
122 leveldb::Options options; 184 leveldb::Options options;
123 if (IsInMemoryDatabase()) { 185 if (IsInMemoryDatabase()) {
124 if (!env_) 186 if (!env_)
125 return STATUS_OK; // The database has not been initialized. 187 return STATUS_OK; // The database has not been initialized.
126 188
127 options.env = env_.get(); 189 options.env = env_.get();
128 } 190 }
129 191
130 state_ = STATE_DISABLED; 192 state_ = STATE_DISABLED;
131 db_.reset(); 193 db_.reset();
132 194
133 return LevelDBStatusToStatus( 195 return LevelDBStatusToStatus(
134 leveldb::DestroyDB(path_.AsUTF8Unsafe(), options)); 196 leveldb::DestroyDB(path_.AsUTF8Unsafe(), options));
135 } 197 }
136 198
137 void NotificationDatabase::WriteNextNotificationId( 199 NotificationDatabase::Status NotificationDatabase::ReadNextNotificationId() {
138 leveldb::WriteBatch* batch, 200 std::string value;
139 int64_t next_notification_id) const { 201 Status status = LevelDBStatusToStatus(
140 DCHECK_GE(next_notification_id, kFirstNotificationId); 202 db_->Get(leveldb::ReadOptions(), kNextNotificationIdKey, &value));
141 DCHECK(batch);
142 203
143 batch->Put(kNextNotificationIdKey, base::Int64ToString(next_notification_id)); 204 if (status == STATUS_ERROR_NOT_FOUND) {
205 next_notification_id_ = kFirstNotificationId;
206 return STATUS_OK;
207 }
208
209 if (status != STATUS_OK)
210 return status;
211
212 if (!base::StringToInt64(value, &next_notification_id_) ||
213 next_notification_id_ < kFirstNotificationId) {
214 return STATUS_ERROR_CORRUPTED;
215 }
216
217 return STATUS_OK;
144 } 218 }
145 219
146 } // namespace content 220 } // 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