1e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved.
2e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// found in the LICENSE file.
4e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
55f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sync/internal_api/public/attachments/attachment_service_impl.h"
6e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
71320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <iterator>
81320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
90529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/bind.h"
100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "base/message_loop/message_loop.h"
11116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "base/thread_task_runner_handle.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/time/time.h"
130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "sync/api/attachments/attachment.h"
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "sync/api/attachments/fake_attachment_store.h"
1546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)#include "sync/internal_api/public/attachments/fake_attachment_downloader.h"
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "sync/internal_api/public/attachments/fake_attachment_uploader.h"
17e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochnamespace syncer {
19e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// GetOrDownloadAttachments starts multiple parallel DownloadAttachment calls.
2146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// GetOrDownloadState tracks completion of these calls and posts callback for
2246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// consumer once all attachments are either retrieved or reported unavailable.
2346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class AttachmentServiceImpl::GetOrDownloadState
2446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : public base::RefCounted<GetOrDownloadState>,
2546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      public base::NonThreadSafe {
2646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public:
2746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // GetOrDownloadState gets parameter from values passed to
2846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // AttachmentService::GetOrDownloadAttachments.
2946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // |attachment_ids| is a list of attachmens to retrieve.
3046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // |callback| will be posted on current thread when all attachments retrieved
3146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // or confirmed unavailable.
3246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GetOrDownloadState(const AttachmentIdList& attachment_ids,
3346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     const GetOrDownloadCallback& callback);
3446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Attachment was just retrieved. Add it to retrieved attachments.
3646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void AddAttachment(const Attachment& attachment);
3746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
3846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Both reading from local store and downloading attachment failed.
3946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Add it to unavailable set.
4046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void AddUnavailableAttachmentId(const AttachmentId& attachment_id);
4146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private:
4346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  friend class base::RefCounted<GetOrDownloadState>;
4446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  virtual ~GetOrDownloadState();
4546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
4646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // If all attachment requests completed then post callback to consumer with
4746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // results.
4846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  void PostResultIfAllRequestsCompleted();
4946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  GetOrDownloadCallback callback_;
5146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Requests for these attachments are still in progress.
5346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AttachmentIdSet in_progress_attachments_;
5446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  AttachmentIdSet unavailable_attachments_;
5646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<AttachmentMap> retrieved_attachments_;
5746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
5846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(GetOrDownloadState);
5946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)};
6046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
6146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AttachmentServiceImpl::GetOrDownloadState::GetOrDownloadState(
6246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AttachmentIdList& attachment_ids,
6346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GetOrDownloadCallback& callback)
6446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    : callback_(callback), retrieved_attachments_(new AttachmentMap()) {
6546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::copy(
6646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      attachment_ids.begin(),
6746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      attachment_ids.end(),
6846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::inserter(in_progress_attachments_, in_progress_attachments_.end()));
6946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PostResultIfAllRequestsCompleted();
7046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
7146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AttachmentServiceImpl::GetOrDownloadState::~GetOrDownloadState() {
7346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(CalledOnValidThread());
7446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
7546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AttachmentServiceImpl::GetOrDownloadState::AddAttachment(
7746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const Attachment& attachment) {
7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(CalledOnValidThread());
7946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(retrieved_attachments_->find(attachment.GetId()) ==
8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         retrieved_attachments_->end());
8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  retrieved_attachments_->insert(
8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      std::make_pair(attachment.GetId(), attachment));
8346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(in_progress_attachments_.find(attachment.GetId()) !=
8446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         in_progress_attachments_.end());
8546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  in_progress_attachments_.erase(attachment.GetId());
8646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PostResultIfAllRequestsCompleted();
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AttachmentServiceImpl::GetOrDownloadState::AddUnavailableAttachmentId(
9046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AttachmentId& attachment_id) {
9146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(CalledOnValidThread());
9246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(unavailable_attachments_.find(attachment_id) ==
9346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         unavailable_attachments_.end());
9446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  unavailable_attachments_.insert(attachment_id);
9546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(in_progress_attachments_.find(attachment_id) !=
9646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         in_progress_attachments_.end());
9746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  in_progress_attachments_.erase(attachment_id);
9846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  PostResultIfAllRequestsCompleted();
9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
10146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void
10246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)AttachmentServiceImpl::GetOrDownloadState::PostResultIfAllRequestsCompleted() {
10346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (in_progress_attachments_.empty()) {
10446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // All requests completed. Let's notify consumer.
10546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    GetOrDownloadResult result =
10646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        unavailable_attachments_.empty() ? GET_SUCCESS : GET_UNSPECIFIED_ERROR;
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        FROM_HERE,
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        base::Bind(callback_, result, base::Passed(&retrieved_attachments_)));
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AttachmentServiceImpl::AttachmentServiceImpl(
1141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_refptr<AttachmentStore> attachment_store,
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<AttachmentUploader> attachment_uploader,
11646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<AttachmentDownloader> attachment_downloader,
1171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Delegate* delegate,
1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::TimeDelta& initial_backoff_delay,
1191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const base::TimeDelta& max_backoff_delay)
1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    : attachment_store_(attachment_store),
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      attachment_uploader_(attachment_uploader.Pass()),
12246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      attachment_downloader_(attachment_downloader.Pass()),
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      delegate_(delegate),
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      weak_ptr_factory_(this) {
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(CalledOnValidThread());
1261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(attachment_store_.get());
1271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // TODO(maniscalco): Observe network connectivity change events.  When the
1291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // network becomes disconnected, consider suspending queue dispatch.  When
1301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // connectivity is restored, consider clearing any dispatch backoff (bug
1311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // 411981).
1321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  upload_task_queue_.reset(new TaskQueue<AttachmentId>(
1331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&AttachmentServiceImpl::BeginUpload,
1341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 weak_ptr_factory_.GetWeakPtr()),
1351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      initial_backoff_delay,
1361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      max_backoff_delay));
1371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::NetworkChangeNotifier::AddNetworkChangeObserver(this);
139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)AttachmentServiceImpl::~AttachmentServiceImpl() {
142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(CalledOnValidThread());
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  net::NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Static.
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)scoped_ptr<syncer::AttachmentService> AttachmentServiceImpl::CreateForTest() {
1481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  scoped_refptr<syncer::AttachmentStore> attachment_store(
149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      new syncer::FakeAttachmentStore(base::ThreadTaskRunnerHandle::Get()));
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  scoped_ptr<AttachmentUploader> attachment_uploader(
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      new FakeAttachmentUploader);
15246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<AttachmentDownloader> attachment_downloader(
15346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new FakeAttachmentDownloader());
154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  scoped_ptr<syncer::AttachmentService> attachment_service(
1551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      new syncer::AttachmentServiceImpl(attachment_store,
15646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        attachment_uploader.Pass(),
15746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                        attachment_downloader.Pass(),
1581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        NULL,
1591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        base::TimeDelta(),
1601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                        base::TimeDelta()));
161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return attachment_service.Pass();
162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
1641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciAttachmentStore* AttachmentServiceImpl::GetStore() {
1651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return attachment_store_.get();
1661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
1671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AttachmentServiceImpl::GetOrDownloadAttachments(
169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const AttachmentIdList& attachment_ids,
170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const GetOrDownloadCallback& callback) {
171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(CalledOnValidThread());
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_refptr<GetOrDownloadState> state(
17346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new GetOrDownloadState(attachment_ids, callback));
1740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  attachment_store_->Read(attachment_ids,
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          base::Bind(&AttachmentServiceImpl::ReadDone,
1760529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                     weak_ptr_factory_.GetWeakPtr(),
17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                     state));
178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AttachmentServiceImpl::DropAttachments(
181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const AttachmentIdList& attachment_ids,
182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const DropCallback& callback) {
183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(CalledOnValidThread());
1840529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  attachment_store_->Drop(attachment_ids,
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          base::Bind(&AttachmentServiceImpl::DropDone,
1860529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                     weak_ptr_factory_.GetWeakPtr(),
1870529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                     callback));
188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AttachmentServiceImpl::ReadDone(
19146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const scoped_refptr<GetOrDownloadState>& state,
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AttachmentStore::Result& result,
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<AttachmentMap> attachments,
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<AttachmentIdList> unavailable_attachment_ids) {
19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Add read attachments to result.
19646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (AttachmentMap::const_iterator iter = attachments->begin();
19746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       iter != attachments->end();
19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++iter) {
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    state->AddAttachment(iter->second);
20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
201116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
202116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AttachmentIdList::const_iterator iter = unavailable_attachment_ids->begin();
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  AttachmentIdList::const_iterator end = unavailable_attachment_ids->end();
204116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (attachment_downloader_.get()) {
205116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // Try to download locally unavailable attachments.
206116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (; iter != end; ++iter) {
207116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      attachment_downloader_->DownloadAttachment(
208116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          *iter,
209116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          base::Bind(&AttachmentServiceImpl::DownloadDone,
210116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     weak_ptr_factory_.GetWeakPtr(),
211116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     state,
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                     *iter));
213116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
214116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  } else {
215116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // No downloader so all locally unavailable attachments are unavailable.
216116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    for (; iter != end; ++iter) {
217116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      state->AddUnavailableAttachmentId(*iter);
218116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    }
2190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2210529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AttachmentServiceImpl::DropDone(const DropCallback& callback,
2230529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                     const AttachmentStore::Result& result) {
2240529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  AttachmentService::DropResult drop_result =
2250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      AttachmentService::DROP_UNSPECIFIED_ERROR;
2260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (result == AttachmentStore::SUCCESS) {
2270529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    drop_result = AttachmentService::DROP_SUCCESS;
2280529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  }
2290529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // TODO(maniscalco): Deal with case where an error occurred (bug 361251).
2300529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  base::MessageLoop::current()->PostTask(FROM_HERE,
2310529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch                                         base::Bind(callback, drop_result));
2320529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
2330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void AttachmentServiceImpl::UploadDone(
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AttachmentUploader::UploadResult& result,
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const AttachmentId& attachment_id) {
2371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(CalledOnValidThread());
2381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switch (result) {
2391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case AttachmentUploader::UPLOAD_SUCCESS:
2401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      upload_task_queue_->MarkAsSucceeded(attachment_id);
2411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      if (delegate_) {
2421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        delegate_->OnAttachmentUploaded(attachment_id);
2431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      }
2441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
2451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case AttachmentUploader::UPLOAD_TRANSIENT_ERROR:
2461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      upload_task_queue_->MarkAsFailed(attachment_id);
2471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      upload_task_queue_->AddToQueue(attachment_id);
2481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
2491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case AttachmentUploader::UPLOAD_UNSPECIFIED_ERROR:
2501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // TODO(pavely): crbug/372622: Deal with UploadAttachment failures.
2511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      upload_task_queue_->MarkAsFailed(attachment_id);
2521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
25646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void AttachmentServiceImpl::DownloadDone(
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const scoped_refptr<GetOrDownloadState>& state,
25846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AttachmentId& attachment_id,
25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const AttachmentDownloader::DownloadResult& result,
26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    scoped_ptr<Attachment> attachment) {
2611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  switch (result) {
2621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case AttachmentDownloader::DOWNLOAD_SUCCESS:
2631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      state->AddAttachment(*attachment.get());
2641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
2651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case AttachmentDownloader::DOWNLOAD_TRANSIENT_ERROR:
2661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    case AttachmentDownloader::DOWNLOAD_UNSPECIFIED_ERROR:
2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      state->AddUnavailableAttachmentId(attachment_id);
2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      break;
2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AttachmentServiceImpl::BeginUpload(const AttachmentId& attachment_id) {
2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(CalledOnValidThread());
2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AttachmentIdList attachment_ids;
2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  attachment_ids.push_back(attachment_id);
2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  attachment_store_->Read(attachment_ids,
2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                          base::Bind(&AttachmentServiceImpl::ReadDoneNowUpload,
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                     weak_ptr_factory_.GetWeakPtr()));
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AttachmentServiceImpl::UploadAttachments(
2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const AttachmentIdSet& attachment_ids) {
2831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(CalledOnValidThread());
2841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!attachment_uploader_.get()) {
2851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
28646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
2871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AttachmentIdSet::const_iterator iter = attachment_ids.begin();
2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AttachmentIdSet::const_iterator end = attachment_ids.end();
2891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (; iter != end; ++iter) {
2901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    upload_task_queue_->AddToQueue(*iter);
2911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
2931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AttachmentServiceImpl::OnNetworkChanged(
2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    net::NetworkChangeNotifier::ConnectionType type) {
2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (type != net::NetworkChangeNotifier::CONNECTION_NONE) {
2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    upload_task_queue_->ResetBackoff();
2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AttachmentServiceImpl::ReadDoneNowUpload(
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const AttachmentStore::Result& result,
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<AttachmentMap> attachments,
3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    scoped_ptr<AttachmentIdList> unavailable_attachment_ids) {
3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(CalledOnValidThread());
3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!unavailable_attachment_ids->empty()) {
3071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // TODO(maniscalco): We failed to read some attachments. What should we do
3081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // now?
3091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AttachmentIdList::const_iterator iter = unavailable_attachment_ids->begin();
3101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    AttachmentIdList::const_iterator end = unavailable_attachment_ids->end();
3111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    for (; iter != end; ++iter) {
3121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      upload_task_queue_->Cancel(*iter);
3131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AttachmentMap::const_iterator iter = attachments->begin();
3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  AttachmentMap::const_iterator end = attachments->end();
3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (; iter != end; ++iter) {
3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    attachment_uploader_->UploadAttachment(
3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        iter->second,
3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&AttachmentServiceImpl::UploadDone,
3221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   weak_ptr_factory_.GetWeakPtr()));
3231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
3251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid AttachmentServiceImpl::SetTimerForTest(scoped_ptr<base::Timer> timer) {
3271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  upload_task_queue_->SetTimerForTest(timer.Pass());
32846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
32946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
330e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}  // namespace syncer
331