1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "sync/api/attachments/fake_attachment_store.h"
6
7#include "base/bind.h"
8#include "base/location.h"
9#include "base/memory/ref_counted_memory.h"
10#include "base/sequenced_task_runner.h"
11#include "base/single_thread_task_runner.h"
12#include "base/thread_task_runner_handle.h"
13#include "sync/api/attachments/attachment.h"
14
15namespace syncer {
16
17// Backend is where all the work happens.
18class FakeAttachmentStore::Backend
19    : public base::RefCountedThreadSafe<FakeAttachmentStore::Backend> {
20 public:
21  // Construct a Backend that posts its results to |frontend_task_runner|.
22  Backend(
23      const scoped_refptr<base::SingleThreadTaskRunner>& frontend_task_runner);
24
25  void Read(const AttachmentIdList& ids, const ReadCallback& callback);
26  void Write(const AttachmentList& attachments, const WriteCallback& callback);
27  void Drop(const AttachmentIdList& ids, const DropCallback& callback);
28
29 private:
30  friend class base::RefCountedThreadSafe<Backend>;
31
32  ~Backend();
33
34  scoped_refptr<base::SingleThreadTaskRunner> frontend_task_runner_;
35  AttachmentMap attachments_;
36};
37
38FakeAttachmentStore::Backend::Backend(
39    const scoped_refptr<base::SingleThreadTaskRunner>& frontend_task_runner)
40    : frontend_task_runner_(frontend_task_runner) {}
41
42FakeAttachmentStore::Backend::~Backend() {}
43
44void FakeAttachmentStore::Backend::Read(const AttachmentIdList& ids,
45                                        const ReadCallback& callback) {
46  Result result_code = SUCCESS;
47  AttachmentIdList::const_iterator id_iter = ids.begin();
48  AttachmentIdList::const_iterator id_end = ids.end();
49  scoped_ptr<AttachmentMap> result_map(new AttachmentMap);
50  scoped_ptr<AttachmentIdList> unavailable_attachments(new AttachmentIdList);
51  for (; id_iter != id_end; ++id_iter) {
52    const AttachmentId& id = *id_iter;
53    syncer::AttachmentMap::iterator attachment_iter =
54        attachments_.find(*id_iter);
55    if (attachment_iter != attachments_.end()) {
56      const Attachment& attachment = attachment_iter->second;
57      result_map->insert(std::make_pair(id, attachment));
58    } else {
59      unavailable_attachments->push_back(id);
60    }
61  }
62  if (!unavailable_attachments->empty()) {
63    result_code = UNSPECIFIED_ERROR;
64  }
65  frontend_task_runner_->PostTask(
66      FROM_HERE,
67      base::Bind(callback,
68                 result_code,
69                 base::Passed(&result_map),
70                 base::Passed(&unavailable_attachments)));
71}
72
73void FakeAttachmentStore::Backend::Write(const AttachmentList& attachments,
74                                         const WriteCallback& callback) {
75  AttachmentList::const_iterator iter = attachments.begin();
76  AttachmentList::const_iterator end = attachments.end();
77  for (; iter != end; ++iter) {
78    attachments_.insert(std::make_pair(iter->GetId(), *iter));
79  }
80  frontend_task_runner_->PostTask(FROM_HERE, base::Bind(callback, SUCCESS));
81}
82
83void FakeAttachmentStore::Backend::Drop(const AttachmentIdList& ids,
84                                        const DropCallback& callback) {
85  Result result = SUCCESS;
86  AttachmentIdList::const_iterator ids_iter = ids.begin();
87  AttachmentIdList::const_iterator ids_end = ids.end();
88  for (; ids_iter != ids_end; ++ids_iter) {
89    AttachmentMap::iterator attachments_iter = attachments_.find(*ids_iter);
90    if (attachments_iter != attachments_.end()) {
91      attachments_.erase(attachments_iter);
92    }
93  }
94  frontend_task_runner_->PostTask(FROM_HERE, base::Bind(callback, result));
95}
96
97FakeAttachmentStore::FakeAttachmentStore(
98    const scoped_refptr<base::SequencedTaskRunner>& backend_task_runner)
99    : backend_(new Backend(base::ThreadTaskRunnerHandle::Get())),
100      backend_task_runner_(backend_task_runner) {}
101
102FakeAttachmentStore::~FakeAttachmentStore() {}
103
104void FakeAttachmentStore::Read(const AttachmentIdList& ids,
105                               const ReadCallback& callback) {
106  backend_task_runner_->PostTask(
107      FROM_HERE,
108      base::Bind(&FakeAttachmentStore::Backend::Read, backend_, ids, callback));
109}
110
111void FakeAttachmentStore::Write(const AttachmentList& attachments,
112                                const WriteCallback& callback) {
113  backend_task_runner_->PostTask(
114      FROM_HERE,
115      base::Bind(&FakeAttachmentStore::Backend::Write,
116                 backend_,
117                 attachments,
118                 callback));
119}
120
121void FakeAttachmentStore::Drop(const AttachmentIdList& ids,
122                               const DropCallback& callback) {
123  backend_task_runner_->PostTask(
124      FROM_HERE,
125      base::Bind(&FakeAttachmentStore::Backend::Drop, backend_, ids, callback));
126}
127
128}  // namespace syncer
129