OLD | NEW |
---|---|
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" |
(...skipping 12 matching lines...) Expand all Loading... | |
23 #include "url/gurl.h" | 23 #include "url/gurl.h" |
24 | 24 |
25 // Notification LevelDB database schema (in alphabetized order) | 25 // Notification LevelDB database schema (in alphabetized order) |
26 // ======================= | 26 // ======================= |
27 // | 27 // |
28 // key: "DATA:" <origin identifier> '\x00' <notification_id> | 28 // key: "DATA:" <origin identifier> '\x00' <notification_id> |
29 // value: String containing the NotificationDatabaseDataProto protocol buffer | 29 // value: String containing the NotificationDatabaseDataProto protocol buffer |
30 // in serialized form. | 30 // in serialized form. |
31 // | 31 // |
32 // key: "NEXT_NOTIFICATION_ID" | 32 // key: "NEXT_NOTIFICATION_ID" |
33 // value: Decimal string which fits into an int64_t. | 33 // value: Decimal string which fits into an int64_t, containing the next |
34 // persistent notification ID. | |
34 | 35 |
35 namespace content { | 36 namespace content { |
36 namespace { | 37 namespace { |
37 | 38 |
38 // Keys of the fields defined in the database. | 39 // Keys of the fields defined in the database. |
39 const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID"; | 40 const char kNextNotificationIdKey[] = "NEXT_NOTIFICATION_ID"; |
40 const char kDataKeyPrefix[] = "DATA:"; | 41 const char kDataKeyPrefix[] = "DATA:"; |
41 | 42 |
42 // Separates the components of compound keys. | 43 // Separates the components of compound keys. |
43 const char kKeySeparator = '\x00'; | 44 const char kKeySeparator = '\x00'; |
44 | 45 |
45 // The first notification id which to be handed out by the database. | 46 // The first notification id which to be handed out by the database. |
46 const int64_t kFirstNotificationId = 1; | 47 const int64_t kFirstPersistentNotificationId = 1; |
47 | 48 |
48 // Converts the LevelDB |status| to one of the notification database's values. | 49 // Converts the LevelDB |status| to one of the notification database's values. |
49 NotificationDatabase::Status LevelDBStatusToStatus( | 50 NotificationDatabase::Status LevelDBStatusToStatus( |
50 const leveldb::Status& status) { | 51 const leveldb::Status& status) { |
51 if (status.ok()) | 52 if (status.ok()) |
52 return NotificationDatabase::STATUS_OK; | 53 return NotificationDatabase::STATUS_OK; |
53 else if (status.IsNotFound()) | 54 else if (status.IsNotFound()) |
54 return NotificationDatabase::STATUS_ERROR_NOT_FOUND; | 55 return NotificationDatabase::STATUS_ERROR_NOT_FOUND; |
55 else if (status.IsCorruption()) | 56 else if (status.IsCorruption()) |
56 return NotificationDatabase::STATUS_ERROR_CORRUPTED; | 57 return NotificationDatabase::STATUS_ERROR_CORRUPTED; |
(...skipping 11 matching lines...) Expand all Loading... | |
68 std::string CreateDataPrefix(const GURL& origin) { | 69 std::string CreateDataPrefix(const GURL& origin) { |
69 if (!origin.is_valid()) | 70 if (!origin.is_valid()) |
70 return kDataKeyPrefix; | 71 return kDataKeyPrefix; |
71 | 72 |
72 return base::StringPrintf("%s%s%c", kDataKeyPrefix, | 73 return base::StringPrintf("%s%s%c", kDataKeyPrefix, |
73 storage::GetIdentifierFromOrigin(origin).c_str(), | 74 storage::GetIdentifierFromOrigin(origin).c_str(), |
74 kKeySeparator); | 75 kKeySeparator); |
75 } | 76 } |
76 | 77 |
77 // Creates the compound data key in which notification data is stored. | 78 // Creates the compound data key in which notification data is stored. |
78 std::string CreateDataKey(const GURL& origin, int64_t notification_id) { | 79 std::string CreateDataKey(const GURL& origin, |
80 const std::string& notification_id) { | |
79 DCHECK(origin.is_valid()); | 81 DCHECK(origin.is_valid()); |
80 return CreateDataPrefix(origin) + base::Int64ToString(notification_id); | 82 DCHECK(!notification_id.empty()); |
83 | |
84 return CreateDataPrefix(origin) + notification_id; | |
81 } | 85 } |
82 | 86 |
83 // Deserializes data in |serialized_data| to |notification_database_data|. | 87 // Deserializes data in |serialized_data| to |notification_database_data|. |
84 // Will return if the deserialization was successful. | 88 // Will return if the deserialization was successful. |
85 NotificationDatabase::Status DeserializedNotificationData( | 89 NotificationDatabase::Status DeserializedNotificationData( |
86 const std::string& serialized_data, | 90 const std::string& serialized_data, |
87 NotificationDatabaseData* notification_database_data) { | 91 NotificationDatabaseData* notification_database_data) { |
88 DCHECK(notification_database_data); | 92 DCHECK(notification_database_data); |
89 if (DeserializeNotificationDatabaseData(serialized_data, | 93 if (DeserializeNotificationDatabaseData(serialized_data, |
90 notification_database_data)) { | 94 notification_database_data)) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 | 134 |
131 leveldb::DB* db = nullptr; | 135 leveldb::DB* db = nullptr; |
132 Status status = LevelDBStatusToStatus( | 136 Status status = LevelDBStatusToStatus( |
133 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db)); | 137 leveldb::DB::Open(options, path_.AsUTF8Unsafe(), &db)); |
134 if (status != STATUS_OK) | 138 if (status != STATUS_OK) |
135 return status; | 139 return status; |
136 | 140 |
137 state_ = STATE_INITIALIZED; | 141 state_ = STATE_INITIALIZED; |
138 db_.reset(db); | 142 db_.reset(db); |
139 | 143 |
140 return ReadNextNotificationId(); | 144 return ReadNextPersistentNotificationId(); |
145 } | |
146 | |
147 int64_t NotificationDatabase::GetNextPersistentNotificationId() { | |
148 return next_persistent_notification_id_++; | |
141 } | 149 } |
142 | 150 |
143 NotificationDatabase::Status NotificationDatabase::ReadNotificationData( | 151 NotificationDatabase::Status NotificationDatabase::ReadNotificationData( |
144 int64_t notification_id, | 152 const std::string& notification_id, |
145 const GURL& origin, | 153 const GURL& origin, |
146 NotificationDatabaseData* notification_database_data) const { | 154 NotificationDatabaseData* notification_database_data) const { |
147 DCHECK(sequence_checker_.CalledOnValidSequence()); | 155 DCHECK(sequence_checker_.CalledOnValidSequence()); |
148 DCHECK_EQ(STATE_INITIALIZED, state_); | 156 DCHECK_EQ(STATE_INITIALIZED, state_); |
149 DCHECK_GE(notification_id, kFirstNotificationId); | 157 DCHECK(!notification_id.empty()); |
150 DCHECK(origin.is_valid()); | 158 DCHECK(origin.is_valid()); |
151 DCHECK(notification_database_data); | 159 DCHECK(notification_database_data); |
152 | 160 |
153 std::string key = CreateDataKey(origin, notification_id); | 161 std::string key = CreateDataKey(origin, notification_id); |
154 std::string serialized_data; | 162 std::string serialized_data; |
155 | 163 |
156 Status status = LevelDBStatusToStatus( | 164 Status status = LevelDBStatusToStatus( |
157 db_->Get(leveldb::ReadOptions(), key, &serialized_data)); | 165 db_->Get(leveldb::ReadOptions(), key, &serialized_data)); |
158 if (status != STATUS_OK) | 166 if (status != STATUS_OK) |
159 return status; | 167 return status; |
(...skipping 21 matching lines...) Expand all Loading... | |
181 NotificationDatabase::ReadAllNotificationDataForServiceWorkerRegistration( | 189 NotificationDatabase::ReadAllNotificationDataForServiceWorkerRegistration( |
182 const GURL& origin, | 190 const GURL& origin, |
183 int64_t service_worker_registration_id, | 191 int64_t service_worker_registration_id, |
184 std::vector<NotificationDatabaseData>* notification_data_vector) const { | 192 std::vector<NotificationDatabaseData>* notification_data_vector) const { |
185 return ReadAllNotificationDataInternal(origin, service_worker_registration_id, | 193 return ReadAllNotificationDataInternal(origin, service_worker_registration_id, |
186 notification_data_vector); | 194 notification_data_vector); |
187 } | 195 } |
188 | 196 |
189 NotificationDatabase::Status NotificationDatabase::WriteNotificationData( | 197 NotificationDatabase::Status NotificationDatabase::WriteNotificationData( |
190 const GURL& origin, | 198 const GURL& origin, |
191 const NotificationDatabaseData& notification_database_data, | 199 const NotificationDatabaseData& notification_data) { |
192 int64_t* notification_id) { | |
193 DCHECK(sequence_checker_.CalledOnValidSequence()); | 200 DCHECK(sequence_checker_.CalledOnValidSequence()); |
194 DCHECK_EQ(STATE_INITIALIZED, state_); | 201 DCHECK_EQ(STATE_INITIALIZED, state_); |
195 DCHECK(notification_id); | |
196 DCHECK(origin.is_valid()); | 202 DCHECK(origin.is_valid()); |
197 | 203 |
198 DCHECK_GE(next_notification_id_, kFirstNotificationId); | 204 const std::string& notification_id = notification_data.notification_id; |
199 | 205 DCHECK(!notification_id.empty()); |
200 NotificationDatabaseData storage_data = notification_database_data; | |
201 storage_data.notification_id = next_notification_id_; | |
202 | 206 |
203 std::string serialized_data; | 207 std::string serialized_data; |
204 if (!SerializeNotificationDatabaseData(storage_data, &serialized_data)) { | 208 if (!SerializeNotificationDatabaseData(notification_data, &serialized_data)) { |
205 DLOG(ERROR) << "Unable to serialize data for a notification belonging " | 209 DLOG(ERROR) << "Unable to serialize data for a notification belonging " |
206 << "to: " << origin; | 210 << "to: " << origin; |
207 return STATUS_ERROR_FAILED; | 211 return STATUS_ERROR_FAILED; |
208 } | 212 } |
209 | 213 |
210 leveldb::WriteBatch batch; | 214 leveldb::WriteBatch batch; |
211 batch.Put(CreateDataKey(origin, next_notification_id_), serialized_data); | 215 batch.Put(CreateDataKey(origin, notification_id), serialized_data); |
212 batch.Put(kNextNotificationIdKey, | |
213 base::Int64ToString(next_notification_id_ + 1)); | |
214 | 216 |
215 Status status = | 217 if (written_persistent_notification_id_ != next_persistent_notification_id_) { |
216 LevelDBStatusToStatus(db_->Write(leveldb::WriteOptions(), &batch)); | 218 written_persistent_notification_id_ = next_persistent_notification_id_; |
217 if (status != STATUS_OK) | 219 batch.Put(kNextNotificationIdKey, |
218 return status; | 220 base::Int64ToString(next_persistent_notification_id_)); |
221 } | |
219 | 222 |
220 *notification_id = next_notification_id_++; | 223 return LevelDBStatusToStatus(db_->Write(leveldb::WriteOptions(), &batch)); |
221 return STATUS_OK; | |
222 } | 224 } |
223 | 225 |
224 NotificationDatabase::Status NotificationDatabase::DeleteNotificationData( | 226 NotificationDatabase::Status NotificationDatabase::DeleteNotificationData( |
225 int64_t notification_id, | 227 const std::string& notification_id, |
226 const GURL& origin) { | 228 const GURL& origin) { |
227 DCHECK(sequence_checker_.CalledOnValidSequence()); | 229 DCHECK(sequence_checker_.CalledOnValidSequence()); |
228 DCHECK_EQ(STATE_INITIALIZED, state_); | 230 DCHECK_EQ(STATE_INITIALIZED, state_); |
229 DCHECK_GE(notification_id, kFirstNotificationId); | 231 DCHECK(!notification_id.empty()); |
230 DCHECK(origin.is_valid()); | 232 DCHECK(origin.is_valid()); |
231 | 233 |
232 std::string key = CreateDataKey(origin, notification_id); | 234 std::string key = CreateDataKey(origin, notification_id); |
233 return LevelDBStatusToStatus(db_->Delete(leveldb::WriteOptions(), key)); | 235 return LevelDBStatusToStatus(db_->Delete(leveldb::WriteOptions(), key)); |
234 } | 236 } |
235 | 237 |
236 NotificationDatabase::Status | 238 NotificationDatabase::Status |
237 NotificationDatabase::DeleteAllNotificationDataForOrigin( | 239 NotificationDatabase::DeleteAllNotificationDataForOrigin( |
238 const GURL& origin, | 240 const GURL& origin, |
239 const std::string& tag, | 241 const std::string& tag, |
240 std::set<int64_t>* deleted_notification_set) { | 242 std::set<std::string>* deleted_notification_ids) { |
241 return DeleteAllNotificationDataInternal(origin, tag, | 243 return DeleteAllNotificationDataInternal(origin, tag, |
242 kInvalidServiceWorkerRegistrationId, | 244 kInvalidServiceWorkerRegistrationId, |
243 deleted_notification_set); | 245 deleted_notification_ids); |
244 } | 246 } |
245 | 247 |
246 NotificationDatabase::Status | 248 NotificationDatabase::Status |
247 NotificationDatabase::DeleteAllNotificationDataForServiceWorkerRegistration( | 249 NotificationDatabase::DeleteAllNotificationDataForServiceWorkerRegistration( |
248 const GURL& origin, | 250 const GURL& origin, |
249 int64_t service_worker_registration_id, | 251 int64_t service_worker_registration_id, |
250 std::set<int64_t>* deleted_notification_set) { | 252 std::set<std::string>* deleted_notification_ids) { |
251 return DeleteAllNotificationDataInternal(origin, "" /* tag */, | 253 return DeleteAllNotificationDataInternal(origin, "" /* tag */, |
252 service_worker_registration_id, | 254 service_worker_registration_id, |
253 deleted_notification_set); | 255 deleted_notification_ids); |
254 } | 256 } |
255 | 257 |
256 NotificationDatabase::Status NotificationDatabase::Destroy() { | 258 NotificationDatabase::Status NotificationDatabase::Destroy() { |
257 DCHECK(sequence_checker_.CalledOnValidSequence()); | 259 DCHECK(sequence_checker_.CalledOnValidSequence()); |
258 | 260 |
259 leveldb::Options options; | 261 leveldb::Options options; |
260 if (IsInMemoryDatabase()) { | 262 if (IsInMemoryDatabase()) { |
261 if (!env_) | 263 if (!env_) |
262 return STATUS_OK; // The database has not been initialized. | 264 return STATUS_OK; // The database has not been initialized. |
263 | 265 |
264 options.env = env_.get(); | 266 options.env = env_.get(); |
265 } | 267 } |
266 | 268 |
267 state_ = STATE_DISABLED; | 269 state_ = STATE_DISABLED; |
268 db_.reset(); | 270 db_.reset(); |
269 | 271 |
270 return LevelDBStatusToStatus( | 272 return LevelDBStatusToStatus( |
271 leveldb::DestroyDB(path_.AsUTF8Unsafe(), options)); | 273 leveldb::DestroyDB(path_.AsUTF8Unsafe(), options)); |
272 } | 274 } |
273 | 275 |
274 NotificationDatabase::Status NotificationDatabase::ReadNextNotificationId() { | 276 NotificationDatabase::Status |
277 NotificationDatabase::ReadNextPersistentNotificationId() { | |
275 std::string value; | 278 std::string value; |
276 Status status = LevelDBStatusToStatus( | 279 Status status = LevelDBStatusToStatus( |
277 db_->Get(leveldb::ReadOptions(), kNextNotificationIdKey, &value)); | 280 db_->Get(leveldb::ReadOptions(), kNextNotificationIdKey, &value)); |
278 | 281 |
279 if (status == STATUS_ERROR_NOT_FOUND) { | 282 if (status == STATUS_ERROR_NOT_FOUND) { |
280 next_notification_id_ = kFirstNotificationId; | 283 next_persistent_notification_id_ = kFirstPersistentNotificationId; |
284 written_persistent_notification_id_ = kFirstPersistentNotificationId; | |
281 return STATUS_OK; | 285 return STATUS_OK; |
282 } | 286 } |
283 | 287 |
284 if (status != STATUS_OK) | 288 if (status != STATUS_OK) |
285 return status; | 289 return status; |
286 | 290 |
287 if (!base::StringToInt64(value, &next_notification_id_) || | 291 if (!base::StringToInt64(value, &next_persistent_notification_id_) || |
288 next_notification_id_ < kFirstNotificationId) { | 292 next_persistent_notification_id_ < kFirstPersistentNotificationId) { |
289 return STATUS_ERROR_CORRUPTED; | 293 return STATUS_ERROR_CORRUPTED; |
290 } | 294 } |
291 | 295 |
296 written_persistent_notification_id_ = next_persistent_notification_id_; | |
297 | |
292 return STATUS_OK; | 298 return STATUS_OK; |
293 } | 299 } |
294 | 300 |
295 NotificationDatabase::Status | 301 NotificationDatabase::Status |
296 NotificationDatabase::ReadAllNotificationDataInternal( | 302 NotificationDatabase::ReadAllNotificationDataInternal( |
297 const GURL& origin, | 303 const GURL& origin, |
298 int64_t service_worker_registration_id, | 304 int64_t service_worker_registration_id, |
299 std::vector<NotificationDatabaseData>* notification_data_vector) const { | 305 std::vector<NotificationDatabaseData>* notification_data_vector) const { |
300 DCHECK(sequence_checker_.CalledOnValidSequence()); | 306 DCHECK(sequence_checker_.CalledOnValidSequence()); |
301 DCHECK(notification_data_vector); | 307 DCHECK(notification_data_vector); |
302 | 308 |
303 const std::string prefix = CreateDataPrefix(origin); | 309 const std::string prefix = CreateDataPrefix(origin); |
304 | 310 |
305 leveldb::Slice prefix_slice(prefix); | 311 leveldb::Slice prefix_slice(prefix); |
306 | 312 |
307 NotificationDatabaseData notification_database_data; | 313 NotificationDatabaseData notification_database_data; |
308 std::unique_ptr<leveldb::Iterator> iter( | 314 std::unique_ptr<leveldb::Iterator> iter( |
309 db_->NewIterator(leveldb::ReadOptions())); | 315 db_->NewIterator(leveldb::ReadOptions())); |
310 for (iter->Seek(prefix_slice); iter->Valid(); iter->Next()) { | 316 for (iter->Seek(prefix_slice); iter->Valid(); iter->Next()) { |
311 if (!iter->key().starts_with(prefix_slice)) | 317 if (!iter->key().starts_with(prefix_slice)) |
312 break; | 318 break; |
313 | 319 |
314 Status status = DeserializedNotificationData(iter->value().ToString(), | 320 Status status = DeserializedNotificationData(iter->value().ToString(), |
315 ¬ification_database_data); | 321 ¬ification_database_data); |
316 if (status != STATUS_OK) | 322 if (status != STATUS_OK) |
317 return status; | 323 return status; |
johnme
2016/09/08 15:21:50
I'm concerned that notifications that pre-date the
Peter Beverloo
2016/09/08 18:56:03
Why would it fail to deserialize? That'd work just
| |
318 | 324 |
319 if (service_worker_registration_id != kInvalidServiceWorkerRegistrationId && | 325 if (service_worker_registration_id != kInvalidServiceWorkerRegistrationId && |
320 notification_database_data.service_worker_registration_id != | 326 notification_database_data.service_worker_registration_id != |
321 service_worker_registration_id) { | 327 service_worker_registration_id) { |
322 continue; | 328 continue; |
323 } | 329 } |
324 | 330 |
325 notification_data_vector->push_back(notification_database_data); | 331 notification_data_vector->push_back(notification_database_data); |
326 } | 332 } |
327 | 333 |
328 return LevelDBStatusToStatus(iter->status()); | 334 return LevelDBStatusToStatus(iter->status()); |
329 } | 335 } |
330 | 336 |
331 NotificationDatabase::Status | 337 NotificationDatabase::Status |
332 NotificationDatabase::DeleteAllNotificationDataInternal( | 338 NotificationDatabase::DeleteAllNotificationDataInternal( |
333 const GURL& origin, | 339 const GURL& origin, |
334 const std::string& tag, | 340 const std::string& tag, |
335 int64_t service_worker_registration_id, | 341 int64_t service_worker_registration_id, |
336 std::set<int64_t>* deleted_notification_set) { | 342 std::set<std::string>* deleted_notification_ids) { |
337 DCHECK(sequence_checker_.CalledOnValidSequence()); | 343 DCHECK(sequence_checker_.CalledOnValidSequence()); |
338 DCHECK(deleted_notification_set); | 344 DCHECK(deleted_notification_ids); |
339 DCHECK(origin.is_valid()); | 345 DCHECK(origin.is_valid()); |
340 | 346 |
341 const std::string prefix = CreateDataPrefix(origin); | 347 const std::string prefix = CreateDataPrefix(origin); |
342 const bool should_deserialize = | |
343 service_worker_registration_id != kInvalidServiceWorkerRegistrationId || | |
344 !tag.empty(); | |
345 | 348 |
346 leveldb::Slice prefix_slice(prefix); | 349 leveldb::Slice prefix_slice(prefix); |
347 leveldb::WriteBatch batch; | 350 leveldb::WriteBatch batch; |
348 | 351 |
349 NotificationDatabaseData notification_database_data; | 352 NotificationDatabaseData notification_database_data; |
350 std::unique_ptr<leveldb::Iterator> iter( | 353 std::unique_ptr<leveldb::Iterator> iter( |
351 db_->NewIterator(leveldb::ReadOptions())); | 354 db_->NewIterator(leveldb::ReadOptions())); |
352 for (iter->Seek(prefix_slice); iter->Valid(); iter->Next()) { | 355 for (iter->Seek(prefix_slice); iter->Valid(); iter->Next()) { |
353 if (!iter->key().starts_with(prefix_slice)) | 356 if (!iter->key().starts_with(prefix_slice)) |
354 break; | 357 break; |
355 | 358 |
356 if (should_deserialize) { | 359 Status status = DeserializedNotificationData(iter->value().ToString(), |
357 Status status = DeserializedNotificationData(iter->value().ToString(), | 360 ¬ification_database_data); |
358 ¬ification_database_data); | 361 if (status != STATUS_OK) |
359 if (status != STATUS_OK) | 362 return status; |
360 return status; | |
361 | 363 |
362 if (!tag.empty() && | 364 if (!tag.empty() && |
363 notification_database_data.notification_data.tag != tag) { | 365 notification_database_data.notification_data.tag != tag) { |
364 continue; | 366 continue; |
365 } | |
366 | |
367 if (service_worker_registration_id != | |
368 kInvalidServiceWorkerRegistrationId && | |
369 notification_database_data.service_worker_registration_id != | |
370 service_worker_registration_id) { | |
371 continue; | |
372 } | |
373 } | 367 } |
374 | 368 |
375 leveldb::Slice notification_id_slice = iter->key(); | 369 if (service_worker_registration_id != kInvalidServiceWorkerRegistrationId && |
376 notification_id_slice.remove_prefix(prefix_slice.size()); | 370 notification_database_data.service_worker_registration_id != |
377 | 371 service_worker_registration_id) { |
378 int64_t notification_id = 0; | 372 continue; |
379 if (!base::StringToInt64(notification_id_slice.ToString(), | |
380 ¬ification_id)) { | |
381 return STATUS_ERROR_CORRUPTED; | |
382 } | 373 } |
383 | 374 |
384 deleted_notification_set->insert(notification_id); | |
385 batch.Delete(iter->key()); | 375 batch.Delete(iter->key()); |
376 deleted_notification_ids->insert( | |
377 notification_database_data.notification_id); | |
386 } | 378 } |
387 | 379 |
388 if (deleted_notification_set->empty()) | 380 if (deleted_notification_ids->empty()) |
389 return STATUS_OK; | 381 return STATUS_OK; |
390 | 382 |
391 return LevelDBStatusToStatus(db_->Write(leveldb::WriteOptions(), &batch)); | 383 return LevelDBStatusToStatus(db_->Write(leveldb::WriteOptions(), &batch)); |
392 } | 384 } |
393 | 385 |
394 } // namespace content | 386 } // namespace content |
OLD | NEW |