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

Unified Diff: sync/internal_api/attachments/attachment_uploader_impl.cc

Issue 2130453004: [Sync] Move //sync to //components/sync. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebase. Created 4 years, 5 months 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 side-by-side diff with in-line comments
Download patch
Index: sync/internal_api/attachments/attachment_uploader_impl.cc
diff --git a/sync/internal_api/attachments/attachment_uploader_impl.cc b/sync/internal_api/attachments/attachment_uploader_impl.cc
deleted file mode 100644
index 6666f5cb31a816c1245adbec6fff5ba28bffb8e1..0000000000000000000000000000000000000000
--- a/sync/internal_api/attachments/attachment_uploader_impl.cc
+++ /dev/null
@@ -1,402 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "sync/internal_api/public/attachments/attachment_uploader_impl.h"
-
-#include <stdint.h>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/base64.h"
-#include "base/base64url.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/single_thread_task_runner.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_byteorder.h"
-#include "base/threading/non_thread_safe.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_fetcher_delegate.h"
-#include "net/url_request/url_request_status.h"
-#include "sync/api/attachments/attachment.h"
-#include "sync/protocol/sync.pb.h"
-
-namespace {
-
-const char kContentType[] = "application/octet-stream";
-const char kAttachments[] = "attachments/";
-const char kSyncStoreBirthday[] = "X-Sync-Store-Birthday";
-const char kSyncDataTypeId[] = "X-Sync-Data-Type-Id";
-
-} // namespace
-
-namespace syncer {
-
-// Encapsulates all the state associated with a single upload.
-class AttachmentUploaderImpl::UploadState : public net::URLFetcherDelegate,
- public OAuth2TokenService::Consumer,
- public base::NonThreadSafe {
- public:
- // Construct an UploadState.
- //
- // UploadState encapsulates the state associated with a single upload. When
- // the upload completes, the UploadState object becomes "stopped".
- //
- // |owner| is a pointer to the object that owns this UploadState. Upon
- // completion this object will PostTask to owner's OnUploadStateStopped
- // method.
- UploadState(
- const GURL& upload_url,
- const scoped_refptr<net::URLRequestContextGetter>&
- url_request_context_getter,
- const Attachment& attachment,
- const UploadCallback& user_callback,
- const std::string& account_id,
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider,
- const std::string& raw_store_birthday,
- const base::WeakPtr<AttachmentUploaderImpl>& owner,
- ModelType model_type);
-
- ~UploadState() override;
-
- // Returns true if this object is stopped. Once stopped, this object is
- // effectively dead and can be destroyed.
- bool IsStopped() const;
-
- // Add |user_callback| to the list of callbacks to be invoked when this upload
- // completed.
- //
- // It is an error to call |AddUserCallback| on a stopped UploadState (see
- // |IsStopped|).
- void AddUserCallback(const UploadCallback& user_callback);
-
- // Return the Attachment this object is uploading.
- const Attachment& GetAttachment();
-
- // URLFetcher implementation.
- void OnURLFetchComplete(const net::URLFetcher* source) override;
-
- // OAuth2TokenService::Consumer.
- void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) override;
- void OnGetTokenFailure(const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) override;
-
- private:
- typedef std::vector<UploadCallback> UploadCallbackList;
-
- void GetToken();
-
- void StopAndReportResult(const UploadResult& result,
- const AttachmentId& attachment_id);
-
- bool is_stopped_;
- GURL upload_url_;
- const scoped_refptr<net::URLRequestContextGetter>&
- url_request_context_getter_;
- Attachment attachment_;
- UploadCallbackList user_callbacks_;
- std::unique_ptr<net::URLFetcher> fetcher_;
- std::string account_id_;
- OAuth2TokenService::ScopeSet scopes_;
- std::string access_token_;
- std::string raw_store_birthday_;
- OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider_;
- // Pointer to the AttachmentUploaderImpl that owns this object.
- base::WeakPtr<AttachmentUploaderImpl> owner_;
- std::unique_ptr<OAuth2TokenServiceRequest> access_token_request_;
- ModelType model_type_;
-
- DISALLOW_COPY_AND_ASSIGN(UploadState);
-};
-
-AttachmentUploaderImpl::UploadState::UploadState(
- const GURL& upload_url,
- const scoped_refptr<net::URLRequestContextGetter>&
- url_request_context_getter,
- const Attachment& attachment,
- const UploadCallback& user_callback,
- const std::string& account_id,
- const OAuth2TokenService::ScopeSet& scopes,
- OAuth2TokenServiceRequest::TokenServiceProvider* token_service_provider,
- const std::string& raw_store_birthday,
- const base::WeakPtr<AttachmentUploaderImpl>& owner,
- ModelType model_type)
- : OAuth2TokenService::Consumer("attachment-uploader-impl"),
- is_stopped_(false),
- upload_url_(upload_url),
- url_request_context_getter_(url_request_context_getter),
- attachment_(attachment),
- user_callbacks_(1, user_callback),
- account_id_(account_id),
- scopes_(scopes),
- raw_store_birthday_(raw_store_birthday),
- token_service_provider_(token_service_provider),
- owner_(owner),
- model_type_(model_type) {
- DCHECK(upload_url_.is_valid());
- DCHECK(url_request_context_getter_.get());
- DCHECK(!account_id_.empty());
- DCHECK(!scopes_.empty());
- DCHECK(token_service_provider_);
- DCHECK(!raw_store_birthday_.empty());
- GetToken();
-}
-
-AttachmentUploaderImpl::UploadState::~UploadState() {
-}
-
-bool AttachmentUploaderImpl::UploadState::IsStopped() const {
- DCHECK(CalledOnValidThread());
- return is_stopped_;
-}
-
-void AttachmentUploaderImpl::UploadState::AddUserCallback(
- const UploadCallback& user_callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(!is_stopped_);
- user_callbacks_.push_back(user_callback);
-}
-
-const Attachment& AttachmentUploaderImpl::UploadState::GetAttachment() {
- DCHECK(CalledOnValidThread());
- return attachment_;
-}
-
-void AttachmentUploaderImpl::UploadState::OnURLFetchComplete(
- const net::URLFetcher* source) {
- DCHECK(CalledOnValidThread());
- if (is_stopped_) {
- return;
- }
-
- UploadResult result = UPLOAD_TRANSIENT_ERROR;
- AttachmentId attachment_id = attachment_.GetId();
- net::URLRequestStatus status = source->GetStatus();
- const int response_code = source->GetResponseCode();
- UMA_HISTOGRAM_SPARSE_SLOWLY("Sync.Attachments.UploadResponseCode",
- status.is_success() ? response_code : status.error());
- if (response_code == net::HTTP_OK) {
- result = UPLOAD_SUCCESS;
- } else if (response_code == net::HTTP_UNAUTHORIZED) {
- // Server tells us we've got a bad token so invalidate it.
- OAuth2TokenServiceRequest::InvalidateToken(
- token_service_provider_, account_id_, scopes_, access_token_);
- // Fail the request, but indicate that it may be successful if retried.
- result = UPLOAD_TRANSIENT_ERROR;
- } else if (response_code == net::HTTP_FORBIDDEN) {
- // User is not allowed to use attachments. Retrying won't help.
- result = UPLOAD_UNSPECIFIED_ERROR;
- } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) {
- result = UPLOAD_TRANSIENT_ERROR;
- }
- StopAndReportResult(result, attachment_id);
-}
-
-void AttachmentUploaderImpl::UploadState::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) {
- DCHECK(CalledOnValidThread());
- if (is_stopped_) {
- return;
- }
-
- DCHECK_EQ(access_token_request_.get(), request);
- access_token_request_.reset();
- access_token_ = access_token;
- fetcher_ = net::URLFetcher::Create(upload_url_, net::URLFetcher::POST, this);
- ConfigureURLFetcherCommon(fetcher_.get(), access_token_, raw_store_birthday_,
- model_type_, url_request_context_getter_.get());
-
- const uint32_t crc32c = attachment_.GetCrc32c();
- fetcher_->AddExtraRequestHeader(base::StringPrintf(
- "X-Goog-Hash: crc32c=%s", FormatCrc32cHash(crc32c).c_str()));
-
- // TODO(maniscalco): Is there a better way? Copying the attachment data into
- // a string feels wrong given how large attachments may be (several MBs). If
- // we may end up switching from URLFetcher to URLRequest, this copy won't be
- // necessary.
- scoped_refptr<base::RefCountedMemory> memory = attachment_.GetData();
- const std::string upload_content(memory->front_as<char>(), memory->size());
- fetcher_->SetUploadData(kContentType, upload_content);
-
- fetcher_->Start();
-}
-
-void AttachmentUploaderImpl::UploadState::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) {
- DCHECK(CalledOnValidThread());
- if (is_stopped_) {
- return;
- }
-
- DCHECK_EQ(access_token_request_.get(), request);
- access_token_request_.reset();
- // TODO(maniscalco): We treat this as a transient error, but it may in fact be
- // a very long lived error and require user action. Consider differentiating
- // between the causes of GetToken failure and act accordingly. Think about
- // the causes of GetToken failure. Are there (bug 412802).
- StopAndReportResult(UPLOAD_TRANSIENT_ERROR, attachment_.GetId());
-}
-
-void AttachmentUploaderImpl::UploadState::GetToken() {
- access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart(
- token_service_provider_, account_id_, scopes_, this);
-}
-
-void AttachmentUploaderImpl::UploadState::StopAndReportResult(
- const UploadResult& result,
- const AttachmentId& attachment_id) {
- DCHECK(!is_stopped_);
- is_stopped_ = true;
- UploadCallbackList::const_iterator iter = user_callbacks_.begin();
- UploadCallbackList::const_iterator end = user_callbacks_.end();
- for (; iter != end; ++iter) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(*iter, result, attachment_id));
- }
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(&AttachmentUploaderImpl::OnUploadStateStopped,
- owner_, attachment_id.GetProto().unique_id()));
-}
-
-AttachmentUploaderImpl::AttachmentUploaderImpl(
- const GURL& sync_service_url,
- const scoped_refptr<net::URLRequestContextGetter>&
- url_request_context_getter,
- const std::string& account_id,
- const OAuth2TokenService::ScopeSet& scopes,
- const scoped_refptr<OAuth2TokenServiceRequest::TokenServiceProvider>&
- token_service_provider,
- const std::string& store_birthday,
- ModelType model_type)
- : sync_service_url_(sync_service_url),
- url_request_context_getter_(url_request_context_getter),
- account_id_(account_id),
- scopes_(scopes),
- token_service_provider_(token_service_provider),
- raw_store_birthday_(store_birthday),
- model_type_(model_type),
- weak_ptr_factory_(this) {
- DCHECK(CalledOnValidThread());
- DCHECK(!account_id.empty());
- DCHECK(!scopes.empty());
- DCHECK(token_service_provider_.get());
- DCHECK(!raw_store_birthday_.empty());
-}
-
-AttachmentUploaderImpl::~AttachmentUploaderImpl() {
- DCHECK(CalledOnValidThread());
-}
-
-void AttachmentUploaderImpl::UploadAttachment(const Attachment& attachment,
- const UploadCallback& callback) {
- DCHECK(CalledOnValidThread());
- const AttachmentId attachment_id = attachment.GetId();
- const std::string unique_id = attachment_id.GetProto().unique_id();
- DCHECK(!unique_id.empty());
- StateMap::iterator iter = state_map_.find(unique_id);
- if (iter != state_map_.end()) {
- // We have an old upload request for this attachment...
- if (!iter->second->IsStopped()) {
- // "join" to it.
- DCHECK(attachment.GetData()
- ->Equals(iter->second->GetAttachment().GetData()));
- iter->second->AddUserCallback(callback);
- return;
- } else {
- // It's stopped so we can't use it. Delete it.
- state_map_.erase(iter);
- }
- }
-
- const GURL url = GetURLForAttachmentId(sync_service_url_, attachment_id);
- std::unique_ptr<UploadState> upload_state(new UploadState(
- url, url_request_context_getter_, attachment, callback, account_id_,
- scopes_, token_service_provider_.get(), raw_store_birthday_,
- weak_ptr_factory_.GetWeakPtr(), model_type_));
- state_map_[unique_id] = std::move(upload_state);
-}
-
-// Static.
-GURL AttachmentUploaderImpl::GetURLForAttachmentId(
- const GURL& sync_service_url,
- const AttachmentId& attachment_id) {
- std::string path = sync_service_url.path();
- if (path.empty() || *path.rbegin() != '/') {
- path += '/';
- }
- path += kAttachments;
- path += attachment_id.GetProto().unique_id();
- GURL::Replacements replacements;
- replacements.SetPathStr(path);
- return sync_service_url.ReplaceComponents(replacements);
-}
-
-void AttachmentUploaderImpl::OnUploadStateStopped(const UniqueId& unique_id) {
- StateMap::iterator iter = state_map_.find(unique_id);
- // Only erase if stopped. Because this method is called asynchronously, it's
- // possible that a new request for this same id arrived after the UploadState
- // stopped, but before this method was invoked. In that case the UploadState
- // in the map might be a new one.
- if (iter != state_map_.end() && iter->second->IsStopped()) {
- state_map_.erase(iter);
- }
-}
-
-std::string AttachmentUploaderImpl::FormatCrc32cHash(uint32_t crc32c) {
- const uint32_t crc32c_big_endian = base::HostToNet32(crc32c);
- const base::StringPiece raw(reinterpret_cast<const char*>(&crc32c_big_endian),
- sizeof(crc32c_big_endian));
- std::string encoded;
- base::Base64Encode(raw, &encoded);
- return encoded;
-}
-
-void AttachmentUploaderImpl::ConfigureURLFetcherCommon(
- net::URLFetcher* fetcher,
- const std::string& access_token,
- const std::string& raw_store_birthday,
- ModelType model_type,
- net::URLRequestContextGetter* request_context_getter) {
- DCHECK(request_context_getter);
- DCHECK(fetcher);
- fetcher->SetAutomaticallyRetryOn5xx(false);
- fetcher->SetRequestContext(request_context_getter);
- fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES |
- net::LOAD_DO_NOT_SEND_COOKIES |
- net::LOAD_DISABLE_CACHE);
- fetcher->AddExtraRequestHeader(base::StringPrintf(
- "%s: Bearer %s", net::HttpRequestHeaders::kAuthorization,
- access_token.c_str()));
- // Encode the birthday. Birthday is opaque so we assume it could contain
- // anything. Encode it so that it's safe to pass as an HTTP header value.
- std::string encoded_store_birthday;
- base::Base64UrlEncode(
- raw_store_birthday, base::Base64UrlEncodePolicy::OMIT_PADDING,
- &encoded_store_birthday);
- fetcher->AddExtraRequestHeader(base::StringPrintf(
- "%s: %s", kSyncStoreBirthday, encoded_store_birthday.c_str()));
-
- // Use field number to pass ModelType because it's stable and we have server
- // code to decode it.
- const int field_number = GetSpecificsFieldNumberFromModelType(model_type);
- fetcher->AddExtraRequestHeader(
- base::StringPrintf("%s: %d", kSyncDataTypeId, field_number));
-}
-
-} // namespace syncer

Powered by Google App Engine
This is Rietveld 408576698