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

Side by Side Diff: chrome/browser/safe_browsing/notification_image_reporter.cc

Issue 2624193004: Submit a sample of notification images to Safe Browsing (Closed)
Patch Set: Add basic success test Created 3 years, 11 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/safe_browsing/notification_image_reporter.h"
6
7 #include <cmath>
8 #include <vector>
9
10 #include "base/bind.h"
11 #include "base/logging.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/memory/ref_counted_memory.h"
14 #include "base/rand_util.h"
15 #include "base/threading/sequenced_worker_pool.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
19 #include "chrome/common/safe_browsing/csd.pb.h"
20 #include "components/safe_browsing_db/database_manager.h"
21 #include "components/safe_browsing_db/safe_browsing_prefs.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "net/url_request/report_sender.h"
24 #include "skia/ext/image_operations.h"
25 #include "third_party/skia/include/core/SkBitmap.h"
26 #include "ui/gfx/codec/png_codec.h"
27 #include "ui/gfx/geometry/size.h"
28 #include "url/gurl.h"
29
30 using content::BrowserThread;
31
32 namespace safe_browsing {
33
34 namespace {
35
36 const size_t kMaxReportsPerDay = 5;
37
38 const char kReportingUploadUrl[] =
39 "https://safebrowsing.googleusercontent.com/safebrowsing/clientreport/"
40 "chrome-notification-image"; // TODO(johnme): Confirm URL.
41
42 } // namespace
43
44 NotificationImageReporter::NotificationImageReporter(
45 net::URLRequestContext* request_context)
46 : NotificationImageReporter(base::MakeUnique<net::ReportSender>(
47 request_context,
48 net::ReportSender::CookiesPreference::DO_NOT_SEND_COOKIES)) {}
49
50 NotificationImageReporter::NotificationImageReporter(
51 std::unique_ptr<net::ReportSender> report_sender)
52 : report_sender_(std::move(report_sender)) {
53 DCHECK_CURRENTLY_ON(BrowserThread::IO);
54 }
55
56 NotificationImageReporter::~NotificationImageReporter() {
57 // Thread on which this is destroyed may vary.
58 }
59
60 void NotificationImageReporter::ReportNotificationImageOnUI(
61 Profile* profile,
62 const GURL& origin,
63 const SkBitmap& image) {
64 DCHECK_CURRENTLY_ON(BrowserThread::UI);
65 DCHECK_EQ(origin, origin.GetOrigin());
66
67 // Skip reporting unless SBER2 Scout is enabled.
68 switch (GetExtendedReportingLevel(*profile->GetPrefs())) {
69 case SBER_LEVEL_OFF:
70 case SBER_LEVEL_LEGACY:
71 return;
72 case SBER_LEVEL_SCOUT:
73 break;
74 }
75
76 // Sample a Finch-controlled fraction only.
77 double report_chance = GetReportChance();
78 if (base::RandDouble() >= report_chance)
79 return;
80
81 BrowserThread::PostTask(
82 BrowserThread::IO, FROM_HERE,
83 base::Bind(&NotificationImageReporter::ReportNotificationImageOnIO, this,
84 make_scoped_refptr(g_browser_process->safe_browsing_service()),
85 origin, image));
86 }
87
88 double NotificationImageReporter::GetReportChance() {
89 return 0.2; // TODO(johnme): Get this from Finch.
90 }
91
92 void NotificationImageReporter::ReportNotificationImageOnIO(
93 scoped_refptr<SafeBrowsingService> safe_browsing_service,
94 const GURL& origin,
95 const SkBitmap& image) {
96 DCHECK_CURRENTLY_ON(BrowserThread::IO);
97
98 // Skip whitelisted origins to cut down on report volume.
99 if (!safe_browsing_service || !safe_browsing_service->database_manager() ||
100 safe_browsing_service->database_manager()->MatchCsdWhitelistUrl(origin)) {
101 return;
102 }
103
104 // Avoid exceeding kMaxReportsPerDay.
105 base::Time a_day_ago = base::Time::Now() - base::TimeDelta::FromDays(1);
106 while (!report_times_.empty() &&
107 report_times_.front() < /* older than */ a_day_ago) {
108 report_times_.pop();
109 }
110 if (report_times_.size() >= kMaxReportsPerDay)
111 return;
112 report_times_.push(base::Time::Now());
113
114 BrowserThread::GetBlockingPool()->PostWorkerTask(
115 FROM_HERE,
116 base::Bind(
117 &NotificationImageReporter::DownscaleNotificationImageOnBlockingPool,
118 this, origin, image));
119 }
120
121 void NotificationImageReporter::DownscaleNotificationImageOnBlockingPool(
122 const GURL& origin,
123 const SkBitmap& image) {
124 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
125
126 // Downscale to fit within 512x512. TODO(johnme): Get this from Finch.
127 const double MAX_SIZE = 512;
128 double scale = std::min(MAX_SIZE / image.width(), MAX_SIZE / image.height());
129 SkBitmap downscaled_image =
130 scale >= 1.0 ? image // already small enough
131 : skia::ImageOperations::Resize(
132 image, skia::ImageOperations::RESIZE_GOOD,
133 std::lround(scale * image.width()),
134 std::lround(scale * image.height()));
135
136 // Encode as PNG.
137 std::vector<unsigned char> png_bytes;
138 if (!gfx::PNGCodec::EncodeBGRASkBitmap(downscaled_image, false, &png_bytes)) {
139 NOTREACHED();
140 return;
141 }
142
143 BrowserThread::PostTask(
144 BrowserThread::IO, FROM_HERE,
145 base::Bind(&NotificationImageReporter::SendReportOnIO, this, origin,
146 base::RefCountedBytes::TakeVector(&png_bytes),
147 gfx::Size(downscaled_image.width(), downscaled_image.height()),
148 gfx::Size(image.width(), image.height())));
149 }
150
151 void NotificationImageReporter::SendReportOnIO(
152 const GURL& origin,
153 scoped_refptr<base::RefCountedMemory> png_data,
154 const gfx::Size& dimensions,
155 const gfx::Size& original_dimensions) {
156 DCHECK_CURRENTLY_ON(BrowserThread::IO);
157
158 NotificationImageReportRequest report;
159 report.set_notification_origin(origin.spec());
160 report.mutable_image()->set_png_data(png_data->front(), png_data->size());
161 report.mutable_image()->mutable_dimensions()->set_width(dimensions.width());
162 report.mutable_image()->mutable_dimensions()->set_height(dimensions.height());
163 if (dimensions != original_dimensions) {
164 report.mutable_image()->mutable_original_dimensions()->set_width(
165 original_dimensions.width());
166 report.mutable_image()->mutable_original_dimensions()->set_height(
167 original_dimensions.height());
168 }
169
170 std::string serialized_report;
171 report.SerializeToString(&serialized_report);
172 report_sender_->Send(GURL(kReportingUploadUrl), "application/octet-stream",
173 serialized_report, base::Closure(),
174 base::Callback<void(const GURL&, int)>());
175 // TODO(johnme): Consider logging bandwidth and/or duration to UMA.
176 }
177
178 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698