summaryrefslogtreecommitdiffstats
path: root/chrome/browser/safe_browsing/two_phase_uploader.cc
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-08 13:41:53 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-03-08 13:41:53 +0000
commit344536698ac489239bac55640420c5375df1defe (patch)
tree8aee76a7afde6e7ffba3546a4ac895b5059f5385 /chrome/browser/safe_browsing/two_phase_uploader.cc
parent9b69c61ce91158ad35916fb817083c70bf8047d5 (diff)
downloadchromium_src-344536698ac489239bac55640420c5375df1defe.zip
chromium_src-344536698ac489239bac55640420c5375df1defe.tar.gz
chromium_src-344536698ac489239bac55640420c5375df1defe.tar.bz2
Implement two phase upload protocol handler class.
BUG=169557 Review URL: https://chromiumcodereview.appspot.com/12387058 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@186944 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/safe_browsing/two_phase_uploader.cc')
-rw-r--r--chrome/browser/safe_browsing/two_phase_uploader.cc146
1 files changed, 146 insertions, 0 deletions
diff --git a/chrome/browser/safe_browsing/two_phase_uploader.cc b/chrome/browser/safe_browsing/two_phase_uploader.cc
new file mode 100644
index 0000000..9b6165e
--- /dev/null
+++ b/chrome/browser/safe_browsing/two_phase_uploader.cc
@@ -0,0 +1,146 @@
+// Copyright 2013 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 "chrome/browser/safe_browsing/two_phase_uploader.h"
+
+#include "base/bind.h"
+#include "base/task_runner.h"
+#include "net/base/net_errors.h"
+#include "net/http/http_response_headers.h"
+#include "net/url_request/url_fetcher.h"
+#include "net/url_request/url_request_status.h"
+
+namespace {
+
+// Header sent on initial request to start the two phase upload process.
+const char* kStartHeader = "x-goog-resumable: start";
+
+// Header returned on initial response with URL to use for the second phase.
+const char* kLocationHeader = "Location";
+
+const char* kUploadContentType = "application/octet-stream";
+
+} // namespace
+
+TwoPhaseUploader::TwoPhaseUploader(
+ net::URLRequestContextGetter* url_request_context_getter,
+ base::TaskRunner* file_task_runner,
+ const GURL& base_url,
+ const std::string& metadata,
+ const base::FilePath& file_path,
+ const ProgressCallback& progress_callback,
+ const FinishCallback& finish_callback)
+ : state_(STATE_NONE),
+ url_request_context_getter_(url_request_context_getter),
+ file_task_runner_(file_task_runner),
+ base_url_(base_url),
+ metadata_(metadata),
+ file_path_(file_path),
+ progress_callback_(progress_callback),
+ finish_callback_(finish_callback) {
+}
+
+TwoPhaseUploader::~TwoPhaseUploader() {
+ DCHECK(CalledOnValidThread());
+}
+
+void TwoPhaseUploader::Start() {
+ DCHECK(CalledOnValidThread());
+ DCHECK_EQ(STATE_NONE, state_);
+
+ UploadMetadata();
+}
+
+void TwoPhaseUploader::OnURLFetchComplete(const net::URLFetcher* source) {
+ DCHECK(CalledOnValidThread());
+ net::URLRequestStatus status = source->GetStatus();
+ int response_code = source->GetResponseCode();
+
+ DVLOG(1) << __FUNCTION__ << " " << source->GetURL().spec()
+ << " " << status.status() << " " << response_code;
+
+ if (!status.is_success()) {
+ LOG(ERROR) << "URLFetcher failed, status=" << status.status()
+ << " err=" << status.error();
+ Finish(status.error(), response_code, "");
+ return;
+ }
+
+ std::string response;
+ source->GetResponseAsString(&response);
+
+ switch (state_) {
+ case UPLOAD_METADATA:
+ {
+ if (response_code != 201) {
+ LOG(ERROR) << "Invalid response to initial request: "
+ << response_code;
+ Finish(net::OK, response_code, response);
+ return;
+ }
+ std::string location;
+ if (!source->GetResponseHeaders()->EnumerateHeader(
+ NULL, kLocationHeader, &location)) {
+ LOG(ERROR) << "no location header";
+ Finish(net::OK, response_code, "");
+ return;
+ }
+ DVLOG(1) << "upload location: " << location;
+ upload_url_ = GURL(location);
+ UploadFile();
+ break;
+ }
+ case UPLOAD_FILE:
+ if (response_code != 200) {
+ LOG(ERROR) << "Invalid response to upload request: "
+ << response_code;
+ } else {
+ state_ = STATE_SUCCESS;
+ }
+ Finish(net::OK, response_code, response);
+ return;
+ default:
+ NOTREACHED();
+ };
+}
+
+void TwoPhaseUploader::OnURLFetchUploadProgress(const net::URLFetcher* source,
+ int64 current, int64 total) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(3) << __FUNCTION__ << " " << source->GetURL().spec()
+ << " " << current << "/" << total;
+ if (state_ == UPLOAD_FILE)
+ progress_callback_.Run(current, total);
+}
+
+void TwoPhaseUploader::UploadMetadata() {
+ DCHECK(CalledOnValidThread());
+ state_ = UPLOAD_METADATA;
+ url_fetcher_.reset(net::URLFetcher::Create(base_url_, net::URLFetcher::POST,
+ this));
+ url_fetcher_->SetRequestContext(url_request_context_getter_);
+ url_fetcher_->SetExtraRequestHeaders(kStartHeader);
+ url_fetcher_->SetUploadData(kUploadContentType, metadata_);
+ url_fetcher_->Start();
+}
+
+void TwoPhaseUploader::UploadFile() {
+ DCHECK(CalledOnValidThread());
+ state_ = UPLOAD_FILE;
+
+ url_fetcher_.reset(net::URLFetcher::Create(upload_url_, net::URLFetcher::PUT,
+ this));
+ url_fetcher_->SetRequestContext(url_request_context_getter_);
+ url_fetcher_->SetUploadFilePath(kUploadContentType,
+ file_path_,
+ file_task_runner_);
+ url_fetcher_->Start();
+}
+
+void TwoPhaseUploader::Finish(int net_error,
+ int response_code,
+ const std::string& response) {
+ DCHECK(CalledOnValidThread());
+ finish_callback_.Run(state_, net_error, response_code, response);
+}