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

Side by Side Diff: components/dom_distiller/core/dom_distiller_store.cc

Issue 717793007: Add attachments support to DomDistillerStore (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Move some unrelated stuff out Created 6 years, 1 month 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "components/dom_distiller/core/dom_distiller_store.h" 5 #include "components/dom_distiller/core/dom_distiller_store.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
9 #include "components/dom_distiller/core/article_entry.h" 10 #include "components/dom_distiller/core/article_entry.h"
10 #include "sync/api/sync_change.h" 11 #include "sync/api/sync_change.h"
11 #include "sync/protocol/article_specifics.pb.h" 12 #include "sync/protocol/article_specifics.pb.h"
12 #include "sync/protocol/sync.pb.h" 13 #include "sync/protocol/sync.pb.h"
13 14
14 using leveldb_proto::ProtoDatabase; 15 using leveldb_proto::ProtoDatabase;
15 using sync_pb::ArticleSpecifics; 16 using sync_pb::ArticleSpecifics;
16 using sync_pb::EntitySpecifics; 17 using sync_pb::EntitySpecifics;
17 using syncer::ModelType; 18 using syncer::ModelType;
18 using syncer::SyncChange; 19 using syncer::SyncChange;
19 using syncer::SyncChangeList; 20 using syncer::SyncChangeList;
20 using syncer::SyncData; 21 using syncer::SyncData;
21 using syncer::SyncDataList; 22 using syncer::SyncDataList;
22 using syncer::SyncError; 23 using syncer::SyncError;
23 using syncer::SyncMergeResult; 24 using syncer::SyncMergeResult;
24 25
25 namespace dom_distiller { 26 namespace dom_distiller {
26 27
27 DomDistillerStore::DomDistillerStore( 28 DomDistillerStore::DomDistillerStore(
28 scoped_ptr<ProtoDatabase<ArticleEntry> > database, 29 scoped_ptr<ProtoDatabase<ArticleEntry> > database,
29 const base::FilePath& database_dir) 30 const base::FilePath& database_dir)
30 : database_(database.Pass()), 31 : database_(database.Pass()),
31 database_loaded_(false), 32 database_loaded_(false),
33 attachment_store_(syncer::AttachmentStore::CreateInMemoryStore()),
maniscalco 2014/11/12 18:59:44 Is the async construction requirement of the on di
cjhopman 2014/11/14 02:45:15 yes.
32 weak_ptr_factory_(this) { 34 weak_ptr_factory_(this) {
33 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, 35 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit,
34 weak_ptr_factory_.GetWeakPtr())); 36 weak_ptr_factory_.GetWeakPtr()));
35 } 37 }
36 38
37 DomDistillerStore::DomDistillerStore( 39 DomDistillerStore::DomDistillerStore(
38 scoped_ptr<ProtoDatabase<ArticleEntry> > database, 40 scoped_ptr<ProtoDatabase<ArticleEntry> > database,
39 const std::vector<ArticleEntry>& initial_data, 41 const std::vector<ArticleEntry>& initial_data,
40 const base::FilePath& database_dir) 42 const base::FilePath& database_dir)
41 : database_(database.Pass()), 43 : database_(database.Pass()),
42 database_loaded_(false), 44 database_loaded_(false),
45 attachment_store_(syncer::AttachmentStore::CreateInMemoryStore()),
43 model_(initial_data), 46 model_(initial_data),
44 weak_ptr_factory_(this) { 47 weak_ptr_factory_(this) {
45 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, 48 database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit,
46 weak_ptr_factory_.GetWeakPtr())); 49 weak_ptr_factory_.GetWeakPtr()));
47 } 50 }
48 51
49 DomDistillerStore::~DomDistillerStore() {} 52 DomDistillerStore::~DomDistillerStore() {}
50 53
51 // DomDistillerStoreInterface implementation. 54 // DomDistillerStoreInterface implementation.
52 syncer::SyncableService* DomDistillerStore::GetSyncableService() { 55 syncer::SyncableService* DomDistillerStore::GetSyncableService() {
53 return this; 56 return this;
54 } 57 }
55 58
56 bool DomDistillerStore::GetEntryById(const std::string& entry_id, 59 bool DomDistillerStore::GetEntryById(const std::string& entry_id,
57 ArticleEntry* entry) { 60 ArticleEntry* entry) {
58 return model_.GetEntryById(entry_id, entry); 61 return model_.GetEntryById(entry_id, entry);
59 } 62 }
60 63
61 bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) { 64 bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) {
62 return model_.GetEntryByUrl(url, entry); 65 return model_.GetEntryByUrl(url, entry);
63 } 66 }
64 67
68 void DomDistillerStore::UpdateAttachments(
69 const std::string& entry_id,
70 scoped_ptr<ArticleAttachmentsData> attachments_data,
71 UpdateAttachmentsCallback callback) {
maniscalco 2014/11/12 18:59:44 Can be passed by const&.
cjhopman 2014/11/14 02:45:15 Done.
72 if (!GetEntryById(entry_id, nullptr)) {
73 base::MessageLoop::current()->PostTask(FROM_HERE,
74 base::Bind(callback, false));
75 }
76
77 scoped_ptr<sync_pb::ArticleAttachments> article_attachments(
78 new sync_pb::ArticleAttachments());
79 syncer::AttachmentList attachment_list;
80 attachments_data->CreateSyncAttachments(&attachment_list,
81 article_attachments.get());
82
83 attachment_store_->Write(
84 attachment_list,
85 base::Bind(&DomDistillerStore::OnAttachmentsWrite,
86 weak_ptr_factory_.GetWeakPtr(), entry_id,
87 base::Passed(&article_attachments), callback));
88 }
89
90 void DomDistillerStore::OnAttachmentsWrite(
91 const std::string& entry_id,
92 scoped_ptr<sync_pb::ArticleAttachments> article_attachments,
93 UpdateAttachmentsCallback callback,
maniscalco 2014/11/12 18:59:43 Can be passed by const&.
cjhopman 2014/11/14 02:45:15 Done.
94 const syncer::AttachmentStore::Result& result) {
95 bool success = result == syncer::AttachmentStore::SUCCESS;
maniscalco 2014/11/12 18:59:43 WDYT about using a switch statement without a defa
cjhopman 2014/11/14 02:45:15 Done.
96 if (success) {
maniscalco 2014/11/12 18:59:43 I'm thinking about cases where the write might fai
cjhopman 2014/11/14 02:45:15 Yeah, I could see us handling disk full differentl
97 ArticleEntry entry;
98 bool has_entry = GetEntryById(entry_id, &entry);
99 if (!has_entry) {
100 success = false;
101 attachment_store_->Drop(GetAttachmentIds(*article_attachments),
102 syncer::AttachmentStore::DropCallback());
103 } else {
104 if (entry.has_attachments()) {
105 attachment_store_->Drop(GetAttachmentIds(entry.attachments()),
106 syncer::AttachmentStore::DropCallback());
107 }
108 entry.set_allocated_attachments(article_attachments.release());
109
110 SyncChangeList changes_to_apply;
111 changes_to_apply.push_back(SyncChange(
112 FROM_HERE, SyncChange::ACTION_UPDATE, CreateLocalData(entry)));
113
114 SyncChangeList changes_applied;
115 SyncChangeList changes_missing;
116
117 ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
118
119 DCHECK_EQ(size_t(0), changes_missing.size());
120 DCHECK_EQ(size_t(1), changes_applied.size());
121
122 ApplyChangesToSync(FROM_HERE, changes_applied);
123 ApplyChangesToDatabase(changes_applied);
124 }
125 }
126 callback.Run(success);
maniscalco 2014/11/12 18:59:44 Is it important that callback executes before cont
cjhopman 2014/11/14 02:45:15 Done.
127 }
128
129 void DomDistillerStore::GetAttachments(
130 const std::string& entry_id,
131 GetAttachmentsCallback callback) {
maniscalco 2014/11/12 18:59:44 Can be passed by const&.
cjhopman 2014/11/14 02:45:15 Done.
132 ArticleEntry entry;
133 if (!model_.GetEntryById(entry_id, &entry)
134 || !entry.has_attachments()) {
135 base::MessageLoop::current()->PostTask(
136 FROM_HERE, base::Bind(callback, false, nullptr));
137 return;
138 }
139
140 // TODO(cjhopman): This should use GetOrDownloadAttachments() once there is a
141 // feasible way to use that.
142 attachment_store_->Read(GetAttachmentIds(entry.attachments()),
143 base::Bind(&DomDistillerStore::OnAttachmentsRead,
144 weak_ptr_factory_.GetWeakPtr(),
145 entry.attachments(), callback));
146 }
147
148 void DomDistillerStore::OnAttachmentsRead(
149 const sync_pb::ArticleAttachments& attachments_proto,
150 GetAttachmentsCallback callback,
maniscalco 2014/11/12 18:59:43 Can be passed by const&.
cjhopman 2014/11/14 02:45:15 Done.
151 const syncer::AttachmentStore::Result& result,
152 scoped_ptr<syncer::AttachmentMap> attachments,
153 scoped_ptr<syncer::AttachmentIdList> missing) {
154 bool success =
155 (result == syncer::AttachmentStore::SUCCESS) && missing->empty();
156 scoped_ptr<ArticleAttachmentsData> attachments_data;
157 if (success) {
158 attachments_data = ArticleAttachmentsData::GetFromAttachmentMap(
159 attachments_proto, *attachments);
160 }
161 callback.Run(success, attachments_data.Pass());
162 }
163
65 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { 164 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
66 return ChangeEntry(entry, SyncChange::ACTION_ADD); 165 return ChangeEntry(entry, SyncChange::ACTION_ADD);
67 } 166 }
68 167
69 bool DomDistillerStore::UpdateEntry(const ArticleEntry& entry) { 168 bool DomDistillerStore::UpdateEntry(const ArticleEntry& entry) {
70 return ChangeEntry(entry, SyncChange::ACTION_UPDATE); 169 return ChangeEntry(entry, SyncChange::ACTION_UPDATE);
71 } 170 }
72 171
73 bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) { 172 bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) {
74 return ChangeEntry(entry, SyncChange::ACTION_DELETE); 173 return ChangeEntry(entry, SyncChange::ACTION_DELETE);
75 } 174 }
76 175
77 bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry, 176 bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry,
78 SyncChange::SyncChangeType changeType) { 177 SyncChange::SyncChangeType changeType) {
79 if (!database_loaded_) { 178 if (!database_loaded_) {
80 return false; 179 return false;
81 } 180 }
82 181
83 bool hasEntry = model_.GetEntryById(entry.entry_id(), NULL); 182 bool hasEntry = model_.GetEntryById(entry.entry_id(), NULL);
84 if (hasEntry) { 183 if (hasEntry) {
85 if (changeType == SyncChange::ACTION_ADD) { 184 if (changeType == SyncChange::ACTION_ADD) {
86 DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; 185 DVLOG(1) << "Already have entry with id " << entry.entry_id() << ".";
87 return false; 186 return false;
88 } 187 }
188 #ifndef NDEBUG
maniscalco 2014/11/12 18:59:44 WDYT about moving this code into function and call
cjhopman 2014/11/14 02:45:15 I think it's a great idea.
189 ArticleEntry currentEntry;
190 model_.GetEntryById(entry.entry_id(), &currentEntry);
191 DCHECK_EQ(currentEntry.has_attachments(), entry.has_attachments());
192 if (currentEntry.has_attachments()) {
193 DCHECK_EQ(currentEntry.attachments().SerializeAsString(),
194 entry.attachments().SerializeAsString());
195 }
196 #endif
89 } else if (changeType != SyncChange::ACTION_ADD) { 197 } else if (changeType != SyncChange::ACTION_ADD) {
90 DVLOG(1) << "No entry with id " << entry.entry_id() << " found."; 198 DVLOG(1) << "No entry with id " << entry.entry_id() << " found.";
91 return false; 199 return false;
92 } 200 }
93 201
94 SyncChangeList changes_to_apply; 202 SyncChangeList changes_to_apply;
95 changes_to_apply.push_back( 203 changes_to_apply.push_back(
96 SyncChange(FROM_HERE, changeType, CreateLocalData(entry))); 204 SyncChange(FROM_HERE, changeType, CreateLocalData(entry)));
97 205
98 SyncChangeList changes_applied; 206 SyncChangeList changes_applied;
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
333 result.set_num_items_deleted(0); 441 result.set_num_items_deleted(0);
334 442
335 result.set_pre_association_version(0); 443 result.set_pre_association_version(0);
336 result.set_num_items_after_association(model_.GetNumEntries()); 444 result.set_num_items_after_association(model_.GetNumEntries());
337 result.set_error(error); 445 result.set_error(error);
338 446
339 return result; 447 return result;
340 } 448 }
341 449
342 } // namespace dom_distiller 450 } // namespace dom_distiller
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698