| 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 b0c445e24ebc76e35ddd1e8b73e8fe019a07a7fa..f229fe7e5873b123382187124165441ab0c392d5 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,120 @@ 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:
|
| + DCHECK(missing->empty());
|
| + success = true;
|
| + 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 +191,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 +219,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;
|
|
|