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

Unified Diff: chrome/browser/safe_browsing/download_feedback.cc

Issue 15881012: Implement safebrowsing download feedback service, enabled for dev & canary only. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 6 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: chrome/browser/safe_browsing/download_feedback.cc
diff --git a/chrome/browser/safe_browsing/download_feedback.cc b/chrome/browser/safe_browsing/download_feedback.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fef426ad7aeb686670e087af2e9812f79a2ac217
--- /dev/null
+++ b/chrome/browser/safe_browsing/download_feedback.cc
@@ -0,0 +1,226 @@
+// 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/download_feedback.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/files/file_util_proxy.h"
+#include "base/metrics/histogram.h"
+#include "base/task_runner.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/safe_browsing/csd.pb.h"
+#include "net/base/net_errors.h"
+
+namespace safe_browsing {
+
+namespace {
+
+// The default URL where browser sends download feedback requests.
+const char kSbDefaultFeedbackURL[] =
+ "https://safebrowsing.google.com/safebrowsing/uploads/chrome";
+
+// This enum is used by histograms. Do not change the ordering or remove items.
+enum UploadResultType {
+ UPLOAD_SUCCESS,
+ UPLOAD_CANCELLED,
+ UPLOAD_METADATA_NET_ERROR,
+ UPLOAD_METADATA_RESPONSE_ERROR,
+ UPLOAD_FILE_NET_ERROR,
+ UPLOAD_FILE_RESPONSE_ERROR,
+ UPLOAD_COMPLETE_RESPONSE_ERROR,
+ // Memory space for histograms is determined by the max.
+ // ALWAYS ADD NEW VALUES BEFORE THIS ONE.
+ UPLOAD_RESULT_MAX
+};
+
+// Handles the uploading of a single downloaded binary to the safebrowsing
+// download feedback service.
+class DownloadFeedbackImpl : public DownloadFeedback {
+ public:
+ DownloadFeedbackImpl(net::URLRequestContextGetter* request_context_getter,
+ base::TaskRunner* file_task_runner,
+ const base::FilePath& file_path,
+ const std::string& ping_request,
+ const std::string& ping_response);
+ virtual ~DownloadFeedbackImpl();
+
+ virtual void Start(const base::Closure& finish_callback) OVERRIDE;
+
+ virtual const std::string& GetPingRequestForTesting() const OVERRIDE {
+ return ping_request_;
+ }
+
+ virtual const std::string& GetPingResponseForTesting() const OVERRIDE {
+ return ping_response_;
+ }
+
+ private:
+ // Callback for TwoPhaseUploader completion. Relays the result to the
+ // |finish_callback|.
+ void FinishedUpload(base::Closure finish_callback,
+ TwoPhaseUploader::State state,
+ int net_error,
+ int response_code,
+ const std::string& response);
+
+ void RecordUploadResult(UploadResultType result);
+
+ scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
+ scoped_refptr<base::TaskRunner> file_task_runner_;
+ const base::FilePath file_path_;
+ int64 file_size_;
+
+ // The safebrowsing request and response of checking that this binary is
+ // unsafe.
+ std::string ping_request_;
+ std::string ping_response_;
+
+ scoped_ptr<TwoPhaseUploader> uploader_;
+
+ DISALLOW_COPY_AND_ASSIGN(DownloadFeedbackImpl);
+};
+
+DownloadFeedbackImpl::DownloadFeedbackImpl(
+ net::URLRequestContextGetter* request_context_getter,
+ base::TaskRunner* file_task_runner,
+ const base::FilePath& file_path,
+ const std::string& ping_request,
+ const std::string& ping_response)
+ : request_context_getter_(request_context_getter),
+ file_task_runner_(file_task_runner),
+ file_path_(file_path),
+ file_size_(-1),
+ ping_request_(ping_request),
+ ping_response_(ping_response) {
+ DVLOG(1) << "DownloadFeedback constructed " << this << " for "
+ << file_path.AsUTF8Unsafe();
+}
+
+DownloadFeedbackImpl::~DownloadFeedbackImpl() {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << "DownloadFeedback destructed " << this;
+
+ if (uploader_) {
+ RecordUploadResult(UPLOAD_CANCELLED);
+ // Destroy the uploader before attempting to delete the file.
+ uploader_.reset();
+ }
+
+ base::FileUtilProxy::Delete(file_task_runner_, file_path_, false,
+ base::FileUtilProxy::StatusCallback());
+}
+
+void DownloadFeedbackImpl::Start(const base::Closure& finish_callback) {
+ DCHECK(CalledOnValidThread());
+ DCHECK(!uploader_);
+
+ CommandLine* cmdline = CommandLine::ForCurrentProcess();
+
+ ClientDownloadReport report_metadata;
+
+ bool r = report_metadata.mutable_download_request()->ParseFromString(
+ ping_request_);
+ DCHECK(r);
+ r = report_metadata.mutable_download_response()->ParseFromString(
+ ping_response_);
+ DCHECK(r);
+ file_size_ = report_metadata.download_request().length();
+
+ GURL url = GURL(cmdline->HasSwitch(switches::kSbDownloadFeedbackURL) ?
+ cmdline->GetSwitchValueASCII(switches::kSbDownloadFeedbackURL) :
+ kSbDefaultFeedbackURL);
+
+ std::string metadata_string;
+ bool ok = report_metadata.SerializeToString(&metadata_string);
+ DCHECK(ok);
+ uploader_.reset(TwoPhaseUploader::Create(
+ request_context_getter_,
+ file_task_runner_,
+ url,
+ metadata_string,
+ file_path_,
+ TwoPhaseUploader::ProgressCallback(),
+ base::Bind(&DownloadFeedbackImpl::FinishedUpload, base::Unretained(this),
+ finish_callback)));
+ uploader_->Start();
+}
+
+void DownloadFeedbackImpl::FinishedUpload(base::Closure finish_callback,
+ TwoPhaseUploader::State state,
+ int net_error,
+ int response_code,
+ const std::string& response_data) {
+ DCHECK(CalledOnValidThread());
+ DVLOG(1) << __FUNCTION__ << " " << state << " rlen=" << response_data.size();
+
+ switch (state) {
+ case TwoPhaseUploader::STATE_SUCCESS: {
+ ClientUploadResponse response;
+ if (!response.ParseFromString(response_data) ||
+ response.status() != ClientUploadResponse::SUCCESS)
+ RecordUploadResult(UPLOAD_COMPLETE_RESPONSE_ERROR);
+ else
+ RecordUploadResult(UPLOAD_SUCCESS);
+ break;
+ }
+ case TwoPhaseUploader::UPLOAD_FILE:
+ if (net_error != net::OK)
+ RecordUploadResult(UPLOAD_FILE_NET_ERROR);
+ else
+ RecordUploadResult(UPLOAD_FILE_RESPONSE_ERROR);
+ break;
+ case TwoPhaseUploader::UPLOAD_METADATA:
+ if (net_error != net::OK)
+ RecordUploadResult(UPLOAD_METADATA_NET_ERROR);
+ else
+ RecordUploadResult(UPLOAD_METADATA_RESPONSE_ERROR);
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ uploader_.reset();
+
+ finish_callback.Run();
+ // We may be deleted here.
+}
+
+void DownloadFeedbackImpl::RecordUploadResult(UploadResultType result) {
+ if (result == UPLOAD_SUCCESS)
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "SBDownloadFeedback.SizeSuccess", file_size_, 1, kMaxUploadSize, 50);
+ else
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "SBDownloadFeedback.SizeFailure", file_size_, 1, kMaxUploadSize, 50);
+ UMA_HISTOGRAM_ENUMERATION(
+ "SBDownloadFeedback.UploadResult", result, UPLOAD_RESULT_MAX);
+}
+
+} // namespace
+
+// static
+const int64 DownloadFeedback::kMaxUploadSize = 50 * 1024 * 1024;
+
+// static
+DownloadFeedbackFactory* DownloadFeedback::factory_ = NULL;
+
+// static
+DownloadFeedback* DownloadFeedback::Create(
+ net::URLRequestContextGetter* request_context_getter,
+ base::TaskRunner* file_task_runner,
+ const base::FilePath& file_path,
+ const std::string& ping_request,
+ const std::string& ping_response) {
+ if (!DownloadFeedback::factory_)
+ return new DownloadFeedbackImpl(
+ request_context_getter, file_task_runner, file_path, ping_request,
+ ping_response);
+ return DownloadFeedback::factory_->CreateDownloadFeedback(
+ request_context_getter, file_task_runner, file_path, ping_request,
+ ping_response);
+}
+
+} // namespace safe_browsing
+

Powered by Google App Engine
This is Rietveld 408576698