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 "components/safe_browsing/content/web_ui/safe_browsing_ui.h"
6
7 #include <stddef.h>
8 #include <algorithm>
9 #include <memory>
10 #include <utility>
11 #include <vector>
12
13 #include "base/base64.h"
14 #include "base/base64url.h"
15 #include "base/bind.h"
16 #include "base/callback.h"
17 #include "base/i18n/time_formatting.h"
18 #include "base/json/json_string_value_serializer.h"
19 #include "base/memory/ref_counted.h"
20 #include "base/memory/singleton.h"
21 #include "base/stl_util.h"
22 #include "base/strings/string_number_conversions.h"
23 #include "base/strings/utf_string_conversions.h"
24 #include "base/task/post_task.h"
25 #include "base/time/time.h"
26 #include "base/values.h"
27 #include "components/grit/components_resources.h"
28 #include "components/grit/components_scaled_resources.h"
29 #include "components/password_manager/core/browser/hash_password_manager.h"
30 #include "components/safe_browsing/buildflags.h"
31 #include "components/safe_browsing/core/browser/referrer_chain_provider.h"
32 #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
33 #include "components/safe_browsing/core/features.h"
34 #include "components/safe_browsing/core/proto/csd.pb.h"
35 #if BUILDFLAG(FULL_SAFE_BROWSING)
36 #include "components/safe_browsing/core/proto/webprotect.pb.h"
37 #endif
38 #include "components/safe_browsing/core/realtime/policy_engine.h"
39 #include "components/safe_browsing/core/web_ui/constants.h"
40 #include "components/strings/grit/components_strings.h"
41 #include "components/user_prefs/user_prefs.h"
42 #include "content/public/browser/browser_context.h"
43 #include "content/public/browser/browser_task_traits.h"
44 #include "content/public/browser/browser_thread.h"
45 #include "content/public/browser/web_contents.h"
46
47 #if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
48 #include "components/safe_browsing/core/db/v4_local_database_manager.h"
49 #endif
50
51 using base::Time;
52 using sync_pb::GaiaPasswordReuse;
53 using PasswordCaptured = sync_pb::UserEventSpecifics::GaiaPasswordCaptured;
54 using PasswordReuseLookup = sync_pb::GaiaPasswordReuse::PasswordReuseLookup;
55 using PasswordReuseDetected = sync_pb::GaiaPasswordReuse::PasswordReuseDetected;
56 using PasswordReuseDialogInteraction =
57 sync_pb::GaiaPasswordReuse::PasswordReuseDialogInteraction;
58
59 namespace safe_browsing {
60 WebUIInfoSingleton::WebUIInfoSingleton() = default;
61
62 WebUIInfoSingleton::~WebUIInfoSingleton() = default;
63
64 // static
GetInstance()65 WebUIInfoSingleton* WebUIInfoSingleton::GetInstance() {
66 return base::Singleton<WebUIInfoSingleton>::get();
67 }
68
69 // static
HasListener()70 bool WebUIInfoSingleton::HasListener() {
71 return GetInstance()->has_test_listener_ ||
72 !GetInstance()->webui_instances_.empty();
73 }
74
AddToClientDownloadRequestsSent(std::unique_ptr<ClientDownloadRequest> client_download_request)75 void WebUIInfoSingleton::AddToClientDownloadRequestsSent(
76 std::unique_ptr<ClientDownloadRequest> client_download_request) {
77 if (!HasListener())
78 return;
79
80 for (auto* webui_listener : webui_instances_)
81 webui_listener->NotifyClientDownloadRequestJsListener(
82 client_download_request.get());
83 client_download_requests_sent_.push_back(std::move(client_download_request));
84 }
85
ClearClientDownloadRequestsSent()86 void WebUIInfoSingleton::ClearClientDownloadRequestsSent() {
87 std::vector<std::unique_ptr<ClientDownloadRequest>>().swap(
88 client_download_requests_sent_);
89 }
90
AddToClientDownloadResponsesReceived(std::unique_ptr<ClientDownloadResponse> client_download_response)91 void WebUIInfoSingleton::AddToClientDownloadResponsesReceived(
92 std::unique_ptr<ClientDownloadResponse> client_download_response) {
93 if (!HasListener())
94 return;
95
96 for (auto* webui_listener : webui_instances_)
97 webui_listener->NotifyClientDownloadResponseJsListener(
98 client_download_response.get());
99 client_download_responses_received_.push_back(
100 std::move(client_download_response));
101 }
102
ClearClientDownloadResponsesReceived()103 void WebUIInfoSingleton::ClearClientDownloadResponsesReceived() {
104 std::vector<std::unique_ptr<ClientDownloadResponse>>().swap(
105 client_download_responses_received_);
106 }
107
AddToCSBRRsSent(std::unique_ptr<ClientSafeBrowsingReportRequest> csbrr)108 void WebUIInfoSingleton::AddToCSBRRsSent(
109 std::unique_ptr<ClientSafeBrowsingReportRequest> csbrr) {
110 if (!HasListener())
111 return;
112
113 for (auto* webui_listener : webui_instances_)
114 webui_listener->NotifyCSBRRJsListener(csbrr.get());
115 csbrrs_sent_.push_back(std::move(csbrr));
116 }
117
ClearCSBRRsSent()118 void WebUIInfoSingleton::ClearCSBRRsSent() {
119 std::vector<std::unique_ptr<ClientSafeBrowsingReportRequest>>().swap(
120 csbrrs_sent_);
121 }
122
AddToPGEvents(const sync_pb::UserEventSpecifics & event)123 void WebUIInfoSingleton::AddToPGEvents(
124 const sync_pb::UserEventSpecifics& event) {
125 if (!HasListener())
126 return;
127
128 for (auto* webui_listener : webui_instances_)
129 webui_listener->NotifyPGEventJsListener(event);
130
131 pg_event_log_.push_back(event);
132 }
133
ClearPGEvents()134 void WebUIInfoSingleton::ClearPGEvents() {
135 std::vector<sync_pb::UserEventSpecifics>().swap(pg_event_log_);
136 }
137
AddToSecurityEvents(const sync_pb::GaiaPasswordReuse & event)138 void WebUIInfoSingleton::AddToSecurityEvents(
139 const sync_pb::GaiaPasswordReuse& event) {
140 if (!HasListener())
141 return;
142
143 for (auto* webui_listener : webui_instances_)
144 webui_listener->NotifySecurityEventJsListener(event);
145
146 security_event_log_.push_back(event);
147 }
148
ClearSecurityEvents()149 void WebUIInfoSingleton::ClearSecurityEvents() {
150 std::vector<sync_pb::GaiaPasswordReuse>().swap(security_event_log_);
151 }
152
AddToPGPings(const LoginReputationClientRequest & request)153 int WebUIInfoSingleton::AddToPGPings(
154 const LoginReputationClientRequest& request) {
155 if (!HasListener())
156 return -1;
157
158 for (auto* webui_listener : webui_instances_)
159 webui_listener->NotifyPGPingJsListener(pg_pings_.size(), request);
160
161 pg_pings_.push_back(request);
162
163 return pg_pings_.size() - 1;
164 }
165
AddToPGResponses(int token,const LoginReputationClientResponse & response)166 void WebUIInfoSingleton::AddToPGResponses(
167 int token,
168 const LoginReputationClientResponse& response) {
169 if (!HasListener())
170 return;
171
172 for (auto* webui_listener : webui_instances_)
173 webui_listener->NotifyPGResponseJsListener(token, response);
174
175 pg_responses_[token] = response;
176 }
177
ClearPGPings()178 void WebUIInfoSingleton::ClearPGPings() {
179 std::vector<LoginReputationClientRequest>().swap(pg_pings_);
180 std::map<int, LoginReputationClientResponse>().swap(pg_responses_);
181 }
182
AddToRTLookupPings(const RTLookupRequest request)183 int WebUIInfoSingleton::AddToRTLookupPings(const RTLookupRequest request) {
184 if (!HasListener())
185 return -1;
186
187 for (auto* webui_listener : webui_instances_)
188 webui_listener->NotifyRTLookupPingJsListener(rt_lookup_pings_.size(),
189 request);
190
191 rt_lookup_pings_.push_back(request);
192
193 return rt_lookup_pings_.size() - 1;
194 }
195
AddToRTLookupResponses(int token,const RTLookupResponse response)196 void WebUIInfoSingleton::AddToRTLookupResponses(
197 int token,
198 const RTLookupResponse response) {
199 if (!HasListener())
200 return;
201
202 for (auto* webui_listener : webui_instances_)
203 webui_listener->NotifyRTLookupResponseJsListener(token, response);
204
205 rt_lookup_responses_[token] = response;
206 }
207
ClearRTLookupPings()208 void WebUIInfoSingleton::ClearRTLookupPings() {
209 std::vector<RTLookupRequest>().swap(rt_lookup_pings_);
210 std::map<int, RTLookupResponse>().swap(rt_lookup_responses_);
211 }
212
LogMessage(const std::string & message)213 void WebUIInfoSingleton::LogMessage(const std::string& message) {
214 if (!HasListener())
215 return;
216
217 base::Time timestamp = base::Time::Now();
218 log_messages_.push_back(std::make_pair(timestamp, message));
219
220 base::PostTask(FROM_HERE, {content::BrowserThread::UI},
221 base::BindOnce(&WebUIInfoSingleton::NotifyLogMessageListeners,
222 timestamp, message));
223 }
224
ClearLogMessages()225 void WebUIInfoSingleton::ClearLogMessages() {
226 std::vector<std::pair<base::Time, std::string>>().swap(log_messages_);
227 }
228
NotifyLogMessageListeners(const base::Time & timestamp,const std::string & message)229 /* static */ void WebUIInfoSingleton::NotifyLogMessageListeners(
230 const base::Time& timestamp,
231 const std::string& message) {
232 WebUIInfoSingleton* web_ui_info = GetInstance();
233
234 for (auto* webui_listener : web_ui_info->webui_instances())
235 webui_listener->NotifyLogMessageJsListener(timestamp, message);
236 }
237
AddToReportingEvents(const base::Value & event)238 void WebUIInfoSingleton::AddToReportingEvents(const base::Value& event) {
239 if (!HasListener())
240 return;
241
242 for (auto* webui_listener : webui_instances_)
243 webui_listener->NotifyReportingEventJsListener(event);
244
245 reporting_events_.push_back(event.Clone());
246 }
247
ClearReportingEvents()248 void WebUIInfoSingleton::ClearReportingEvents() {
249 std::vector<base::Value>().swap(reporting_events_);
250 }
251
252 #if BUILDFLAG(FULL_SAFE_BROWSING)
AddToDeepScanRequests(const DeepScanningClientRequest & request)253 void WebUIInfoSingleton::AddToDeepScanRequests(
254 const DeepScanningClientRequest& request) {
255 if (!HasListener())
256 return;
257
258 if (deep_scan_requests_.find(request.request_token()) ==
259 deep_scan_requests_.end()) {
260 for (auto* webui_listener : webui_instances_)
261 webui_listener->NotifyDeepScanRequestJsListener(request);
262 }
263
264 deep_scan_requests_[request.request_token()] = request;
265 }
266
AddToDeepScanResponses(const std::string & token,const std::string & status,const DeepScanningClientResponse & response)267 void WebUIInfoSingleton::AddToDeepScanResponses(
268 const std::string& token,
269 const std::string& status,
270 const DeepScanningClientResponse& response) {
271 if (!HasListener())
272 return;
273
274 for (auto* webui_listener : webui_instances_)
275 webui_listener->NotifyDeepScanResponseJsListener(token, status, response);
276
277 deep_scan_responses_[token] = std::make_pair(status, response);
278 }
279
ClearDeepScans()280 void WebUIInfoSingleton::ClearDeepScans() {
281 DeepScanningRequestMap().swap(deep_scan_requests_);
282 StatusAndDeepScanningResponseMap().swap(deep_scan_responses_);
283 }
284 #endif
RegisterWebUIInstance(SafeBrowsingUIHandler * webui)285 void WebUIInfoSingleton::RegisterWebUIInstance(SafeBrowsingUIHandler* webui) {
286 webui_instances_.push_back(webui);
287 }
288
UnregisterWebUIInstance(SafeBrowsingUIHandler * webui)289 void WebUIInfoSingleton::UnregisterWebUIInstance(SafeBrowsingUIHandler* webui) {
290 base::Erase(webui_instances_, webui);
291 MaybeClearData();
292 }
293
GetCookieManager()294 network::mojom::CookieManager* WebUIInfoSingleton::GetCookieManager() {
295 if (!cookie_manager_remote_)
296 InitializeCookieManager();
297
298 return cookie_manager_remote_.get();
299 }
300
ClearListenerForTesting()301 void WebUIInfoSingleton::ClearListenerForTesting() {
302 has_test_listener_ = false;
303 MaybeClearData();
304 }
305
InitializeCookieManager()306 void WebUIInfoSingleton::InitializeCookieManager() {
307 DCHECK(network_context_);
308
309 // Reset |cookie_manager_remote_|, and only re-initialize it if we have a
310 // listening SafeBrowsingUIHandler.
311 cookie_manager_remote_.reset();
312
313 if (HasListener()) {
314 network_context_->GetNetworkContext()->GetCookieManager(
315 cookie_manager_remote_.BindNewPipeAndPassReceiver());
316
317 // base::Unretained is safe because |this| owns |cookie_manager_remote_|.
318 cookie_manager_remote_.set_disconnect_handler(base::BindOnce(
319 &WebUIInfoSingleton::InitializeCookieManager, base::Unretained(this)));
320 }
321 }
322
MaybeClearData()323 void WebUIInfoSingleton::MaybeClearData() {
324 if (!HasListener()) {
325 ClearCSBRRsSent();
326 ClearClientDownloadRequestsSent();
327 ClearClientDownloadResponsesReceived();
328 ClearPGEvents();
329 ClearPGPings();
330 ClearRTLookupPings();
331 ClearLogMessages();
332 ClearReportingEvents();
333
334 #if BUILDFLAG(FULL_SAFE_BROWSING)
335 ClearDeepScans();
336 #endif
337 }
338 }
339
340 namespace {
341 #if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
342
UserReadableTimeFromMillisSinceEpoch(int64_t time_in_milliseconds)343 base::Value UserReadableTimeFromMillisSinceEpoch(int64_t time_in_milliseconds) {
344 base::Time time = base::Time::UnixEpoch() +
345 base::TimeDelta::FromMilliseconds(time_in_milliseconds);
346 return base::Value(
347 base::UTF16ToASCII(base::TimeFormatShortDateAndTime(time)));
348 }
349
AddStoreInfo(const DatabaseManagerInfo::DatabaseInfo::StoreInfo store_info,base::ListValue * database_info_list)350 void AddStoreInfo(const DatabaseManagerInfo::DatabaseInfo::StoreInfo store_info,
351 base::ListValue* database_info_list) {
352 if (store_info.has_file_name()) {
353 database_info_list->Append(base::Value(store_info.file_name()));
354 } else {
355 database_info_list->Append(base::Value("Unknown store"));
356 }
357
358 std::string store_info_string = "<blockquote>";
359 if (store_info.has_file_size_bytes()) {
360 store_info_string +=
361 "Size (in bytes): " + std::to_string(store_info.file_size_bytes()) +
362 "<br>";
363 }
364
365 if (store_info.has_update_status()) {
366 store_info_string +=
367 "Update status: " + std::to_string(store_info.update_status()) + "<br>";
368 }
369
370 if (store_info.has_last_apply_update_time_millis()) {
371 store_info_string += "Last update time: " +
372 UserReadableTimeFromMillisSinceEpoch(
373 store_info.last_apply_update_time_millis())
374 .GetString() +
375 "<br>";
376 }
377
378 if (store_info.has_checks_attempted()) {
379 store_info_string += "Number of database checks: " +
380 std::to_string(store_info.checks_attempted()) + "<br>";
381 }
382
383 store_info_string += "</blockquote>";
384
385 database_info_list->Append(base::Value(store_info_string));
386 }
387
AddDatabaseInfo(const DatabaseManagerInfo::DatabaseInfo database_info,base::ListValue * database_info_list)388 void AddDatabaseInfo(const DatabaseManagerInfo::DatabaseInfo database_info,
389 base::ListValue* database_info_list) {
390 if (database_info.has_database_size_bytes()) {
391 database_info_list->Append(base::Value("Database size (in bytes)"));
392 database_info_list->Append(
393 base::Value(static_cast<double>(database_info.database_size_bytes())));
394 }
395
396 // Add the information specific to each store.
397 for (int i = 0; i < database_info.store_info_size(); i++) {
398 AddStoreInfo(database_info.store_info(i), database_info_list);
399 }
400 }
401
AddUpdateInfo(const DatabaseManagerInfo::UpdateInfo update_info,base::ListValue * database_info_list)402 void AddUpdateInfo(const DatabaseManagerInfo::UpdateInfo update_info,
403 base::ListValue* database_info_list) {
404 if (update_info.has_network_status_code()) {
405 // Network status of the last GetUpdate().
406 database_info_list->Append(base::Value("Last update network status code"));
407 database_info_list->Append(base::Value(update_info.network_status_code()));
408 }
409 if (update_info.has_last_update_time_millis()) {
410 database_info_list->Append(base::Value("Last update time"));
411 database_info_list->Append(UserReadableTimeFromMillisSinceEpoch(
412 update_info.last_update_time_millis()));
413 }
414 if (update_info.has_next_update_time_millis()) {
415 database_info_list->Append(base::Value("Next update time"));
416 database_info_list->Append(UserReadableTimeFromMillisSinceEpoch(
417 update_info.next_update_time_millis()));
418 }
419 }
420
ParseFullHashInfo(const FullHashCacheInfo::FullHashCache::CachedHashPrefixInfo::FullHashInfo full_hash_info,base::DictionaryValue * full_hash_info_dict)421 void ParseFullHashInfo(
422 const FullHashCacheInfo::FullHashCache::CachedHashPrefixInfo::FullHashInfo
423 full_hash_info,
424 base::DictionaryValue* full_hash_info_dict) {
425 if (full_hash_info.has_positive_expiry()) {
426 full_hash_info_dict->SetString(
427 "Positive expiry",
428 UserReadableTimeFromMillisSinceEpoch(full_hash_info.positive_expiry())
429 .GetString());
430 }
431 if (full_hash_info.has_full_hash()) {
432 std::string full_hash;
433 base::Base64UrlEncode(full_hash_info.full_hash(),
434 base::Base64UrlEncodePolicy::INCLUDE_PADDING,
435 &full_hash);
436 full_hash_info_dict->SetString("Full hash (base64)", full_hash);
437 }
438 if (full_hash_info.list_identifier().has_platform_type()) {
439 full_hash_info_dict->SetInteger(
440 "platform_type", full_hash_info.list_identifier().platform_type());
441 }
442 if (full_hash_info.list_identifier().has_threat_entry_type()) {
443 full_hash_info_dict->SetInteger(
444 "threat_entry_type",
445 full_hash_info.list_identifier().threat_entry_type());
446 }
447 if (full_hash_info.list_identifier().has_threat_type()) {
448 full_hash_info_dict->SetInteger(
449 "threat_type", full_hash_info.list_identifier().threat_type());
450 }
451 }
452
ParseFullHashCache(const FullHashCacheInfo::FullHashCache full_hash_cache,base::ListValue * full_hash_cache_list)453 void ParseFullHashCache(const FullHashCacheInfo::FullHashCache full_hash_cache,
454 base::ListValue* full_hash_cache_list) {
455 base::DictionaryValue full_hash_cache_parsed;
456
457 if (full_hash_cache.has_hash_prefix()) {
458 std::string hash_prefix;
459 base::Base64UrlEncode(full_hash_cache.hash_prefix(),
460 base::Base64UrlEncodePolicy::INCLUDE_PADDING,
461 &hash_prefix);
462 full_hash_cache_parsed.SetString("Hash prefix (base64)", hash_prefix);
463 }
464 if (full_hash_cache.cached_hash_prefix_info().has_negative_expiry()) {
465 full_hash_cache_parsed.SetString(
466 "Negative expiry",
467 UserReadableTimeFromMillisSinceEpoch(
468 full_hash_cache.cached_hash_prefix_info().negative_expiry())
469 .GetString());
470 }
471
472 full_hash_cache_list->Append(std::move(full_hash_cache_parsed));
473
474 for (auto full_hash_info_it :
475 full_hash_cache.cached_hash_prefix_info().full_hash_info()) {
476 base::DictionaryValue full_hash_info_dict;
477 ParseFullHashInfo(full_hash_info_it, &full_hash_info_dict);
478 full_hash_cache_list->Append(std::move(full_hash_info_dict));
479 }
480 }
481
ParseFullHashCacheInfo(const FullHashCacheInfo full_hash_cache_info_proto,base::ListValue * full_hash_cache_info)482 void ParseFullHashCacheInfo(const FullHashCacheInfo full_hash_cache_info_proto,
483 base::ListValue* full_hash_cache_info) {
484 if (full_hash_cache_info_proto.has_number_of_hits()) {
485 base::DictionaryValue number_of_hits;
486 number_of_hits.SetInteger("Number of cache hits",
487 full_hash_cache_info_proto.number_of_hits());
488 full_hash_cache_info->Append(std::move(number_of_hits));
489 }
490
491 // Record FullHashCache list.
492 for (auto full_hash_cache_it : full_hash_cache_info_proto.full_hash_cache()) {
493 base::ListValue full_hash_cache_list;
494 ParseFullHashCache(full_hash_cache_it, &full_hash_cache_list);
495 full_hash_cache_info->Append(std::move(full_hash_cache_list));
496 }
497 }
498
AddFullHashCacheInfo(const FullHashCacheInfo full_hash_cache_info_proto)499 std::string AddFullHashCacheInfo(
500 const FullHashCacheInfo full_hash_cache_info_proto) {
501 std::string full_hash_cache_parsed;
502
503 base::ListValue full_hash_cache;
504 ParseFullHashCacheInfo(full_hash_cache_info_proto, &full_hash_cache);
505
506 base::Value* full_hash_cache_tree = &full_hash_cache;
507
508 JSONStringValueSerializer serializer(&full_hash_cache_parsed);
509 serializer.set_pretty_print(true);
510 serializer.Serialize(*full_hash_cache_tree);
511
512 return full_hash_cache_parsed;
513 }
514
515 #endif
516
SerializeReferrer(const ReferrerChainEntry & referrer)517 base::Value SerializeReferrer(const ReferrerChainEntry& referrer) {
518 base::DictionaryValue referrer_dict;
519 referrer_dict.SetKey("url", base::Value(referrer.url()));
520 referrer_dict.SetKey("main_frame_url",
521 base::Value(referrer.main_frame_url()));
522
523 std::string url_type;
524 switch (referrer.type()) {
525 case ReferrerChainEntry::EVENT_URL:
526 url_type = "EVENT_URL";
527 break;
528 case ReferrerChainEntry::LANDING_PAGE:
529 url_type = "LANDING_PAGE";
530 break;
531 case ReferrerChainEntry::LANDING_REFERRER:
532 url_type = "LANDING_REFERRER";
533 break;
534 case ReferrerChainEntry::CLIENT_REDIRECT:
535 url_type = "CLIENT_REDIRECT";
536 break;
537 case ReferrerChainEntry::DEPRECATED_SERVER_REDIRECT:
538 url_type = "DEPRECATED_SERVER_REDIRECT";
539 break;
540 case ReferrerChainEntry::RECENT_NAVIGATION:
541 url_type = "RECENT_NAVIGATION";
542 break;
543 case ReferrerChainEntry::REFERRER:
544 url_type = "REFERRER";
545 break;
546 }
547 referrer_dict.SetKey("type", base::Value(url_type));
548
549 base::ListValue ip_addresses;
550 for (const std::string& ip_address : referrer.ip_addresses()) {
551 ip_addresses.Append(base::Value(ip_address));
552 }
553 referrer_dict.SetKey("ip_addresses", std::move(ip_addresses));
554
555 referrer_dict.SetKey("referrer_url", base::Value(referrer.referrer_url()));
556
557 referrer_dict.SetKey("referrer_main_frame_url",
558 base::Value(referrer.referrer_main_frame_url()));
559
560 referrer_dict.SetKey("is_retargeting",
561 base::Value(referrer.is_retargeting()));
562
563 referrer_dict.SetKey("navigation_time_msec",
564 base::Value(referrer.navigation_time_msec()));
565
566 base::ListValue server_redirects;
567 for (const ReferrerChainEntry::ServerRedirect& server_redirect :
568 referrer.server_redirect_chain()) {
569 server_redirects.Append(base::Value(server_redirect.url()));
570 }
571 referrer_dict.SetKey("server_redirect_chain", std::move(server_redirects));
572
573 std::string navigation_initiation;
574 switch (referrer.navigation_initiation()) {
575 case ReferrerChainEntry::UNDEFINED:
576 navigation_initiation = "UNDEFINED";
577 break;
578 case ReferrerChainEntry::BROWSER_INITIATED:
579 navigation_initiation = "BROWSER_INITIATED";
580 break;
581 case ReferrerChainEntry::RENDERER_INITIATED_WITHOUT_USER_GESTURE:
582 navigation_initiation = "RENDERER_INITIATED_WITHOUT_USER_GESTURE";
583 break;
584 case ReferrerChainEntry::RENDERER_INITIATED_WITH_USER_GESTURE:
585 navigation_initiation = "RENDERER_INITIATED_WITH_USER_GESTURE";
586 break;
587 }
588 referrer_dict.SetKey("navigation_initiation",
589 base::Value(navigation_initiation));
590
591 referrer_dict.SetKey(
592 "maybe_launched_by_external_application",
593 base::Value(referrer.maybe_launched_by_external_application()));
594
595 return std::move(referrer_dict);
596 }
597
SerializeClientDownloadRequest(const ClientDownloadRequest & cdr)598 std::string SerializeClientDownloadRequest(const ClientDownloadRequest& cdr) {
599 base::DictionaryValue dict;
600 if (cdr.has_url())
601 dict.SetString("url", cdr.url());
602 if (cdr.has_download_type())
603 dict.SetInteger("download_type", cdr.download_type());
604 if (cdr.has_length())
605 dict.SetInteger("length", cdr.length());
606 if (cdr.has_file_basename())
607 dict.SetString("file_basename", cdr.file_basename());
608 if (cdr.has_archive_valid())
609 dict.SetBoolean("archive_valid", cdr.archive_valid());
610
611 auto archived_binaries = std::make_unique<base::ListValue>();
612 for (const auto& archived_binary : cdr.archived_binary()) {
613 auto dict_archived_binary = std::make_unique<base::DictionaryValue>();
614 if (archived_binary.has_file_basename())
615 dict_archived_binary->SetString("file_basename",
616 archived_binary.file_basename());
617 if (archived_binary.has_download_type())
618 dict_archived_binary->SetInteger("download_type",
619 archived_binary.download_type());
620 if (archived_binary.has_length())
621 dict_archived_binary->SetInteger("length", archived_binary.length());
622 if (archived_binary.is_encrypted())
623 dict_archived_binary->SetBoolean("is_encrypted", true);
624 if (archived_binary.digests().has_sha256()) {
625 const std::string& sha256 = archived_binary.digests().sha256();
626 dict_archived_binary->SetString(
627 "digests.sha256", base::HexEncode(sha256.c_str(), sha256.size()));
628 }
629 archived_binaries->Append(std::move(dict_archived_binary));
630 }
631 dict.SetList("archived_binary", std::move(archived_binaries));
632
633 auto referrer_chain = std::make_unique<base::ListValue>();
634 for (const auto& referrer_chain_entry : cdr.referrer_chain()) {
635 referrer_chain->Append(SerializeReferrer(referrer_chain_entry));
636 }
637 dict.SetList("referrer_chain", std::move(referrer_chain));
638
639 dict.SetBoolean("request_ap_verdicts", cdr.request_ap_verdicts());
640
641 dict.SetInteger("archive_file_count", cdr.archive_file_count());
642 dict.SetInteger("archive_directory_count", cdr.archive_directory_count());
643
644 dict.SetBoolean("request_ap_verdicts", cdr.request_ap_verdicts());
645
646 if (!cdr.access_token().empty())
647 dict.SetString("access_token", cdr.access_token());
648
649 base::Value* request_tree = &dict;
650 std::string request_serialized;
651 JSONStringValueSerializer serializer(&request_serialized);
652 serializer.set_pretty_print(true);
653 serializer.Serialize(*request_tree);
654 return request_serialized;
655 }
656
SerializeClientDownloadResponse(const ClientDownloadResponse & cdr)657 std::string SerializeClientDownloadResponse(const ClientDownloadResponse& cdr) {
658 base::DictionaryValue dict;
659
660 switch (cdr.verdict()) {
661 case ClientDownloadResponse::SAFE:
662 dict.SetKey("verdict", base::Value("SAFE"));
663 break;
664 case ClientDownloadResponse::DANGEROUS:
665 dict.SetKey("verdict", base::Value("DANGEROUS"));
666 break;
667 case ClientDownloadResponse::UNCOMMON:
668 dict.SetKey("verdict", base::Value("UNCOMMON"));
669 break;
670 case ClientDownloadResponse::POTENTIALLY_UNWANTED:
671 dict.SetKey("verdict", base::Value("POTENTIALLY_UNWANTED"));
672 break;
673 case ClientDownloadResponse::DANGEROUS_HOST:
674 dict.SetKey("verdict", base::Value("DANGEROUS_HOST"));
675 break;
676 case ClientDownloadResponse::UNKNOWN:
677 dict.SetKey("verdict", base::Value("UNKNOWN"));
678 break;
679 }
680
681 if (cdr.has_more_info()) {
682 dict.SetPath({"more_info", "description"},
683 base::Value(cdr.more_info().description()));
684 dict.SetPath({"more_info", "url"}, base::Value(cdr.more_info().url()));
685 }
686
687 if (cdr.has_token()) {
688 dict.SetKey("token", base::Value(cdr.token()));
689 }
690
691 if (cdr.has_upload()) {
692 dict.SetKey("upload", base::Value(cdr.upload()));
693 }
694
695 base::Value* request_tree = &dict;
696 std::string request_serialized;
697 JSONStringValueSerializer serializer(&request_serialized);
698 serializer.set_pretty_print(true);
699 serializer.Serialize(*request_tree);
700 return request_serialized;
701 }
702
SerializeCSBRR(const ClientSafeBrowsingReportRequest & report)703 std::string SerializeCSBRR(const ClientSafeBrowsingReportRequest& report) {
704 base::DictionaryValue report_request;
705 if (report.has_type()) {
706 report_request.SetInteger("type", static_cast<int>(report.type()));
707 }
708 if (report.has_page_url())
709 report_request.SetString("page_url", report.page_url());
710 if (report.has_client_country()) {
711 report_request.SetString("client_country", report.client_country());
712 }
713 if (report.has_repeat_visit()) {
714 report_request.SetInteger("repeat_visit", report.repeat_visit());
715 }
716 if (report.has_did_proceed()) {
717 report_request.SetInteger("did_proceed", report.did_proceed());
718 }
719 std::string serialized;
720 if (report.SerializeToString(&serialized)) {
721 std::string base64_encoded;
722 base::Base64Encode(serialized, &base64_encoded);
723 report_request.SetString("csbrr(base64)", base64_encoded);
724 }
725
726 base::Value* report_request_tree = &report_request;
727 std::string report_request_serialized;
728 JSONStringValueSerializer serializer(&report_request_serialized);
729 serializer.set_pretty_print(true);
730 serializer.Serialize(*report_request_tree);
731 return report_request_serialized;
732 }
733
SerializeReuseLookup(const PasswordReuseLookup password_reuse_lookup)734 base::Value SerializeReuseLookup(
735 const PasswordReuseLookup password_reuse_lookup) {
736 std::string lookup_result;
737 switch (password_reuse_lookup.lookup_result()) {
738 case PasswordReuseLookup::UNSPECIFIED:
739 lookup_result = "UNSPECIFIED";
740 break;
741 case PasswordReuseLookup::WHITELIST_HIT:
742 lookup_result = "WHITELIST_HIT";
743 break;
744 case PasswordReuseLookup::CACHE_HIT:
745 lookup_result = "CACHE_HIT";
746 break;
747 case PasswordReuseLookup::REQUEST_SUCCESS:
748 lookup_result = "REQUEST_SUCCESS";
749 break;
750 case PasswordReuseLookup::REQUEST_FAILURE:
751 lookup_result = "REQUEST_FAILURE";
752 break;
753 case PasswordReuseLookup::URL_UNSUPPORTED:
754 lookup_result = "URL_UNSUPPORTED";
755 break;
756 case PasswordReuseLookup::ENTERPRISE_WHITELIST_HIT:
757 lookup_result = "ENTERPRISE_WHITELIST_HIT";
758 break;
759 case PasswordReuseLookup::TURNED_OFF_BY_POLICY:
760 lookup_result = "TURNED_OFF_BY_POLICY";
761 break;
762 }
763 return base::Value(lookup_result);
764 }
765
SerializeVerdict(const PasswordReuseLookup password_reuse_lookup)766 base::Value SerializeVerdict(const PasswordReuseLookup password_reuse_lookup) {
767 std::string verdict;
768 switch (password_reuse_lookup.verdict()) {
769 case PasswordReuseLookup::VERDICT_UNSPECIFIED:
770 verdict = "VERDICT_UNSPECIFIED";
771 break;
772 case PasswordReuseLookup::SAFE:
773 verdict = "SAFE";
774 break;
775 case PasswordReuseLookup::LOW_REPUTATION:
776 verdict = "LOW_REPUTATION";
777 break;
778 case PasswordReuseLookup::PHISHING:
779 verdict = "PHISHING";
780 break;
781 }
782 return base::Value(verdict);
783 }
784
SerializePGEvent(const sync_pb::UserEventSpecifics & event)785 base::DictionaryValue SerializePGEvent(
786 const sync_pb::UserEventSpecifics& event) {
787 base::DictionaryValue result;
788
789 base::Time timestamp = base::Time::FromDeltaSinceWindowsEpoch(
790 base::TimeDelta::FromMicroseconds(event.event_time_usec()));
791 result.SetDouble("time", timestamp.ToJsTime());
792
793 base::DictionaryValue event_dict;
794
795 // Nominally only one of the following if() statements would be true.
796 // Note that top-level path is either password_captured, or one of the fields
797 // under GaiaPasswordReuse (ie. we've flattened the namespace for simplicity).
798
799 if (event.has_gaia_password_captured_event()) {
800 std::string event_trigger;
801
802 switch (event.gaia_password_captured_event().event_trigger()) {
803 case PasswordCaptured::UNSPECIFIED:
804 event_trigger = "UNSPECIFIED";
805 break;
806 case PasswordCaptured::USER_LOGGED_IN:
807 event_trigger = "USER_LOGGED_IN";
808 break;
809 case PasswordCaptured::EXPIRED_28D_TIMER:
810 event_trigger = "EXPIRED_28D_TIMER";
811 break;
812 }
813
814 event_dict.SetPath({"password_captured", "event_trigger"},
815 base::Value(event_trigger));
816 }
817
818 GaiaPasswordReuse reuse = event.gaia_password_reuse_event();
819 if (reuse.has_reuse_detected()) {
820 event_dict.SetPath({"reuse_detected", "status", "enabled"},
821 base::Value(reuse.reuse_detected().status().enabled()));
822
823 std::string reporting_population;
824 switch (
825 reuse.reuse_detected().status().safe_browsing_reporting_population()) {
826 case PasswordReuseDetected::SafeBrowsingStatus::
827 REPORTING_POPULATION_UNSPECIFIED:
828 reporting_population = "REPORTING_POPULATION_UNSPECIFIED";
829 break;
830 case PasswordReuseDetected::SafeBrowsingStatus::NONE:
831 reporting_population = "NONE";
832 break;
833 case PasswordReuseDetected::SafeBrowsingStatus::EXTENDED_REPORTING:
834 reporting_population = "EXTENDED_REPORTING";
835 break;
836 case PasswordReuseDetected::SafeBrowsingStatus::SCOUT:
837 reporting_population = "SCOUT";
838 break;
839 }
840 event_dict.SetPath({"reuse_detected", "status", "reporting_population"},
841 base::Value(reporting_population));
842 }
843
844 if (reuse.has_reuse_lookup()) {
845 event_dict.SetPath({"reuse_lookup", "lookup_result"},
846 SerializeReuseLookup(reuse.reuse_lookup()));
847 event_dict.SetPath({"reuse_lookup", "verdict"},
848 SerializeVerdict(reuse.reuse_lookup()));
849 event_dict.SetPath({"reuse_lookup", "verdict_token"},
850 base::Value(reuse.reuse_lookup().verdict_token()));
851 }
852
853 if (reuse.has_dialog_interaction()) {
854 std::string interaction_result;
855 switch (reuse.dialog_interaction().interaction_result()) {
856 case PasswordReuseDialogInteraction::UNSPECIFIED:
857 interaction_result = "UNSPECIFIED";
858 break;
859 case PasswordReuseDialogInteraction::WARNING_ACTION_TAKEN:
860 interaction_result = "WARNING_ACTION_TAKEN";
861 break;
862 case PasswordReuseDialogInteraction::WARNING_ACTION_IGNORED:
863 interaction_result = "WARNING_ACTION_IGNORED";
864 break;
865 case PasswordReuseDialogInteraction::WARNING_UI_IGNORED:
866 interaction_result = "WARNING_UI_IGNORED";
867 break;
868 case PasswordReuseDialogInteraction::WARNING_ACTION_TAKEN_ON_SETTINGS:
869 interaction_result = "WARNING_ACTION_TAKEN_ON_SETTINGS";
870 break;
871 }
872 event_dict.SetPath({"dialog_interaction", "interaction_result"},
873 base::Value(interaction_result));
874 }
875
876 std::string event_serialized;
877 JSONStringValueSerializer serializer(&event_serialized);
878 serializer.set_pretty_print(true);
879 serializer.Serialize(event_dict);
880 result.SetString("message", event_serialized);
881 return result;
882 }
883
SerializeSecurityEvent(const sync_pb::GaiaPasswordReuse & event)884 base::DictionaryValue SerializeSecurityEvent(
885 const sync_pb::GaiaPasswordReuse& event) {
886 base::DictionaryValue result;
887
888 base::DictionaryValue event_dict;
889 if (event.has_reuse_lookup()) {
890 event_dict.SetPath({"reuse_lookup", "lookup_result"},
891 SerializeReuseLookup(event.reuse_lookup()));
892 event_dict.SetPath({"reuse_lookup", "verdict"},
893 SerializeVerdict(event.reuse_lookup()));
894 event_dict.SetPath({"reuse_lookup", "verdict_token"},
895 base::Value(event.reuse_lookup().verdict_token()));
896 }
897
898 std::string event_serialized;
899 JSONStringValueSerializer serializer(&event_serialized);
900 serializer.set_pretty_print(true);
901 serializer.Serialize(event_dict);
902 result.SetString("message", event_serialized);
903 return result;
904 }
905
SerializeFrame(const LoginReputationClientRequest::Frame & frame)906 base::Value SerializeFrame(const LoginReputationClientRequest::Frame& frame) {
907 base::DictionaryValue frame_dict;
908 frame_dict.SetKey("frame_index", base::Value(frame.frame_index()));
909 frame_dict.SetKey("parent_frame_index",
910 base::Value(frame.parent_frame_index()));
911 frame_dict.SetKey("url", base::Value(frame.url()));
912 frame_dict.SetKey("has_password_field",
913 base::Value(frame.has_password_field()));
914
915 base::ListValue referrer_list;
916 for (const ReferrerChainEntry& referrer : frame.referrer_chain()) {
917 referrer_list.Append(SerializeReferrer(referrer));
918 }
919 frame_dict.SetKey("referrer_chain", std::move(referrer_list));
920
921 frame_dict.SetPath(
922 {"referrer_chain_options", "recent_navigations_to_collect"},
923 base::Value(
924 frame.referrer_chain_options().recent_navigations_to_collect()));
925
926 base::ListValue form_list;
927 for (const LoginReputationClientRequest::Frame::Form& form : frame.forms()) {
928 base::DictionaryValue form_dict;
929 form_dict.SetKey("action_url", base::Value(form.action_url()));
930 form_dict.SetKey("has_password_field",
931 base::Value(form.has_password_field()));
932 form_list.Append(std::move(form_dict));
933 }
934 frame_dict.SetKey("forms", std::move(form_list));
935
936 return std::move(frame_dict);
937 }
938
SerializePasswordReuseEvent(const LoginReputationClientRequest::PasswordReuseEvent & event)939 base::Value SerializePasswordReuseEvent(
940 const LoginReputationClientRequest::PasswordReuseEvent& event) {
941 base::DictionaryValue event_dict;
942
943 base::ListValue domains_list;
944 for (const std::string& domain : event.domains_matching_password()) {
945 domains_list.Append(base::Value(domain));
946 }
947 event_dict.SetKey("domains_matching_password", std::move(domains_list));
948
949 event_dict.SetKey("frame_id", base::Value(event.frame_id()));
950 event_dict.SetKey("is_chrome_signin_password",
951 base::Value(event.is_chrome_signin_password()));
952
953 std::string sync_account_type;
954 switch (event.sync_account_type()) {
955 case LoginReputationClientRequest::PasswordReuseEvent::NOT_SIGNED_IN:
956 sync_account_type = "NOT_SIGNED_IN";
957 break;
958 case LoginReputationClientRequest::PasswordReuseEvent::GMAIL:
959 sync_account_type = "GMAIL";
960 break;
961 case LoginReputationClientRequest::PasswordReuseEvent::GSUITE:
962 sync_account_type = "GSUITE";
963 break;
964 }
965 event_dict.SetKey("sync_account_type", base::Value(sync_account_type));
966
967 std::string reused_password_type;
968 switch (event.reused_password_type()) {
969 case LoginReputationClientRequest::PasswordReuseEvent::
970 REUSED_PASSWORD_TYPE_UNKNOWN:
971 reused_password_type = "REUSED_PASSWORD_TYPE_UNKNOWN";
972 break;
973 case LoginReputationClientRequest::PasswordReuseEvent::SAVED_PASSWORD:
974 reused_password_type = "SAVED_PASSWORD";
975 break;
976 case LoginReputationClientRequest::PasswordReuseEvent::SIGN_IN_PASSWORD:
977 reused_password_type = "SIGN_IN_PASSWORD";
978 break;
979 case LoginReputationClientRequest::PasswordReuseEvent::OTHER_GAIA_PASSWORD:
980 reused_password_type = "OTHER_GAIA_PASSWORD";
981 break;
982 case LoginReputationClientRequest::PasswordReuseEvent::ENTERPRISE_PASSWORD:
983 reused_password_type = "ENTERPRISE_PASSWORD";
984 break;
985 }
986 event_dict.SetKey("reused_password_type", base::Value(reused_password_type));
987
988 return std::move(event_dict);
989 }
990
SerializeChromeUserPopulation(const ChromeUserPopulation & population)991 base::Value SerializeChromeUserPopulation(
992 const ChromeUserPopulation& population) {
993 base::DictionaryValue population_dict;
994
995 std::string user_population;
996 switch (population.user_population()) {
997 case ChromeUserPopulation::UNKNOWN_USER_POPULATION:
998 user_population = "UNKNOWN_USER_POPULATION";
999 break;
1000 case ChromeUserPopulation::SAFE_BROWSING:
1001 user_population = "SAFE_BROWSING";
1002 break;
1003 case ChromeUserPopulation::EXTENDED_REPORTING:
1004 user_population = "EXTENDED_REPORTING";
1005 break;
1006 case ChromeUserPopulation::ENHANCED_PROTECTION:
1007 user_population = "ENHANCED_PROTECTION";
1008 break;
1009 }
1010 population_dict.SetKey("user_population", base::Value(user_population));
1011
1012 population_dict.SetKey("is_history_sync_enabled",
1013 base::Value(population.is_history_sync_enabled()));
1014
1015 base::ListValue finch_list;
1016 for (const std::string& finch_group : population.finch_active_groups()) {
1017 finch_list.Append(base::Value(finch_group));
1018 }
1019 population_dict.SetKey("finch_active_groups", std::move(finch_list));
1020
1021 std::string management_status;
1022 switch (population.profile_management_status()) {
1023 case ChromeUserPopulation::UNKNOWN:
1024 management_status = "UNKNOWN";
1025 break;
1026 case ChromeUserPopulation::UNAVAILABLE:
1027 management_status = "UNAVAILABLE";
1028 break;
1029 case ChromeUserPopulation::NOT_MANAGED:
1030 management_status = "NOT_MANAGED";
1031 break;
1032 case ChromeUserPopulation::ENTERPRISE_MANAGED:
1033 management_status = "ENTERPRISE_MANAGED";
1034 break;
1035 }
1036 population_dict.SetKey("profile_management_status",
1037 base::Value(management_status));
1038 population_dict.SetKey(
1039 "is_under_advanced_protection",
1040 base::Value(population.is_under_advanced_protection()));
1041 population_dict.SetKey("is_incognito",
1042 base::Value(population.is_incognito()));
1043
1044 return std::move(population_dict);
1045 }
1046
SerializeRTThreatInfo(const RTLookupResponse::ThreatInfo & threat_info)1047 base::Value SerializeRTThreatInfo(
1048 const RTLookupResponse::ThreatInfo& threat_info) {
1049 base::DictionaryValue threat_info_dict;
1050 std::string threat_type;
1051 switch (threat_info.threat_type()) {
1052 case RTLookupResponse::ThreatInfo::THREAT_TYPE_UNSPECIFIED:
1053 threat_type = "THREAT_TYPE_UNSPECIFIED";
1054 break;
1055 case RTLookupResponse::ThreatInfo::WEB_MALWARE:
1056 threat_type = "WEB_MALWARE";
1057 break;
1058 case RTLookupResponse::ThreatInfo::SOCIAL_ENGINEERING:
1059 threat_type = "SOCIAL_ENGINEERING";
1060 break;
1061 case RTLookupResponse::ThreatInfo::UNWANTED_SOFTWARE:
1062 threat_type = "UNWANTED_SOFTWARE";
1063 break;
1064 case RTLookupResponse::ThreatInfo::UNCLEAR_BILLING:
1065 threat_type = "UNCLEAR_BILLING";
1066 break;
1067 }
1068 threat_info_dict.SetKey("threat_type", base::Value(threat_type));
1069
1070 threat_info_dict.SetKey(
1071 "cache_duration_sec",
1072 base::Value(static_cast<double>(threat_info.cache_duration_sec())));
1073
1074 threat_info_dict.SetKey("cache_expression",
1075 base::Value(threat_info.cache_expression()));
1076
1077 std::string verdict_type;
1078 switch (threat_info.verdict_type()) {
1079 case RTLookupResponse::ThreatInfo::VERDICT_TYPE_UNSPECIFIED:
1080 verdict_type = "VERDICT_TYPE_UNSPECIFIED";
1081 break;
1082 case RTLookupResponse::ThreatInfo::SAFE:
1083 verdict_type = "SAFE";
1084 break;
1085 case RTLookupResponse::ThreatInfo::DANGEROUS:
1086 verdict_type = "DANGEROUS";
1087 break;
1088 }
1089 threat_info_dict.SetKey("verdict_type", base::Value(verdict_type));
1090
1091 std::string cache_expression_match_type;
1092 switch (threat_info.cache_expression_match_type()) {
1093 case RTLookupResponse::ThreatInfo::MATCH_TYPE_UNSPECIFIED:
1094 cache_expression_match_type = "MATCH_TYPE_UNSPECIFIED";
1095 break;
1096 case RTLookupResponse::ThreatInfo::COVERING_MATCH:
1097 cache_expression_match_type = "COVERING_MATCH";
1098 break;
1099 case RTLookupResponse::ThreatInfo::EXACT_MATCH:
1100 cache_expression_match_type = "EXACT_MATCH";
1101 break;
1102 }
1103
1104 threat_info_dict.SetKey("cache_expression_match_type",
1105 base::Value(cache_expression_match_type));
1106 threat_info_dict.SetKey(
1107 "cache_expression_using_match_type",
1108 base::Value(threat_info.cache_expression_using_match_type()));
1109 return std::move(threat_info_dict);
1110 }
1111
SerializeDomFeatures(const DomFeatures & dom_features)1112 base::Value SerializeDomFeatures(const DomFeatures& dom_features) {
1113 base::DictionaryValue dom_features_dict;
1114 auto feature_map = std::make_unique<base::ListValue>();
1115 for (const auto& feature : dom_features.feature_map()) {
1116 auto feature_dict = std::make_unique<base::DictionaryValue>();
1117 feature_dict->SetStringKey("name", feature.name());
1118 feature_dict->SetDoubleKey("value", feature.value());
1119 feature_map->Append(std::move(feature_dict));
1120 }
1121 dom_features_dict.SetList("feature_map", std::move(feature_map));
1122
1123 auto shingle_hashes = std::make_unique<base::ListValue>();
1124 for (const auto& hash : dom_features.shingle_hashes()) {
1125 shingle_hashes->AppendInteger(hash);
1126 }
1127 dom_features_dict.SetList("shingle_hashes", std::move(shingle_hashes));
1128
1129 dom_features_dict.SetInteger("model_version", dom_features.model_version());
1130
1131 return std::move(dom_features_dict);
1132 }
1133
SerializePGPing(const LoginReputationClientRequest & request)1134 std::string SerializePGPing(const LoginReputationClientRequest& request) {
1135 base::DictionaryValue request_dict;
1136
1137 request_dict.SetKey("page_url", base::Value(request.page_url()));
1138
1139 std::string trigger_type;
1140 switch (request.trigger_type()) {
1141 case LoginReputationClientRequest::TRIGGER_TYPE_UNSPECIFIED:
1142 trigger_type = "TRIGGER_TYPE_UNSPECIFIED";
1143 break;
1144 case LoginReputationClientRequest::UNFAMILIAR_LOGIN_PAGE:
1145 trigger_type = "UNFAMILIAR_LOGIN_PAGE";
1146 break;
1147 case LoginReputationClientRequest::PASSWORD_REUSE_EVENT:
1148 trigger_type = "PASSWORD_REUSE_EVENT";
1149 break;
1150 }
1151 request_dict.SetKey("trigger_type", base::Value(trigger_type));
1152
1153 base::ListValue frames_list;
1154 for (const LoginReputationClientRequest::Frame& frame : request.frames()) {
1155 frames_list.Append(SerializeFrame(frame));
1156 }
1157 request_dict.SetKey("frames", std::move(frames_list));
1158
1159 request_dict.SetKey(
1160 "password_reuse_event",
1161 SerializePasswordReuseEvent(request.password_reuse_event()));
1162 request_dict.SetKey("stored_verdict_cnt",
1163 base::Value(request.stored_verdict_cnt()));
1164 request_dict.SetKey("population",
1165 SerializeChromeUserPopulation(request.population()));
1166 request_dict.SetKey("clicked_through_interstitial",
1167 base::Value(request.clicked_through_interstitial()));
1168 request_dict.SetKey("content_type", base::Value(request.content_type()));
1169
1170 if (request.has_content_area_height()) {
1171 request_dict.SetKey("content_area_height",
1172 base::Value(request.content_area_height()));
1173 }
1174 if (request.has_content_area_width()) {
1175 request_dict.SetKey("content_area_width",
1176 base::Value(request.content_area_width()));
1177 }
1178
1179 if (request.has_dom_features()) {
1180 request_dict.SetKey("dom_features",
1181 SerializeDomFeatures(request.dom_features()));
1182 }
1183
1184 std::string request_serialized;
1185 JSONStringValueSerializer serializer(&request_serialized);
1186 serializer.set_pretty_print(true);
1187 serializer.Serialize(request_dict);
1188 return request_serialized;
1189 }
1190
SerializePGResponse(const LoginReputationClientResponse & response)1191 std::string SerializePGResponse(const LoginReputationClientResponse& response) {
1192 base::DictionaryValue response_dict;
1193
1194 std::string verdict;
1195 switch (response.verdict_type()) {
1196 case LoginReputationClientResponse::VERDICT_TYPE_UNSPECIFIED:
1197 verdict = "VERDICT_TYPE_UNSPECIFIED";
1198 break;
1199 case LoginReputationClientResponse::SAFE:
1200 verdict = "SAFE";
1201 break;
1202 case LoginReputationClientResponse::LOW_REPUTATION:
1203 verdict = "LOW_REPUTATION";
1204 break;
1205 case LoginReputationClientResponse::PHISHING:
1206 verdict = "PHISHING";
1207 break;
1208 }
1209 response_dict.SetKey("verdict_type", base::Value(verdict));
1210 response_dict.SetKey("cache_duration_sec",
1211 base::Value(int(response.cache_duration_sec())));
1212 response_dict.SetKey("cache_expression",
1213 base::Value(response.cache_expression()));
1214 response_dict.SetKey("verdict_token", base::Value(response.verdict_token()));
1215
1216 std::string response_serialized;
1217 JSONStringValueSerializer serializer(&response_serialized);
1218 serializer.set_pretty_print(true);
1219 serializer.Serialize(response_dict);
1220 return response_serialized;
1221 }
1222
SerializeRTLookupPing(const RTLookupRequest & request)1223 std::string SerializeRTLookupPing(const RTLookupRequest& request) {
1224 base::DictionaryValue request_dict;
1225
1226 request_dict.SetKey("url", base::Value(request.url()));
1227 request_dict.SetKey("population",
1228 SerializeChromeUserPopulation(request.population()));
1229 request_dict.SetKey("scoped_oauth_token",
1230 base::Value(request.scoped_oauth_token()));
1231
1232 std::string lookupType;
1233 switch (request.lookup_type()) {
1234 case RTLookupRequest::LOOKUP_TYPE_UNSPECIFIED:
1235 lookupType = "LOOKUP_TYPE_UNSPECIFIED";
1236 break;
1237 case RTLookupRequest::NAVIGATION:
1238 lookupType = "NAVIGATION";
1239 break;
1240 case RTLookupRequest::DOWNLOAD:
1241 lookupType = "DOWNLOAD";
1242 break;
1243 }
1244
1245 request_dict.SetKey("lookup_type", base::Value(lookupType));
1246
1247 std::string request_serialized;
1248 JSONStringValueSerializer serializer(&request_serialized);
1249 serializer.set_pretty_print(true);
1250 serializer.Serialize(request_dict);
1251 return request_serialized;
1252 }
1253
SerializeRTLookupResponse(const RTLookupResponse & response)1254 std::string SerializeRTLookupResponse(const RTLookupResponse& response) {
1255 base::DictionaryValue response_dict;
1256
1257 base::ListValue threat_info_list;
1258 for (const RTLookupResponse::ThreatInfo& threat_info :
1259 response.threat_info()) {
1260 threat_info_list.Append(SerializeRTThreatInfo(threat_info));
1261 }
1262 response_dict.SetKey("threat_infos", std::move(threat_info_list));
1263
1264 std::string response_serialized;
1265 JSONStringValueSerializer serializer(&response_serialized);
1266 serializer.set_pretty_print(true);
1267 serializer.Serialize(response_dict);
1268 return response_serialized;
1269 }
1270
SerializeLogMessage(const base::Time & timestamp,const std::string & message)1271 base::Value SerializeLogMessage(const base::Time& timestamp,
1272 const std::string& message) {
1273 base::DictionaryValue result;
1274 result.SetDouble("time", timestamp.ToJsTime());
1275 result.SetString("message", message);
1276 return std::move(result);
1277 }
1278
SerializeReportingEvent(const base::Value & event)1279 base::Value SerializeReportingEvent(const base::Value& event) {
1280 base::DictionaryValue result;
1281
1282 std::string event_serialized;
1283 JSONStringValueSerializer serializer(&event_serialized);
1284 serializer.set_pretty_print(true);
1285 serializer.Serialize(event);
1286
1287 result.SetString("message", event_serialized);
1288
1289 return std::move(result);
1290 }
1291
1292 #if BUILDFLAG(FULL_SAFE_BROWSING)
SerializeDeepScanningRequest(const DeepScanningClientRequest & request)1293 std::string SerializeDeepScanningRequest(
1294 const DeepScanningClientRequest& request) {
1295 base::DictionaryValue request_dict;
1296
1297 request_dict.SetKey("dm_token", base::Value(request.dm_token()));
1298 request_dict.SetKey("fcm_notification_token",
1299 base::Value(request.fcm_notification_token()));
1300
1301 if (request.has_malware_scan_request()) {
1302 base::DictionaryValue malware_request;
1303
1304 switch (request.malware_scan_request().population()) {
1305 case MalwareDeepScanningClientRequest::POPULATION_UNKNOWN:
1306 malware_request.SetStringKey("population", "POPULATION_UNKNOWN");
1307 break;
1308 case MalwareDeepScanningClientRequest::POPULATION_ENTERPRISE:
1309 malware_request.SetStringKey("population", "POPULATION_ENTERPRISE");
1310 break;
1311 case MalwareDeepScanningClientRequest::POPULATION_TITANIUM:
1312 malware_request.SetStringKey("population", "POPULATION_TITANIUM");
1313 break;
1314 }
1315
1316 request_dict.SetKey("malware_scan_request", std::move(malware_request));
1317 }
1318
1319 if (request.has_dlp_scan_request()) {
1320 base::DictionaryValue dlp_request;
1321
1322 switch (request.dlp_scan_request().content_source()) {
1323 case DlpDeepScanningClientRequest::CONTENT_SOURCE_UNKNOWN:
1324 dlp_request.SetStringKey("content_source", "CONTENT_SOURCE_UNKNOWN");
1325 break;
1326 case DlpDeepScanningClientRequest::FILE_DOWNLOAD:
1327 dlp_request.SetStringKey("content_source", "FILE_DOWNLOAD");
1328 break;
1329 case DlpDeepScanningClientRequest::FILE_UPLOAD:
1330 dlp_request.SetStringKey("content_source", "FILE_UPLOAD");
1331 break;
1332 case DlpDeepScanningClientRequest::WEB_CONTENT_UPLOAD:
1333 dlp_request.SetStringKey("content_source", "WEB_CONTENT_UPLOAD");
1334 break;
1335 }
1336
1337 request_dict.SetKey("dlp_scan_request", std::move(dlp_request));
1338 }
1339
1340 request_dict.SetKey("request_token", base::Value(request.request_token()));
1341 request_dict.SetKey("filename", base::Value(request.filename()));
1342 request_dict.SetKey("digest", base::Value(request.digest()));
1343
1344 std::string request_serialized;
1345 JSONStringValueSerializer serializer(&request_serialized);
1346 serializer.set_pretty_print(true);
1347 serializer.Serialize(request_dict);
1348 return request_serialized;
1349 }
1350
SerializeDeepScanningResponse(const DeepScanningClientResponse & response)1351 std::string SerializeDeepScanningResponse(
1352 const DeepScanningClientResponse& response) {
1353 base::DictionaryValue response_dict;
1354
1355 response_dict.SetStringKey("token", response.token());
1356
1357 if (response.has_malware_scan_verdict()) {
1358 base::DictionaryValue malware_verdict;
1359
1360 switch (response.malware_scan_verdict().verdict()) {
1361 case MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED:
1362 malware_verdict.SetStringKey("verdict", "VERDICT_UNSPECIFIED");
1363 break;
1364 case MalwareDeepScanningVerdict::CLEAN:
1365 malware_verdict.SetStringKey("verdict", "CLEAN");
1366 break;
1367 case MalwareDeepScanningVerdict::UWS:
1368 malware_verdict.SetStringKey("verdict", "UWS");
1369 break;
1370 case MalwareDeepScanningVerdict::MALWARE:
1371 malware_verdict.SetStringKey("verdict", "MALWARE");
1372 break;
1373 case MalwareDeepScanningVerdict::SCAN_FAILURE:
1374 malware_verdict.SetStringKey("verdict", "SCAN_FAILURE");
1375 break;
1376 }
1377
1378 response_dict.SetKey("malware_scan_verdict", std::move(malware_verdict));
1379 }
1380
1381 if (response.has_dlp_scan_verdict()) {
1382 base::DictionaryValue dlp_verdict;
1383
1384 switch (response.dlp_scan_verdict().status()) {
1385 case DlpDeepScanningVerdict::STATUS_UNKNOWN:
1386 dlp_verdict.SetStringKey("status", "STATUS_UNKNOWN");
1387 break;
1388 case DlpDeepScanningVerdict::SUCCESS:
1389 dlp_verdict.SetStringKey("status", "SUCCESS");
1390 break;
1391 case DlpDeepScanningVerdict::FAILURE:
1392 dlp_verdict.SetStringKey("status", "FAILURE");
1393 break;
1394 }
1395
1396 base::ListValue triggered_rules;
1397 for (const DlpDeepScanningVerdict::TriggeredRule& rule :
1398 response.dlp_scan_verdict().triggered_rules()) {
1399 base::DictionaryValue rule_value;
1400
1401 switch (rule.action()) {
1402 case DlpDeepScanningVerdict::TriggeredRule::ACTION_UNKNOWN:
1403 rule_value.SetStringKey("action", "ACTION_UNKNOWN");
1404 break;
1405 case DlpDeepScanningVerdict::TriggeredRule::REPORT_ONLY:
1406 rule_value.SetStringKey("action", "REPORT_ONLY");
1407 break;
1408 case DlpDeepScanningVerdict::TriggeredRule::WARN:
1409 rule_value.SetStringKey("action", "WARN");
1410 break;
1411 case DlpDeepScanningVerdict::TriggeredRule::BLOCK:
1412 rule_value.SetStringKey("action", "BLOCK");
1413 break;
1414 }
1415
1416 rule_value.SetStringKey("rule_name", rule.rule_name());
1417 rule_value.SetDoubleKey("rule_id", rule.rule_id());
1418 rule_value.SetStringKey("rule_resource_name", rule.rule_resource_name());
1419 rule_value.SetStringKey("rule_severity", rule.rule_severity());
1420
1421 base::ListValue matched_detectors;
1422 for (const DlpDeepScanningVerdict::MatchedDetector& detector :
1423 rule.matched_detectors()) {
1424 base::DictionaryValue detector_value;
1425 detector_value.SetStringKey("detector_id", detector.detector_id());
1426 detector_value.SetStringKey("display_name", detector.display_name());
1427 detector_value.SetStringKey("detector_type", detector.detector_type());
1428 matched_detectors.Append(std::move(detector_value));
1429 }
1430
1431 rule_value.SetKey("matched_detectors", std::move(matched_detectors));
1432
1433 triggered_rules.Append(std::move(rule_value));
1434 }
1435
1436 dlp_verdict.SetKey("triggered_rules", std::move(triggered_rules));
1437 }
1438
1439 std::string response_serialized;
1440 JSONStringValueSerializer serializer(&response_serialized);
1441 serializer.set_pretty_print(true);
1442 serializer.Serialize(response_dict);
1443 return response_serialized;
1444 }
1445 #endif
1446 } // namespace
1447
SafeBrowsingUI(content::WebUI * web_ui)1448 SafeBrowsingUI::SafeBrowsingUI(content::WebUI* web_ui)
1449 : content::WebUIController(web_ui) {
1450 // Set up the chrome://safe-browsing source.
1451
1452 content::WebUIDataSource* html_source = content::WebUIDataSource::Create(
1453 safe_browsing::kChromeUISafeBrowsingHost);
1454
1455 content::BrowserContext* browser_context =
1456 web_ui->GetWebContents()->GetBrowserContext();
1457
1458 // Register callback handler.
1459 // Handles messages from JavaScript to C++ via chrome.send().
1460 web_ui->AddMessageHandler(
1461 std::make_unique<SafeBrowsingUIHandler>(browser_context));
1462
1463 // Add required resources.
1464 html_source->AddResourcePath("safe_browsing.css", IDR_SAFE_BROWSING_CSS);
1465 html_source->AddResourcePath("safe_browsing.js", IDR_SAFE_BROWSING_JS);
1466 html_source->SetDefaultResource(IDR_SAFE_BROWSING_HTML);
1467
1468 content::WebUIDataSource::Add(browser_context, html_source);
1469 }
1470
~SafeBrowsingUI()1471 SafeBrowsingUI::~SafeBrowsingUI() {}
1472
SafeBrowsingUIHandler(content::BrowserContext * context)1473 SafeBrowsingUIHandler::SafeBrowsingUIHandler(content::BrowserContext* context)
1474 : browser_context_(context) {}
1475
~SafeBrowsingUIHandler()1476 SafeBrowsingUIHandler::~SafeBrowsingUIHandler() {
1477 WebUIInfoSingleton::GetInstance()->UnregisterWebUIInstance(this);
1478 }
1479
OnJavascriptAllowed()1480 void SafeBrowsingUIHandler::OnJavascriptAllowed() {
1481 // We don't want to register the SafeBrowsingUIHandler with the
1482 // WebUIInfoSingleton at construction, since this can lead to
1483 // messages being sent to the renderer before it's ready. So register it here.
1484 WebUIInfoSingleton::GetInstance()->RegisterWebUIInstance(this);
1485 }
1486
OnJavascriptDisallowed()1487 void SafeBrowsingUIHandler::OnJavascriptDisallowed() {
1488 // In certain situations, Javascript can become disallowed before the
1489 // destructor is called (e.g. tab refresh/renderer crash). In these situation,
1490 // we want to stop receiving JS messages.
1491 WebUIInfoSingleton::GetInstance()->UnregisterWebUIInstance(this);
1492 }
1493
GetExperiments(const base::ListValue * args)1494 void SafeBrowsingUIHandler::GetExperiments(const base::ListValue* args) {
1495 AllowJavascript();
1496 std::string callback_id;
1497 args->GetString(0, &callback_id);
1498 ResolveJavascriptCallback(base::Value(callback_id), GetFeatureStatusList());
1499 }
1500
GetPrefs(const base::ListValue * args)1501 void SafeBrowsingUIHandler::GetPrefs(const base::ListValue* args) {
1502 AllowJavascript();
1503 std::string callback_id;
1504 args->GetString(0, &callback_id);
1505 ResolveJavascriptCallback(base::Value(callback_id),
1506 safe_browsing::GetSafeBrowsingPreferencesList(
1507 user_prefs::UserPrefs::Get(browser_context_)));
1508 }
1509
GetCookie(const base::ListValue * args)1510 void SafeBrowsingUIHandler::GetCookie(const base::ListValue* args) {
1511 std::string callback_id;
1512 args->GetString(0, &callback_id);
1513
1514 WebUIInfoSingleton::GetInstance()->GetCookieManager()->GetAllCookies(
1515 base::BindOnce(&SafeBrowsingUIHandler::OnGetCookie,
1516 weak_factory_.GetWeakPtr(), std::move(callback_id)));
1517 }
1518
OnGetCookie(const std::string & callback_id,const std::vector<net::CanonicalCookie> & cookies)1519 void SafeBrowsingUIHandler::OnGetCookie(
1520 const std::string& callback_id,
1521 const std::vector<net::CanonicalCookie>& cookies) {
1522 DCHECK_GE(1u, cookies.size());
1523
1524 std::string cookie = "No cookie";
1525 double time = 0.0;
1526 if (!cookies.empty()) {
1527 cookie = cookies[0].Value();
1528 time = cookies[0].CreationDate().ToJsTime();
1529 }
1530
1531 base::Value response(base::Value::Type::LIST);
1532 response.Append(base::Value(cookie));
1533 response.Append(base::Value(time));
1534
1535 AllowJavascript();
1536 ResolveJavascriptCallback(base::Value(callback_id), std::move(response));
1537 }
1538
GetSavedPasswords(const base::ListValue * args)1539 void SafeBrowsingUIHandler::GetSavedPasswords(const base::ListValue* args) {
1540 password_manager::HashPasswordManager hash_manager(
1541 user_prefs::UserPrefs::Get(browser_context_));
1542
1543 base::ListValue saved_passwords;
1544 for (const password_manager::PasswordHashData& hash_data :
1545 hash_manager.RetrieveAllPasswordHashes()) {
1546 saved_passwords.AppendString(hash_data.username);
1547 saved_passwords.AppendBoolean(hash_data.is_gaia_password);
1548 }
1549
1550 AllowJavascript();
1551 std::string callback_id;
1552 args->GetString(0, &callback_id);
1553 ResolveJavascriptCallback(base::Value(callback_id), saved_passwords);
1554 }
1555
GetDatabaseManagerInfo(const base::ListValue * args)1556 void SafeBrowsingUIHandler::GetDatabaseManagerInfo(
1557 const base::ListValue* args) {
1558 base::ListValue database_manager_info;
1559
1560 #if BUILDFLAG(SAFE_BROWSING_DB_LOCAL)
1561 const V4LocalDatabaseManager* local_database_manager_instance =
1562 V4LocalDatabaseManager::current_local_database_manager();
1563 if (local_database_manager_instance) {
1564 DatabaseManagerInfo database_manager_info_proto;
1565 FullHashCacheInfo full_hash_cache_info_proto;
1566
1567 local_database_manager_instance->CollectDatabaseManagerInfo(
1568 &database_manager_info_proto, &full_hash_cache_info_proto);
1569
1570 if (database_manager_info_proto.has_update_info()) {
1571 AddUpdateInfo(database_manager_info_proto.update_info(),
1572 &database_manager_info);
1573 }
1574 if (database_manager_info_proto.has_database_info()) {
1575 AddDatabaseInfo(database_manager_info_proto.database_info(),
1576 &database_manager_info);
1577 }
1578
1579 database_manager_info.Append(
1580 base::Value(AddFullHashCacheInfo(full_hash_cache_info_proto)));
1581 }
1582 #endif
1583
1584 AllowJavascript();
1585 std::string callback_id;
1586 args->GetString(0, &callback_id);
1587
1588 ResolveJavascriptCallback(base::Value(callback_id), database_manager_info);
1589 }
1590
GetSentClientDownloadRequests(const base::ListValue * args)1591 void SafeBrowsingUIHandler::GetSentClientDownloadRequests(
1592 const base::ListValue* args) {
1593 const std::vector<std::unique_ptr<ClientDownloadRequest>>& cdrs =
1594 WebUIInfoSingleton::GetInstance()->client_download_requests_sent();
1595
1596 base::ListValue cdrs_sent;
1597
1598 for (const auto& cdr : cdrs) {
1599 cdrs_sent.Append(base::Value(SerializeClientDownloadRequest(*cdr)));
1600 }
1601
1602 AllowJavascript();
1603 std::string callback_id;
1604 args->GetString(0, &callback_id);
1605 ResolveJavascriptCallback(base::Value(callback_id), cdrs_sent);
1606 }
1607
GetReceivedClientDownloadResponses(const base::ListValue * args)1608 void SafeBrowsingUIHandler::GetReceivedClientDownloadResponses(
1609 const base::ListValue* args) {
1610 const std::vector<std::unique_ptr<ClientDownloadResponse>>& cdrs =
1611 WebUIInfoSingleton::GetInstance()->client_download_responses_received();
1612
1613 base::ListValue cdrs_received;
1614
1615 for (const auto& cdr : cdrs) {
1616 cdrs_received.Append(base::Value(SerializeClientDownloadResponse(*cdr)));
1617 }
1618
1619 AllowJavascript();
1620 std::string callback_id;
1621 args->GetString(0, &callback_id);
1622 ResolveJavascriptCallback(base::Value(callback_id), cdrs_received);
1623 }
1624
GetSentCSBRRs(const base::ListValue * args)1625 void SafeBrowsingUIHandler::GetSentCSBRRs(const base::ListValue* args) {
1626 const std::vector<std::unique_ptr<ClientSafeBrowsingReportRequest>>& reports =
1627 WebUIInfoSingleton::GetInstance()->csbrrs_sent();
1628
1629 base::ListValue sent_reports;
1630
1631 for (const auto& report : reports) {
1632 sent_reports.Append(base::Value(SerializeCSBRR(*report)));
1633 }
1634
1635 AllowJavascript();
1636 std::string callback_id;
1637 args->GetString(0, &callback_id);
1638 ResolveJavascriptCallback(base::Value(callback_id), sent_reports);
1639 }
1640
GetPGEvents(const base::ListValue * args)1641 void SafeBrowsingUIHandler::GetPGEvents(const base::ListValue* args) {
1642 const std::vector<sync_pb::UserEventSpecifics>& events =
1643 WebUIInfoSingleton::GetInstance()->pg_event_log();
1644
1645 base::ListValue events_sent;
1646
1647 for (const sync_pb::UserEventSpecifics& event : events)
1648 events_sent.Append(SerializePGEvent(event));
1649
1650 AllowJavascript();
1651 std::string callback_id;
1652 args->GetString(0, &callback_id);
1653 ResolveJavascriptCallback(base::Value(callback_id), events_sent);
1654 }
1655
GetSecurityEvents(const base::ListValue * args)1656 void SafeBrowsingUIHandler::GetSecurityEvents(const base::ListValue* args) {
1657 const std::vector<sync_pb::GaiaPasswordReuse>& events =
1658 WebUIInfoSingleton::GetInstance()->security_event_log();
1659
1660 base::ListValue events_sent;
1661
1662 for (const sync_pb::GaiaPasswordReuse& event : events)
1663 events_sent.Append(SerializeSecurityEvent(event));
1664
1665 AllowJavascript();
1666 std::string callback_id;
1667 args->GetString(0, &callback_id);
1668 ResolveJavascriptCallback(base::Value(callback_id), events_sent);
1669 }
1670
GetPGPings(const base::ListValue * args)1671 void SafeBrowsingUIHandler::GetPGPings(const base::ListValue* args) {
1672 const std::vector<LoginReputationClientRequest> requests =
1673 WebUIInfoSingleton::GetInstance()->pg_pings();
1674
1675 base::ListValue pings_sent;
1676 for (size_t request_index = 0; request_index < requests.size();
1677 request_index++) {
1678 base::ListValue ping_entry;
1679 ping_entry.Append(base::Value(int(request_index)));
1680 ping_entry.Append(base::Value(SerializePGPing(requests[request_index])));
1681 pings_sent.Append(std::move(ping_entry));
1682 }
1683
1684 AllowJavascript();
1685 std::string callback_id;
1686 args->GetString(0, &callback_id);
1687 ResolveJavascriptCallback(base::Value(callback_id), pings_sent);
1688 }
1689
GetPGResponses(const base::ListValue * args)1690 void SafeBrowsingUIHandler::GetPGResponses(const base::ListValue* args) {
1691 const std::map<int, LoginReputationClientResponse> responses =
1692 WebUIInfoSingleton::GetInstance()->pg_responses();
1693
1694 base::ListValue responses_sent;
1695 for (const auto& token_and_response : responses) {
1696 base::ListValue response_entry;
1697 response_entry.Append(base::Value(token_and_response.first));
1698 response_entry.Append(
1699 base::Value(SerializePGResponse(token_and_response.second)));
1700 responses_sent.Append(std::move(response_entry));
1701 }
1702
1703 AllowJavascript();
1704 std::string callback_id;
1705 args->GetString(0, &callback_id);
1706 ResolveJavascriptCallback(base::Value(callback_id), responses_sent);
1707 }
1708
GetRTLookupPings(const base::ListValue * args)1709 void SafeBrowsingUIHandler::GetRTLookupPings(const base::ListValue* args) {
1710 const std::vector<RTLookupRequest> requests =
1711 WebUIInfoSingleton::GetInstance()->rt_lookup_pings();
1712
1713 base::ListValue pings_sent;
1714 for (size_t request_index = 0; request_index < requests.size();
1715 request_index++) {
1716 base::ListValue ping_entry;
1717 ping_entry.Append(base::Value(int(request_index)));
1718 ping_entry.Append(
1719 base::Value(SerializeRTLookupPing(requests[request_index])));
1720 pings_sent.Append(std::move(ping_entry));
1721 }
1722
1723 AllowJavascript();
1724 std::string callback_id;
1725 args->GetString(0, &callback_id);
1726 ResolveJavascriptCallback(base::Value(callback_id), pings_sent);
1727 }
1728
GetRTLookupResponses(const base::ListValue * args)1729 void SafeBrowsingUIHandler::GetRTLookupResponses(const base::ListValue* args) {
1730 const std::map<int, RTLookupResponse> responses =
1731 WebUIInfoSingleton::GetInstance()->rt_lookup_responses();
1732
1733 base::ListValue responses_sent;
1734 for (const auto& token_and_response : responses) {
1735 base::ListValue response_entry;
1736 response_entry.Append(base::Value(token_and_response.first));
1737 response_entry.Append(
1738 base::Value(SerializeRTLookupResponse(token_and_response.second)));
1739 responses_sent.Append(std::move(response_entry));
1740 }
1741
1742 AllowJavascript();
1743 std::string callback_id;
1744 args->GetString(0, &callback_id);
1745 ResolveJavascriptCallback(base::Value(callback_id), responses_sent);
1746 }
1747
GetRTLookupExperimentEnabled(const base::ListValue * args)1748 void SafeBrowsingUIHandler::GetRTLookupExperimentEnabled(
1749 const base::ListValue* args) {
1750 base::ListValue value;
1751 value.Append(base::Value(RealTimePolicyEngine::IsUrlLookupEnabled()));
1752
1753 AllowJavascript();
1754 std::string callback_id;
1755 args->GetString(0, &callback_id);
1756 ResolveJavascriptCallback(base::Value(callback_id), value);
1757 }
1758
GetReferrerChain(const base::ListValue * args)1759 void SafeBrowsingUIHandler::GetReferrerChain(const base::ListValue* args) {
1760 std::string url_string;
1761 args->GetString(1, &url_string);
1762
1763 ReferrerChainProvider* provider =
1764 WebUIInfoSingleton::GetInstance()->referrer_chain_provider();
1765
1766 std::string callback_id;
1767 args->GetString(0, &callback_id);
1768
1769 if (!provider) {
1770 AllowJavascript();
1771 ResolveJavascriptCallback(base::Value(callback_id), base::Value(""));
1772 return;
1773 }
1774
1775 ReferrerChain referrer_chain;
1776 provider->IdentifyReferrerChainByEventURL(
1777 GURL(url_string), SessionID::InvalidValue(), 2, &referrer_chain);
1778
1779 base::ListValue referrer_list;
1780 for (const ReferrerChainEntry& entry : referrer_chain) {
1781 referrer_list.Append(SerializeReferrer(entry));
1782 }
1783
1784 std::string referrer_chain_serialized;
1785 JSONStringValueSerializer serializer(&referrer_chain_serialized);
1786 serializer.set_pretty_print(true);
1787 serializer.Serialize(referrer_list);
1788
1789 AllowJavascript();
1790 ResolveJavascriptCallback(base::Value(callback_id),
1791 base::Value(referrer_chain_serialized));
1792 }
1793
GetReportingEvents(const base::ListValue * args)1794 void SafeBrowsingUIHandler::GetReportingEvents(const base::ListValue* args) {
1795 base::ListValue reporting_events;
1796 for (const auto& reporting_event :
1797 WebUIInfoSingleton::GetInstance()->reporting_events()) {
1798 reporting_events.Append(reporting_event.Clone());
1799 }
1800
1801 AllowJavascript();
1802 std::string callback_id;
1803 args->GetString(0, &callback_id);
1804 ResolveJavascriptCallback(base::Value(callback_id), reporting_events);
1805 }
1806
GetLogMessages(const base::ListValue * args)1807 void SafeBrowsingUIHandler::GetLogMessages(const base::ListValue* args) {
1808 const std::vector<std::pair<base::Time, std::string>>& log_messages =
1809 WebUIInfoSingleton::GetInstance()->log_messages();
1810
1811 base::ListValue messages_received;
1812 for (const auto& message : log_messages) {
1813 messages_received.Append(
1814 base::Value(SerializeLogMessage(message.first, message.second)));
1815 }
1816
1817 AllowJavascript();
1818 std::string callback_id;
1819 args->GetString(0, &callback_id);
1820 ResolveJavascriptCallback(base::Value(callback_id), messages_received);
1821 }
1822
1823 #if BUILDFLAG(FULL_SAFE_BROWSING)
GetDeepScanRequests(const base::ListValue * args)1824 void SafeBrowsingUIHandler::GetDeepScanRequests(const base::ListValue* args) {
1825 base::ListValue pings_sent;
1826 for (const auto& token_and_request :
1827 WebUIInfoSingleton::GetInstance()->deep_scan_requests()) {
1828 base::ListValue ping_entry;
1829 ping_entry.Append(base::Value(token_and_request.first));
1830 ping_entry.Append(
1831 base::Value(SerializeDeepScanningRequest(token_and_request.second)));
1832 pings_sent.Append(std::move(ping_entry));
1833 }
1834
1835 AllowJavascript();
1836 std::string callback_id;
1837 args->GetString(0, &callback_id);
1838 ResolveJavascriptCallback(base::Value(callback_id), pings_sent);
1839 }
1840
GetDeepScanResponses(const base::ListValue * args)1841 void SafeBrowsingUIHandler::GetDeepScanResponses(const base::ListValue* args) {
1842 const WebUIInfoSingleton::StatusAndDeepScanningResponseMap& responses =
1843 WebUIInfoSingleton::GetInstance()->deep_scan_responses();
1844
1845 base::ListValue responses_sent;
1846 for (const auto& token_and_status_and_response : responses) {
1847 const std::string& token = token_and_status_and_response.first;
1848 const std::string& status = token_and_status_and_response.second.first;
1849 const DeepScanningClientResponse& response =
1850 token_and_status_and_response.second.second;
1851
1852 base::ListValue response_entry;
1853 response_entry.Append(base::Value(token));
1854 response_entry.Append(base::Value(status));
1855 response_entry.Append(base::Value(SerializeDeepScanningResponse(response)));
1856 responses_sent.Append(std::move(response_entry));
1857 }
1858
1859 AllowJavascript();
1860 std::string callback_id;
1861 args->GetString(0, &callback_id);
1862 ResolveJavascriptCallback(base::Value(callback_id), responses_sent);
1863 }
1864 #endif
NotifyClientDownloadRequestJsListener(ClientDownloadRequest * client_download_request)1865 void SafeBrowsingUIHandler::NotifyClientDownloadRequestJsListener(
1866 ClientDownloadRequest* client_download_request) {
1867 AllowJavascript();
1868 FireWebUIListener(
1869 "sent-client-download-requests-update",
1870 base::Value(SerializeClientDownloadRequest(*client_download_request)));
1871 }
1872
NotifyClientDownloadResponseJsListener(ClientDownloadResponse * client_download_response)1873 void SafeBrowsingUIHandler::NotifyClientDownloadResponseJsListener(
1874 ClientDownloadResponse* client_download_response) {
1875 AllowJavascript();
1876 FireWebUIListener(
1877 "received-client-download-responses-update",
1878 base::Value(SerializeClientDownloadResponse(*client_download_response)));
1879 }
1880
NotifyCSBRRJsListener(ClientSafeBrowsingReportRequest * csbrr)1881 void SafeBrowsingUIHandler::NotifyCSBRRJsListener(
1882 ClientSafeBrowsingReportRequest* csbrr) {
1883 AllowJavascript();
1884 FireWebUIListener("sent-csbrr-update", base::Value(SerializeCSBRR(*csbrr)));
1885 }
1886
NotifyPGEventJsListener(const sync_pb::UserEventSpecifics & event)1887 void SafeBrowsingUIHandler::NotifyPGEventJsListener(
1888 const sync_pb::UserEventSpecifics& event) {
1889 AllowJavascript();
1890 FireWebUIListener("sent-pg-event", SerializePGEvent(event));
1891 }
1892
NotifySecurityEventJsListener(const sync_pb::GaiaPasswordReuse & event)1893 void SafeBrowsingUIHandler::NotifySecurityEventJsListener(
1894 const sync_pb::GaiaPasswordReuse& event) {
1895 AllowJavascript();
1896 FireWebUIListener("sent-security-event", SerializeSecurityEvent(event));
1897 }
1898
NotifyPGPingJsListener(int token,const LoginReputationClientRequest & request)1899 void SafeBrowsingUIHandler::NotifyPGPingJsListener(
1900 int token,
1901 const LoginReputationClientRequest& request) {
1902 base::ListValue request_list;
1903 request_list.Append(base::Value(token));
1904 request_list.Append(base::Value(SerializePGPing(request)));
1905
1906 AllowJavascript();
1907 FireWebUIListener("pg-pings-update", request_list);
1908 }
1909
NotifyPGResponseJsListener(int token,const LoginReputationClientResponse & response)1910 void SafeBrowsingUIHandler::NotifyPGResponseJsListener(
1911 int token,
1912 const LoginReputationClientResponse& response) {
1913 base::ListValue response_list;
1914 response_list.Append(base::Value(token));
1915 response_list.Append(base::Value(SerializePGResponse(response)));
1916
1917 AllowJavascript();
1918 FireWebUIListener("pg-responses-update", response_list);
1919 }
1920
NotifyRTLookupPingJsListener(int token,const RTLookupRequest & request)1921 void SafeBrowsingUIHandler::NotifyRTLookupPingJsListener(
1922 int token,
1923 const RTLookupRequest& request) {
1924 base::ListValue request_list;
1925 request_list.Append(base::Value(token));
1926 request_list.Append(base::Value(SerializeRTLookupPing(request)));
1927
1928 AllowJavascript();
1929 FireWebUIListener("rt-lookup-pings-update", request_list);
1930 }
1931
NotifyRTLookupResponseJsListener(int token,const RTLookupResponse & response)1932 void SafeBrowsingUIHandler::NotifyRTLookupResponseJsListener(
1933 int token,
1934 const RTLookupResponse& response) {
1935 base::ListValue response_list;
1936 response_list.Append(base::Value(token));
1937 response_list.Append(base::Value(SerializeRTLookupResponse(response)));
1938
1939 AllowJavascript();
1940 FireWebUIListener("rt-lookup-responses-update", response_list);
1941 }
1942
NotifyLogMessageJsListener(const base::Time & timestamp,const std::string & message)1943 void SafeBrowsingUIHandler::NotifyLogMessageJsListener(
1944 const base::Time& timestamp,
1945 const std::string& message) {
1946 AllowJavascript();
1947 FireWebUIListener("log-messages-update",
1948 base::Value(SerializeLogMessage(timestamp, message)));
1949 }
1950
NotifyReportingEventJsListener(const base::Value & event)1951 void SafeBrowsingUIHandler::NotifyReportingEventJsListener(
1952 const base::Value& event) {
1953 AllowJavascript();
1954 FireWebUIListener("reporting-events-update", SerializeReportingEvent(event));
1955 }
1956
1957 #if BUILDFLAG(FULL_SAFE_BROWSING)
NotifyDeepScanRequestJsListener(const DeepScanningClientRequest & request)1958 void SafeBrowsingUIHandler::NotifyDeepScanRequestJsListener(
1959 const DeepScanningClientRequest& request) {
1960 base::ListValue request_list;
1961 request_list.Append(base::Value(request.request_token()));
1962 request_list.Append(base::Value(SerializeDeepScanningRequest(request)));
1963
1964 AllowJavascript();
1965 FireWebUIListener("deep-scan-request-update", request_list);
1966 }
1967
NotifyDeepScanResponseJsListener(const std::string & token,const std::string & status,const DeepScanningClientResponse & response)1968 void SafeBrowsingUIHandler::NotifyDeepScanResponseJsListener(
1969 const std::string& token,
1970 const std::string& status,
1971 const DeepScanningClientResponse& response) {
1972 base::ListValue response_list;
1973 response_list.Append(base::Value(token));
1974 response_list.Append(base::Value(status));
1975 response_list.Append(base::Value(SerializeDeepScanningResponse(response)));
1976
1977 AllowJavascript();
1978 FireWebUIListener("deep-scan-response-update", response_list);
1979 }
1980 #endif
1981
RegisterMessages()1982 void SafeBrowsingUIHandler::RegisterMessages() {
1983 web_ui()->RegisterMessageCallback(
1984 "getExperiments",
1985 base::BindRepeating(&SafeBrowsingUIHandler::GetExperiments,
1986 base::Unretained(this)));
1987 web_ui()->RegisterMessageCallback(
1988 "getPrefs", base::BindRepeating(&SafeBrowsingUIHandler::GetPrefs,
1989 base::Unretained(this)));
1990 web_ui()->RegisterMessageCallback(
1991 "getCookie", base::BindRepeating(&SafeBrowsingUIHandler::GetCookie,
1992 base::Unretained(this)));
1993 web_ui()->RegisterMessageCallback(
1994 "getSavedPasswords",
1995 base::BindRepeating(&SafeBrowsingUIHandler::GetSavedPasswords,
1996 base::Unretained(this)));
1997 web_ui()->RegisterMessageCallback(
1998 "getDatabaseManagerInfo",
1999 base::BindRepeating(&SafeBrowsingUIHandler::GetDatabaseManagerInfo,
2000 base::Unretained(this)));
2001 web_ui()->RegisterMessageCallback(
2002 "getSentClientDownloadRequests",
2003 base::BindRepeating(&SafeBrowsingUIHandler::GetSentClientDownloadRequests,
2004 base::Unretained(this)));
2005 web_ui()->RegisterMessageCallback(
2006 "getReceivedClientDownloadResponses",
2007 base::BindRepeating(
2008 &SafeBrowsingUIHandler::GetReceivedClientDownloadResponses,
2009 base::Unretained(this)));
2010 web_ui()->RegisterMessageCallback(
2011 "getSentCSBRRs",
2012 base::BindRepeating(&SafeBrowsingUIHandler::GetSentCSBRRs,
2013 base::Unretained(this)));
2014 web_ui()->RegisterMessageCallback(
2015 "getPGEvents", base::BindRepeating(&SafeBrowsingUIHandler::GetPGEvents,
2016 base::Unretained(this)));
2017 web_ui()->RegisterMessageCallback(
2018 "getSecurityEvents",
2019 base::BindRepeating(&SafeBrowsingUIHandler::GetSecurityEvents,
2020 base::Unretained(this)));
2021 web_ui()->RegisterMessageCallback(
2022 "getPGPings", base::BindRepeating(&SafeBrowsingUIHandler::GetPGPings,
2023 base::Unretained(this)));
2024 web_ui()->RegisterMessageCallback(
2025 "getPGResponses",
2026 base::BindRepeating(&SafeBrowsingUIHandler::GetPGResponses,
2027 base::Unretained(this)));
2028 web_ui()->RegisterMessageCallback(
2029 "getRTLookupPings",
2030 base::BindRepeating(&SafeBrowsingUIHandler::GetRTLookupPings,
2031 base::Unretained(this)));
2032 web_ui()->RegisterMessageCallback(
2033 "getRTLookupResponses",
2034 base::BindRepeating(&SafeBrowsingUIHandler::GetRTLookupResponses,
2035 base::Unretained(this)));
2036 web_ui()->RegisterMessageCallback(
2037 "getRTLookupExperimentEnabled",
2038 base::BindRepeating(&SafeBrowsingUIHandler::GetRTLookupExperimentEnabled,
2039 base::Unretained(this)));
2040 web_ui()->RegisterMessageCallback(
2041 "getLogMessages",
2042 base::BindRepeating(&SafeBrowsingUIHandler::GetLogMessages,
2043 base::Unretained(this)));
2044 web_ui()->RegisterMessageCallback(
2045 "getReferrerChain",
2046 base::BindRepeating(&SafeBrowsingUIHandler::GetReferrerChain,
2047 base::Unretained(this)));
2048 web_ui()->RegisterMessageCallback(
2049 "getReportingEvents",
2050 base::BindRepeating(&SafeBrowsingUIHandler::GetReportingEvents,
2051 base::Unretained(this)));
2052 #if BUILDFLAG(FULL_SAFE_BROWSING)
2053 web_ui()->RegisterMessageCallback(
2054 "getDeepScanRequests",
2055 base::BindRepeating(&SafeBrowsingUIHandler::GetDeepScanRequests,
2056 base::Unretained(this)));
2057 web_ui()->RegisterMessageCallback(
2058 "getDeepScanResponses",
2059 base::BindRepeating(&SafeBrowsingUIHandler::GetDeepScanResponses,
2060 base::Unretained(this)));
2061 #endif
2062 }
2063
SetWebUIForTesting(content::WebUI * web_ui)2064 void SafeBrowsingUIHandler::SetWebUIForTesting(content::WebUI* web_ui) {
2065 set_web_ui(web_ui);
2066 }
2067
CrSBLogMessage()2068 CrSBLogMessage::CrSBLogMessage() {}
2069
~CrSBLogMessage()2070 CrSBLogMessage::~CrSBLogMessage() {
2071 WebUIInfoSingleton::GetInstance()->LogMessage(stream_.str());
2072 DLOG(WARNING) << stream_.str();
2073 }
2074
2075 } // namespace safe_browsing
2076