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

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: Address peter's review comments 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 : report_sender_(base::MakeUnique<net::ReportSender>(
47 request_context,
48 net::ReportSender::CookiesPreference::DO_NOT_SEND_COOKIES)) {
49 DCHECK_CURRENTLY_ON(BrowserThread::IO);
50 }
51
52 NotificationImageReporter::~NotificationImageReporter() {
53 // Thread on which this is destroyed may vary.
54 }
55
56 void NotificationImageReporter::ReportNotificationImageOnUI(
57 Profile* profile,
58 const GURL& origin,
59 const SkBitmap& image) {
60 DCHECK_CURRENTLY_ON(BrowserThread::UI);
61 DCHECK_EQ(origin, origin.GetOrigin());
Nathan Parker 2017/01/11 22:34:38 How about DCHECK(origin.is_valid()) as well
johnme 2017/01/13 02:38:16 Done.
62
63 // Skip reporting unless SBER2 Scout is enabled.
64 switch (GetExtendedReportingLevel(*profile->GetPrefs())) {
65 case SBER_LEVEL_OFF:
66 case SBER_LEVEL_LEGACY:
67 return;
68 case SBER_LEVEL_SCOUT:
69 break;
70 }
71
72 // Sample a Finch-controlled fraction only.
Nathan Parker 2017/01/11 22:34:38 I'd suggest adding this now, so we have a kill swi
johnme 2017/01/13 02:38:16 Makes sense, especially since the server isn't yet
73 double report_chance = 0.2; // TODO(johnme): Get this from Finch.
74 if (base::RandDouble() >= report_chance)
75 return;
76
77 BrowserThread::PostTask(
78 BrowserThread::IO, FROM_HERE,
79 base::Bind(&NotificationImageReporter::ReportNotificationImageOnIO, this,
80 make_scoped_refptr(g_browser_process->safe_browsing_service()),
81 origin, image));
Nathan Parker 2017/01/11 22:34:38 Does the image get copied here?
johnme 2017/01/13 02:38:16 No, SkBitmaps have an internal thread safe refcoun
82 }
83
84 void NotificationImageReporter::ReportNotificationImageOnIO(
85 scoped_refptr<SafeBrowsingService> safe_browsing_service,
86 const GURL& origin,
87 const SkBitmap& image) {
88 DCHECK_CURRENTLY_ON(BrowserThread::IO);
89
90 // Skip whitelisted origins to cut down on report volume.
91 if (!safe_browsing_service || !safe_browsing_service->database_manager() ||
92 safe_browsing_service->database_manager()->MatchCsdWhitelistUrl(origin)) {
93 return;
94 }
95
96 // Avoid exceeding kMaxReportsPerDay.
97 base::Time a_day_ago = base::Time::Now() - base::TimeDelta::FromDays(1);
98 while (!report_times_.empty() &&
99 report_times_.front() < /* older than */ a_day_ago) {
100 report_times_.pop();
101 }
102 if (report_times_.size() >= kMaxReportsPerDay)
103 return;
104 report_times_.push(base::Time::Now());
105
106 BrowserThread::GetBlockingPool()->PostWorkerTask(
107 FROM_HERE,
108 base::Bind(
109 &NotificationImageReporter::DownscaleNotificationImageOnBlockingPool,
110 this, origin, image));
111 }
112
113 void NotificationImageReporter::DownscaleNotificationImageOnBlockingPool(
114 const GURL& origin,
115 const SkBitmap& image) {
116 DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());
117
118 // Downscale to fit within 512x512. TODO(johnme): Get this from Finch.
119 const double MAX_SIZE = 512;
120 double scale = std::min(MAX_SIZE / image.width(), MAX_SIZE / image.height());
121 SkBitmap downscaled_image =
122 scale >= 1.0 ? image // already small enough
123 : skia::ImageOperations::Resize(
124 image, skia::ImageOperations::RESIZE_GOOD,
125 std::lround(scale * image.width()),
126 std::lround(scale * image.height()));
127
128 // Encode as PNG.
129 std::vector<unsigned char> png_bytes;
130 if (!gfx::PNGCodec::EncodeBGRASkBitmap(downscaled_image, false, &png_bytes)) {
131 NOTREACHED();
132 return;
133 }
134
135 BrowserThread::PostTask(
136 BrowserThread::IO, FROM_HERE,
137 base::Bind(
138 &NotificationImageReporter::SendReportOnIO, this, origin,
139 base::RefCountedBytes::TakeVector(&png_bytes),
140 gfx::Size(image.width(), image.height()),
141 gfx::Size(downscaled_image.width(), downscaled_image.height())));
142 }
143
144 void NotificationImageReporter::SendReportOnIO(
145 const GURL& origin,
146 scoped_refptr<base::RefCountedMemory> png_data,
147 const gfx::Size& dimensions,
148 const gfx::Size& original_dimensions) {
149 DCHECK_CURRENTLY_ON(BrowserThread::IO);
150
151 NotificationImageReportRequest report;
152 report.set_notification_origin(origin.spec());
153 report.mutable_image()->set_png_data(png_data->front(), png_data->size());
154 report.mutable_image()->mutable_dimensions()->set_width(dimensions.width());
155 report.mutable_image()->mutable_dimensions()->set_height(dimensions.height());
156 if (dimensions != original_dimensions) {
157 report.mutable_image()->mutable_original_dimensions()->set_width(
158 original_dimensions.width());
159 report.mutable_image()->mutable_original_dimensions()->set_height(
160 original_dimensions.height());
161 }
162
163 std::string serialized_report;
164 report.SerializeToString(&serialized_report);
165 report_sender_->Send(GURL(kReportingUploadUrl), "application/octet-stream",
166 serialized_report, base::Closure(),
167 base::Callback<void(const GURL&, int)>());
168 // TODO(johnme): Consider logging bandwidth and/or duration to UMA.
169 }
170
171 } // namespace safe_browsing
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698