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

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: 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()),
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 const UpdateAttachmentsCallback& callback) {
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 const UpdateAttachmentsCallback& callback,
94 const syncer::AttachmentStore::Result& result) {
95 bool success = false;
96 switch (result) {
97 case syncer::AttachmentStore::UNSPECIFIED_ERROR:
98 break;
99 case syncer::AttachmentStore::SUCCESS:
100 success = true;
101 break;
102 }
103
104 if (success) {
105 ArticleEntry entry;
106 bool has_entry = GetEntryById(entry_id, &entry);
107 if (!has_entry) {
108 success = false;
109 attachment_store_->Drop(GetAttachmentIds(*article_attachments),
110 syncer::AttachmentStore::DropCallback());
111 } else {
112 if (entry.has_attachments()) {
113 attachment_store_->Drop(GetAttachmentIds(entry.attachments()),
114 syncer::AttachmentStore::DropCallback());
115 }
116 entry.set_allocated_attachments(article_attachments.release());
117
118 SyncChangeList changes_to_apply;
119 changes_to_apply.push_back(SyncChange(
120 FROM_HERE, SyncChange::ACTION_UPDATE, CreateLocalData(entry)));
121
122 SyncChangeList changes_applied;
123 SyncChangeList changes_missing;
124
125 ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing);
126
127 DCHECK_EQ(size_t(0), changes_missing.size());
128 DCHECK_EQ(size_t(1), changes_applied.size());
129
130 ApplyChangesToSync(FROM_HERE, changes_applied);
131 ApplyChangesToDatabase(changes_applied);
132 }
133 }
134 base::MessageLoop::current()->PostTask(FROM_HERE,
135 base::Bind(callback, success));
136 }
137
138 void DomDistillerStore::GetAttachments(
139 const std::string& entry_id,
140 const GetAttachmentsCallback& callback) {
141 ArticleEntry entry;
142 if (!model_.GetEntryById(entry_id, &entry)
143 || !entry.has_attachments()) {
144 base::MessageLoop::current()->PostTask(
145 FROM_HERE, base::Bind(callback, false, nullptr));
146 return;
147 }
148
149 // TODO(cjhopman): This should use GetOrDownloadAttachments() once there is a
150 // feasible way to use that.
151 attachment_store_->Read(GetAttachmentIds(entry.attachments()),
152 base::Bind(&DomDistillerStore::OnAttachmentsRead,
153 weak_ptr_factory_.GetWeakPtr(),
154 entry.attachments(), callback));
155 }
156
157 void DomDistillerStore::OnAttachmentsRead(
158 const sync_pb::ArticleAttachments& attachments_proto,
159 const GetAttachmentsCallback& callback,
160 const syncer::AttachmentStore::Result& result,
161 scoped_ptr<syncer::AttachmentMap> attachments,
162 scoped_ptr<syncer::AttachmentIdList> missing) {
163 bool success = false;
164 switch (result) {
165 case syncer::AttachmentStore::UNSPECIFIED_ERROR:
166 break;
167 case syncer::AttachmentStore::SUCCESS:
168 DCHECK(missing->empty());
169 success = true;
170 break;
171 }
172 scoped_ptr<ArticleAttachmentsData> attachments_data;
173 if (success) {
174 attachments_data = ArticleAttachmentsData::GetFromAttachmentMap(
175 attachments_proto, *attachments);
176 }
177 base::MessageLoop::current()->PostTask(
178 FROM_HERE,
179 base::Bind(callback, success, base::Passed(&attachments_data)));
180 }
181
65 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { 182 bool DomDistillerStore::AddEntry(const ArticleEntry& entry) {
66 return ChangeEntry(entry, SyncChange::ACTION_ADD); 183 return ChangeEntry(entry, SyncChange::ACTION_ADD);
67 } 184 }
68 185
69 bool DomDistillerStore::UpdateEntry(const ArticleEntry& entry) { 186 bool DomDistillerStore::UpdateEntry(const ArticleEntry& entry) {
70 return ChangeEntry(entry, SyncChange::ACTION_UPDATE); 187 return ChangeEntry(entry, SyncChange::ACTION_UPDATE);
71 } 188 }
72 189
73 bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) { 190 bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) {
74 return ChangeEntry(entry, SyncChange::ACTION_DELETE); 191 return ChangeEntry(entry, SyncChange::ACTION_DELETE);
75 } 192 }
76 193
194 namespace {
195
196 bool VerifyAttachmentsUnchanged(const ArticleEntry& entry,
197 const DomDistillerModel& model) {
198 ArticleEntry currentEntry;
199 model.GetEntryById(entry.entry_id(), &currentEntry);
200 DCHECK_EQ(currentEntry.has_attachments(), entry.has_attachments());
201 if (currentEntry.has_attachments()) {
202 DCHECK_EQ(currentEntry.attachments().SerializeAsString(),
203 entry.attachments().SerializeAsString());
204 }
205 return true;
206 }
207
208 } // namespace
209
77 bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry, 210 bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry,
78 SyncChange::SyncChangeType changeType) { 211 SyncChange::SyncChangeType changeType) {
79 if (!database_loaded_) { 212 if (!database_loaded_) {
80 return false; 213 return false;
81 } 214 }
82 215
83 bool hasEntry = model_.GetEntryById(entry.entry_id(), NULL); 216 bool hasEntry = model_.GetEntryById(entry.entry_id(), NULL);
84 if (hasEntry) { 217 if (hasEntry) {
85 if (changeType == SyncChange::ACTION_ADD) { 218 if (changeType == SyncChange::ACTION_ADD) {
86 DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; 219 DVLOG(1) << "Already have entry with id " << entry.entry_id() << ".";
87 return false; 220 return false;
88 } 221 }
222 DCHECK(VerifyAttachmentsUnchanged(entry, model_));
89 } else if (changeType != SyncChange::ACTION_ADD) { 223 } else if (changeType != SyncChange::ACTION_ADD) {
90 DVLOG(1) << "No entry with id " << entry.entry_id() << " found."; 224 DVLOG(1) << "No entry with id " << entry.entry_id() << " found.";
91 return false; 225 return false;
92 } 226 }
93 227
94 SyncChangeList changes_to_apply; 228 SyncChangeList changes_to_apply;
95 changes_to_apply.push_back( 229 changes_to_apply.push_back(
96 SyncChange(FROM_HERE, changeType, CreateLocalData(entry))); 230 SyncChange(FROM_HERE, changeType, CreateLocalData(entry)));
97 231
98 SyncChangeList changes_applied; 232 SyncChangeList changes_applied;
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
331 result.set_num_items_deleted(0); 465 result.set_num_items_deleted(0);
332 466
333 result.set_pre_association_version(0); 467 result.set_pre_association_version(0);
334 result.set_num_items_after_association(model_.GetNumEntries()); 468 result.set_num_items_after_association(model_.GetNumEntries());
335 result.set_error(error); 469 result.set_error(error);
336 470
337 return result; 471 return result;
338 } 472 }
339 473
340 } // namespace dom_distiller 474 } // namespace dom_distiller
OLDNEW
« no previous file with comments | « components/dom_distiller/core/dom_distiller_store.h ('k') | components/dom_distiller/core/dom_distiller_store_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698