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

Unified Diff: sync/internal_api/attachments/attachment_downloader_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_downloader_impl.cc
diff --git a/sync/internal_api/attachments/attachment_downloader_impl.cc b/sync/internal_api/attachments/attachment_downloader_impl.cc
deleted file mode 100644
index f0443c1082c8176137176187d0395e6f21b8571b..0000000000000000000000000000000000000000
--- a/sync/internal_api/attachments/attachment_downloader_impl.cc
+++ /dev/null
@@ -1,296 +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_downloader_impl.h"
-
-#include <stdint.h>
-#include <utility>
-
-#include "base/base64.h"
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/single_thread_task_runner.h"
-#include "base/sys_byteorder.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "net/base/load_flags.h"
-#include "net/http/http_response_headers.h"
-#include "net/http/http_status_code.h"
-#include "net/http/http_util.h"
-#include "net/url_request/url_fetcher.h"
-#include "net/url_request/url_request_status.h"
-#include "sync/internal_api/public/attachments/attachment_uploader_impl.h"
-#include "sync/internal_api/public/attachments/attachment_util.h"
-#include "sync/protocol/sync.pb.h"
-#include "url/gurl.h"
-
-namespace syncer {
-
-struct AttachmentDownloaderImpl::DownloadState {
- public:
- DownloadState(const AttachmentId& attachment_id,
- const AttachmentUrl& attachment_url);
-
- AttachmentId attachment_id;
- AttachmentUrl attachment_url;
- // |access_token| needed to invalidate if downloading attachment fails with
- // HTTP_UNAUTHORIZED.
- std::string access_token;
- std::unique_ptr<net::URLFetcher> url_fetcher;
- std::vector<DownloadCallback> user_callbacks;
- base::TimeTicks start_time;
-};
-
-AttachmentDownloaderImpl::DownloadState::DownloadState(
- const AttachmentId& attachment_id,
- const AttachmentUrl& attachment_url)
- : attachment_id(attachment_id), attachment_url(attachment_url) {
-}
-
-AttachmentDownloaderImpl::AttachmentDownloaderImpl(
- 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)
- : OAuth2TokenService::Consumer("attachment-downloader-impl"),
- sync_service_url_(sync_service_url),
- url_request_context_getter_(url_request_context_getter),
- account_id_(account_id),
- oauth2_scopes_(scopes),
- token_service_provider_(token_service_provider),
- raw_store_birthday_(store_birthday),
- model_type_(model_type) {
- DCHECK(url_request_context_getter_.get());
- DCHECK(!account_id.empty());
- DCHECK(!scopes.empty());
- DCHECK(token_service_provider_.get());
- DCHECK(!raw_store_birthday_.empty());
-}
-
-AttachmentDownloaderImpl::~AttachmentDownloaderImpl() {
-}
-
-void AttachmentDownloaderImpl::DownloadAttachment(
- const AttachmentId& attachment_id,
- const DownloadCallback& callback) {
- DCHECK(CalledOnValidThread());
-
- AttachmentUrl url = AttachmentUploaderImpl::GetURLForAttachmentId(
- sync_service_url_, attachment_id).spec();
-
- StateMap::iterator iter = state_map_.find(url);
- DownloadState* download_state =
- iter != state_map_.end() ? iter->second.get() : nullptr;
- if (!download_state) {
- // There is no request started for this attachment id. Let's create
- // DownloadState and request access token for it.
- std::unique_ptr<DownloadState> new_download_state(
- new DownloadState(attachment_id, url));
- download_state = new_download_state.get();
- state_map_[url] = std::move(new_download_state);
- RequestAccessToken(download_state);
- }
- DCHECK(download_state->attachment_id == attachment_id);
- download_state->user_callbacks.push_back(callback);
-}
-
-void AttachmentDownloaderImpl::OnGetTokenSuccess(
- const OAuth2TokenService::Request* request,
- const std::string& access_token,
- const base::Time& expiration_time) {
- DCHECK(CalledOnValidThread());
- DCHECK(request == access_token_request_.get());
- access_token_request_.reset();
- StateList::const_iterator iter;
- // Start downloads for all download requests waiting for access token.
- for (iter = requests_waiting_for_access_token_.begin();
- iter != requests_waiting_for_access_token_.end();
- ++iter) {
- DownloadState* download_state = *iter;
- download_state->access_token = access_token;
- download_state->url_fetcher =
- CreateFetcher(download_state->attachment_url, access_token);
- download_state->start_time = base::TimeTicks::Now();
- download_state->url_fetcher->Start();
- }
- requests_waiting_for_access_token_.clear();
-}
-
-void AttachmentDownloaderImpl::OnGetTokenFailure(
- const OAuth2TokenService::Request* request,
- const GoogleServiceAuthError& error) {
- DCHECK(CalledOnValidThread());
- DCHECK(request == access_token_request_.get());
- access_token_request_.reset();
- StateList::const_iterator iter;
- // Without access token all downloads fail.
- for (iter = requests_waiting_for_access_token_.begin();
- iter != requests_waiting_for_access_token_.end();
- ++iter) {
- DownloadState* download_state = *iter;
- scoped_refptr<base::RefCountedString> null_attachment_data;
- ReportResult(*download_state, DOWNLOAD_TRANSIENT_ERROR,
- null_attachment_data);
- // Don't delete using the URL directly to avoid an access after free error
- // due to std::unordered_map's implementation. See crbug.com/603275.
- auto erase_iter = state_map_.find(download_state->attachment_url);
- DCHECK(erase_iter != state_map_.end());
- state_map_.erase(erase_iter);
- }
- requests_waiting_for_access_token_.clear();
-}
-
-void AttachmentDownloaderImpl::OnURLFetchComplete(
- const net::URLFetcher* source) {
- DCHECK(CalledOnValidThread());
-
- // Find DownloadState by url.
- AttachmentUrl url = source->GetOriginalURL().spec();
- StateMap::iterator iter = state_map_.find(url);
- DCHECK(iter != state_map_.end());
- const DownloadState& download_state = *iter->second;
- DCHECK(source == download_state.url_fetcher.get());
-
- DownloadResult result = DOWNLOAD_TRANSIENT_ERROR;
- scoped_refptr<base::RefCountedString> attachment_data;
- uint32_t attachment_crc32c = 0;
-
- net::URLRequestStatus status = source->GetStatus();
- const int response_code = source->GetResponseCode();
- UMA_HISTOGRAM_SPARSE_SLOWLY("Sync.Attachments.DownloadResponseCode",
- status.is_success() ? response_code : status.error());
- if (response_code == net::HTTP_OK) {
- std::string data_as_string;
- source->GetResponseAsString(&data_as_string);
- attachment_data = base::RefCountedString::TakeString(&data_as_string);
-
- UMA_HISTOGRAM_LONG_TIMES("Sync.Attachments.DownloadTotalTime",
- base::TimeTicks::Now() - download_state.start_time);
-
- attachment_crc32c = ComputeCrc32c(attachment_data);
- uint32_t crc32c_from_headers = 0;
- if (ExtractCrc32c(source->GetResponseHeaders(), &crc32c_from_headers) &&
- attachment_crc32c != crc32c_from_headers) {
- // Fail download only if there is useful crc32c in header and it doesn't
- // match data. All other cases are fine. When crc32c is not in headers
- // locally calculated one will be stored and used for further checks.
- result = DOWNLOAD_TRANSIENT_ERROR;
- } else {
- // If the id's crc32c doesn't match that of the downloaded attachment,
- // then we're stuck and retrying is unlikely to help.
- if (attachment_crc32c != download_state.attachment_id.GetCrc32c()) {
- result = DOWNLOAD_UNSPECIFIED_ERROR;
- } else {
- result = DOWNLOAD_SUCCESS;
- }
- }
- UMA_HISTOGRAM_BOOLEAN("Sync.Attachments.DownloadChecksumResult",
- result == DOWNLOAD_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_.get(),
- account_id_,
- oauth2_scopes_,
- download_state.access_token);
- // Fail the request, but indicate that it may be successful if retried.
- result = DOWNLOAD_TRANSIENT_ERROR;
- } else if (response_code == net::HTTP_FORBIDDEN) {
- // User is not allowed to use attachments. Retrying won't help.
- result = DOWNLOAD_UNSPECIFIED_ERROR;
- } else if (response_code == net::URLFetcher::RESPONSE_CODE_INVALID) {
- result = DOWNLOAD_TRANSIENT_ERROR;
- }
- ReportResult(download_state, result, attachment_data);
- state_map_.erase(iter);
-}
-
-std::unique_ptr<net::URLFetcher> AttachmentDownloaderImpl::CreateFetcher(
- const AttachmentUrl& url,
- const std::string& access_token) {
- std::unique_ptr<net::URLFetcher> url_fetcher =
- net::URLFetcher::Create(GURL(url), net::URLFetcher::GET, this);
- AttachmentUploaderImpl::ConfigureURLFetcherCommon(
- url_fetcher.get(), access_token, raw_store_birthday_, model_type_,
- url_request_context_getter_.get());
- return url_fetcher;
-}
-
-void AttachmentDownloaderImpl::RequestAccessToken(
- DownloadState* download_state) {
- requests_waiting_for_access_token_.push_back(download_state);
- // Start access token request if there is no active one.
- if (access_token_request_ == NULL) {
- access_token_request_ = OAuth2TokenServiceRequest::CreateAndStart(
- token_service_provider_.get(), account_id_, oauth2_scopes_, this);
- }
-}
-
-void AttachmentDownloaderImpl::ReportResult(
- const DownloadState& download_state,
- const DownloadResult& result,
- const scoped_refptr<base::RefCountedString>& attachment_data) {
- std::vector<DownloadCallback>::const_iterator iter;
- for (iter = download_state.user_callbacks.begin();
- iter != download_state.user_callbacks.end();
- ++iter) {
- std::unique_ptr<Attachment> attachment;
- if (result == DOWNLOAD_SUCCESS) {
- attachment.reset(new Attachment(Attachment::CreateFromParts(
- download_state.attachment_id, attachment_data)));
- }
-
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::Bind(*iter, result, base::Passed(&attachment)));
- }
-}
-
-bool AttachmentDownloaderImpl::ExtractCrc32c(
- const net::HttpResponseHeaders* headers,
- uint32_t* crc32c) {
- DCHECK(crc32c);
- if (!headers) {
- return false;
- }
-
- std::string crc32c_encoded;
- std::string header_value;
- size_t iter = 0;
- // Iterate over all matching headers.
- while (headers->EnumerateHeader(&iter, "x-goog-hash", &header_value)) {
- // Because EnumerateHeader is smart about list values, header_value will
- // either be empty or a single name=value pair.
- net::HttpUtil::NameValuePairsIterator pair_iter(
- header_value.begin(), header_value.end(), ',');
- if (pair_iter.GetNext()) {
- if (pair_iter.name() == "crc32c") {
- crc32c_encoded = pair_iter.value();
- DCHECK(!pair_iter.GetNext());
- break;
- }
- }
- }
- // Check if header was found
- if (crc32c_encoded.empty())
- return false;
- std::string crc32c_raw;
- if (!base::Base64Decode(crc32c_encoded, &crc32c_raw))
- return false;
-
- if (crc32c_raw.size() != sizeof(*crc32c))
- return false;
-
- *crc32c =
- base::NetToHost32(*reinterpret_cast<const uint32_t*>(crc32c_raw.c_str()));
- return true;
-}
-
-} // namespace syncer

Powered by Google App Engine
This is Rietveld 408576698