Index: components/dom_distiller/core/dom_distiller_store.cc |
diff --git a/components/dom_distiller/core/dom_distiller_store.cc b/components/dom_distiller/core/dom_distiller_store.cc |
index 8a3aad588139ad4f1082b11d26a44b5b27e287fd..72e480f4127c8fba819d97586f816790faef942e 100644 |
--- a/components/dom_distiller/core/dom_distiller_store.cc |
+++ b/components/dom_distiller/core/dom_distiller_store.cc |
@@ -6,6 +6,7 @@ |
#include "base/bind.h" |
#include "base/logging.h" |
+#include "base/message_loop/message_loop.h" |
#include "components/dom_distiller/core/article_entry.h" |
#include "sync/api/sync_change.h" |
#include "sync/protocol/article_specifics.pb.h" |
@@ -29,6 +30,7 @@ DomDistillerStore::DomDistillerStore( |
const base::FilePath& database_dir) |
: database_(database.Pass()), |
database_loaded_(false), |
+ attachment_store_(syncer::AttachmentStore::CreateInMemoryStore()), |
weak_ptr_factory_(this) { |
database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, |
weak_ptr_factory_.GetWeakPtr())); |
@@ -40,6 +42,7 @@ DomDistillerStore::DomDistillerStore( |
const base::FilePath& database_dir) |
: database_(database.Pass()), |
database_loaded_(false), |
+ attachment_store_(syncer::AttachmentStore::CreateInMemoryStore()), |
model_(initial_data), |
weak_ptr_factory_(this) { |
database_->Init(database_dir, base::Bind(&DomDistillerStore::OnDatabaseInit, |
@@ -62,6 +65,119 @@ bool DomDistillerStore::GetEntryByUrl(const GURL& url, ArticleEntry* entry) { |
return model_.GetEntryByUrl(url, entry); |
} |
+void DomDistillerStore::UpdateAttachments( |
+ const std::string& entry_id, |
+ scoped_ptr<ArticleAttachmentsData> attachments_data, |
+ const UpdateAttachmentsCallback& callback) { |
+ if (!GetEntryById(entry_id, nullptr)) { |
+ base::MessageLoop::current()->PostTask(FROM_HERE, |
+ base::Bind(callback, false)); |
+ } |
+ |
+ scoped_ptr<sync_pb::ArticleAttachments> article_attachments( |
+ new sync_pb::ArticleAttachments()); |
+ syncer::AttachmentList attachment_list; |
+ attachments_data->CreateSyncAttachments(&attachment_list, |
+ article_attachments.get()); |
+ |
+ attachment_store_->Write( |
+ attachment_list, |
+ base::Bind(&DomDistillerStore::OnAttachmentsWrite, |
+ weak_ptr_factory_.GetWeakPtr(), entry_id, |
+ base::Passed(&article_attachments), callback)); |
+} |
+ |
+void DomDistillerStore::OnAttachmentsWrite( |
+ const std::string& entry_id, |
+ scoped_ptr<sync_pb::ArticleAttachments> article_attachments, |
+ const UpdateAttachmentsCallback& callback, |
+ const syncer::AttachmentStore::Result& result) { |
+ bool success = false; |
+ switch (result) { |
+ case syncer::AttachmentStore::UNSPECIFIED_ERROR: |
+ break; |
+ case syncer::AttachmentStore::SUCCESS: |
+ success = true; |
+ break; |
+ } |
+ |
+ if (success) { |
+ ArticleEntry entry; |
+ bool has_entry = GetEntryById(entry_id, &entry); |
+ if (!has_entry) { |
+ success = false; |
+ attachment_store_->Drop(GetAttachmentIds(*article_attachments), |
+ syncer::AttachmentStore::DropCallback()); |
+ } else { |
+ if (entry.has_attachments()) { |
+ attachment_store_->Drop(GetAttachmentIds(entry.attachments()), |
+ syncer::AttachmentStore::DropCallback()); |
+ } |
+ entry.set_allocated_attachments(article_attachments.release()); |
+ |
+ SyncChangeList changes_to_apply; |
+ changes_to_apply.push_back(SyncChange( |
+ FROM_HERE, SyncChange::ACTION_UPDATE, CreateLocalData(entry))); |
+ |
+ SyncChangeList changes_applied; |
+ SyncChangeList changes_missing; |
+ |
+ ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing); |
+ |
+ DCHECK_EQ(size_t(0), changes_missing.size()); |
+ DCHECK_EQ(size_t(1), changes_applied.size()); |
+ |
+ ApplyChangesToSync(FROM_HERE, changes_applied); |
+ ApplyChangesToDatabase(changes_applied); |
+ } |
+ } |
+ base::MessageLoop::current()->PostTask(FROM_HERE, |
+ base::Bind(callback, success)); |
+} |
+ |
+void DomDistillerStore::GetAttachments( |
+ const std::string& entry_id, |
+ const GetAttachmentsCallback& callback) { |
+ ArticleEntry entry; |
+ if (!model_.GetEntryById(entry_id, &entry) |
+ || !entry.has_attachments()) { |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, base::Bind(callback, false, nullptr)); |
+ return; |
+ } |
+ |
+ // TODO(cjhopman): This should use GetOrDownloadAttachments() once there is a |
+ // feasible way to use that. |
+ attachment_store_->Read(GetAttachmentIds(entry.attachments()), |
+ base::Bind(&DomDistillerStore::OnAttachmentsRead, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ entry.attachments(), callback)); |
+} |
+ |
+void DomDistillerStore::OnAttachmentsRead( |
+ const sync_pb::ArticleAttachments& attachments_proto, |
+ const GetAttachmentsCallback& callback, |
+ const syncer::AttachmentStore::Result& result, |
+ scoped_ptr<syncer::AttachmentMap> attachments, |
+ scoped_ptr<syncer::AttachmentIdList> missing) { |
+ bool success = false; |
+ switch (result) { |
+ case syncer::AttachmentStore::UNSPECIFIED_ERROR: |
+ break; |
+ case syncer::AttachmentStore::SUCCESS: |
+ success = missing->empty(); |
pavely
2014/11/17 19:09:00
Minor comment: if result is SUCCESS then |missing|
cjhopman
2014/11/18 20:57:45
Done.
|
+ break; |
+ } |
+ scoped_ptr<ArticleAttachmentsData> attachments_data; |
+ if (success) { |
+ attachments_data = ArticleAttachmentsData::GetFromAttachmentMap( |
+ attachments_proto, *attachments); |
+ } |
+ base::MessageLoop::current()->PostTask( |
+ FROM_HERE, |
+ base::Bind(callback, success, base::Passed(&attachments_data))); |
+} |
+ |
bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { |
return ChangeEntry(entry, SyncChange::ACTION_ADD); |
} |
@@ -74,6 +190,22 @@ bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) { |
return ChangeEntry(entry, SyncChange::ACTION_DELETE); |
} |
+namespace { |
+ |
+bool VerifyAttachmentsUnchanged(const ArticleEntry& entry, |
+ const DomDistillerModel& model) { |
+ ArticleEntry currentEntry; |
+ model.GetEntryById(entry.entry_id(), ¤tEntry); |
+ DCHECK_EQ(currentEntry.has_attachments(), entry.has_attachments()); |
+ if (currentEntry.has_attachments()) { |
+ DCHECK_EQ(currentEntry.attachments().SerializeAsString(), |
+ entry.attachments().SerializeAsString()); |
+ } |
+ return true; |
+} |
+ |
+} // namespace |
+ |
bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry, |
SyncChange::SyncChangeType changeType) { |
if (!database_loaded_) { |
@@ -86,6 +218,7 @@ bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry, |
DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; |
return false; |
} |
+ DCHECK(VerifyAttachmentsUnchanged(entry, model_)); |
} else if (changeType != SyncChange::ACTION_ADD) { |
DVLOG(1) << "No entry with id " << entry.entry_id() << " found."; |
return false; |