Commit 7b0c35e4 authored by Dominique Fauteux-Chapleau's avatar Dominique Fauteux-Chapleau Committed by Commit Bot

Add ContentAnalysis{Request|Response} support in BinaryUploadService

This also updates the WebUI calls since BinaryUploadService is where
the chrome://safe-browsing page gets its updates.

Follow-ups to this CL
will be updates to DeepScanning{DialogDelegate|Request} to use the new
Connector proto path.

Bug: 1069066,1069069
Change-Id: I170384dc8fee55e239996b623fab672e56c5810a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2243441
Commit-Queue: Dominique Fauteux-Chapleau <domfc@chromium.org>
Reviewed-by: default avatarDaniel Rubery <drubery@chromium.org>
Cr-Commit-Position: refs/heads/master@{#780013}
parent 0c936856
......@@ -4,6 +4,7 @@
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h"
#include <algorithm>
#include <memory>
#include <utility>
......@@ -23,6 +24,7 @@
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h"
#include "chrome/browser/safe_browsing/cloud_content_scanning/multipart_uploader.h"
#include "chrome/browser/safe_browsing/dm_token_utils.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/prefs/pref_service.h"
#include "components/safe_browsing/content/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h"
......@@ -43,10 +45,16 @@ const char kSbAppUploadUrl[] =
"https://safebrowsing.google.com/safebrowsing/uploads/app";
bool IsAdvancedProtectionRequest(const BinaryUploadService::Request& request) {
return !request.deep_scanning_request().has_dlp_scan_request() &&
request.deep_scanning_request().has_malware_scan_request() &&
request.deep_scanning_request().malware_scan_request().population() ==
MalwareDeepScanningClientRequest::POPULATION_TITANIUM;
if (request.use_legacy_proto()) {
return !request.deep_scanning_request().has_dlp_scan_request() &&
request.deep_scanning_request().has_malware_scan_request() &&
request.deep_scanning_request()
.malware_scan_request()
.population() ==
MalwareDeepScanningClientRequest::POPULATION_TITANIUM;
} else {
return request.device_token().empty();
}
}
std::string ResultToString(BinaryUploadService::Result result) {
......@@ -126,7 +134,7 @@ void BinaryUploadService::MaybeUploadForDeepScanningCallback(
if (!authorized) {
// TODO(crbug/1028133): Add extra logic to handle UX for non-authorized
// users.
request->FinishRequest(Result::UNAUTHORIZED, DeepScanningClientResponse());
request->FinishRequest(Result::UNAUTHORIZED);
return;
}
UploadForDeepScanning(std::move(request));
......@@ -149,14 +157,19 @@ void BinaryUploadService::UploadForDeepScanning(
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&BinaryUploadService::FinishRequest,
weakptr_factory_.GetWeakPtr(), raw_request,
Result::FAILED_TO_GET_TOKEN,
DeepScanningClientResponse()));
Result::FAILED_TO_GET_TOKEN));
return;
}
binary_fcm_service_->SetCallbackForToken(
token, base::BindRepeating(&BinaryUploadService::OnGetResponse,
weakptr_factory_.GetWeakPtr(), raw_request));
if (raw_request->use_legacy_proto()) {
binary_fcm_service_->SetCallbackForToken(
token, base::BindRepeating(&BinaryUploadService::OnGetLegacyResponse,
weakptr_factory_.GetWeakPtr(), raw_request));
} else {
binary_fcm_service_->SetCallbackForToken(
token, base::BindRepeating(&BinaryUploadService::OnGetConnectorResponse,
weakptr_factory_.GetWeakPtr(), raw_request));
}
binary_fcm_service_->GetInstanceID(
base::BindOnce(&BinaryUploadService::OnGetInstanceID,
weakptr_factory_.GetWeakPtr(), raw_request));
......@@ -173,8 +186,7 @@ void BinaryUploadService::OnGetInstanceID(Request* request,
return;
if (instance_id == BinaryFCMService::kInvalidId) {
FinishRequest(request, Result::FAILED_TO_GET_TOKEN,
DeepScanningClientResponse());
FinishRequest(request, Result::FAILED_TO_GET_TOKEN);
return;
}
......@@ -197,7 +209,7 @@ void BinaryUploadService::OnGetRequestData(Request* request,
return;
if (result != Result::SUCCESS) {
FinishRequest(request, result, DeepScanningClientResponse());
FinishRequest(request, result);
return;
}
......@@ -240,7 +252,7 @@ void BinaryUploadService::OnGetRequestData(Request* request,
)");
std::string metadata;
request->deep_scanning_request().SerializeToString(&metadata);
request->SerializeToString(&metadata);
base::Base64Encode(metadata, &metadata);
GURL url = request->url().is_valid()
......@@ -251,11 +263,19 @@ void BinaryUploadService::OnGetRequestData(Request* request,
traffic_annotation,
base::BindOnce(&BinaryUploadService::OnUploadComplete,
weakptr_factory_.GetWeakPtr(), request));
if (request->use_legacy_proto()) {
WebUIInfoSingleton::GetInstance()->AddToDeepScanRequests(
request->deep_scanning_request());
} else {
WebUIInfoSingleton::GetInstance()->AddToDeepScanRequests(
request->content_analysis_request());
}
// |request| might have been deleted by the call to Start() in tests, so don't
// dereference it afterwards.
upload_request->Start();
active_uploads_[request] = std::move(upload_request);
WebUIInfoSingleton::GetInstance()->AddToDeepScanRequests(
request->deep_scanning_request());
}
void BinaryUploadService::OnUploadComplete(Request* request,
......@@ -265,53 +285,112 @@ void BinaryUploadService::OnUploadComplete(Request* request,
return;
if (!success) {
FinishRequest(request, Result::UPLOAD_FAILURE,
DeepScanningClientResponse());
FinishRequest(request, Result::UPLOAD_FAILURE);
return;
}
DeepScanningClientResponse response;
if (!response.ParseFromString(response_data)) {
FinishRequest(request, Result::UPLOAD_FAILURE,
DeepScanningClientResponse());
return;
if (request->use_legacy_proto()) {
DeepScanningClientResponse response;
if (!response.ParseFromString(response_data)) {
FinishRequest(request, Result::UPLOAD_FAILURE);
return;
}
active_uploads_.erase(request);
// Synchronous scans can return results in the initial response proto, so
// check for those.
OnGetLegacyResponse(request, response);
} else {
enterprise_connectors::ContentAnalysisResponse response;
if (!response.ParseFromString(response_data)) {
FinishRequest(request, Result::UPLOAD_FAILURE);
return;
}
active_uploads_.erase(request);
// Synchronous scans can return results in the initial response proto, so
// check for those.
OnGetConnectorResponse(request, response);
}
}
active_uploads_.erase(request);
void BinaryUploadService::OnGetConnectorResponse(
Request* request,
enterprise_connectors::ContentAnalysisResponse response) {
if (!IsActive(request))
return;
// Synchronous scans can return results in the initial response proto, so
// check for those.
OnGetResponse(request, response);
for (const auto& result : response.results()) {
if (result.has_tag() && !result.tag().empty()) {
VLOG(1) << "Request " << request->request_token()
<< " finished scanning tag <" << result.tag() << ">";
*received_connector_responses_[request].add_results() = result;
}
}
MaybeFinishConnectorRequest(request);
}
void BinaryUploadService::OnGetResponse(Request* request,
DeepScanningClientResponse response) {
void BinaryUploadService::OnGetLegacyResponse(
Request* request,
DeepScanningClientResponse response) {
if (!IsActive(request))
return;
if (response.has_dlp_scan_verdict()) {
VLOG(1) << "Request " << request->deep_scanning_request().request_token()
VLOG(1) << "Request " << request->request_token()
<< " finished DLP scanning";
received_dlp_verdicts_[request].reset(response.release_dlp_scan_verdict());
}
if (response.has_malware_scan_verdict()) {
VLOG(1) << "Request " << request->deep_scanning_request().request_token()
VLOG(1) << "Request " << request->request_token()
<< " finished malware scanning";
received_malware_verdicts_[request].reset(
response.release_malware_scan_verdict());
}
MaybeFinishRequest(request);
MaybeFinishLegacyRequest(request);
}
void BinaryUploadService::MaybeFinishRequest(Request* request) {
if (request->use_legacy_proto())
MaybeFinishLegacyRequest(request);
else
MaybeFinishConnectorRequest(request);
}
void BinaryUploadService::MaybeFinishConnectorRequest(Request* request) {
if (!received_connector_responses_.contains(request))
return;
for (const std::string& tag : request->content_analysis_request().tags()) {
const auto& results = received_connector_responses_[request].results();
if (std::none_of(
results.begin(), results.end(),
[&tag](const auto& result) { return result.tag() == tag; })) {
VLOG(1) << "Request " << request->request_token() << " is waiting for <"
<< tag << "> scanning to complete.";
return;
}
}
// It's OK to move here since the map entry is about to be removed.
enterprise_connectors::ContentAnalysisResponse response =
std::move(received_connector_responses_[request]);
response.set_request_token(request->request_token());
FinishConnectorRequest(request, Result::SUCCESS, std::move(response));
}
void BinaryUploadService::MaybeFinishLegacyRequest(Request* request) {
bool requested_dlp_scan_response =
request->deep_scanning_request().has_dlp_scan_request();
auto received_dlp_response = received_dlp_verdicts_.find(request);
if (requested_dlp_scan_response &&
received_dlp_response == received_dlp_verdicts_.end()) {
VLOG(1) << "Request " << request->deep_scanning_request().request_token()
VLOG(1) << "Request " << request->request_token()
<< " is waiting for DLP scanning to complete.";
return;
}
......@@ -321,13 +400,13 @@ void BinaryUploadService::MaybeFinishRequest(Request* request) {
auto received_malware_response = received_malware_verdicts_.find(request);
if (requested_malware_scan_response &&
received_malware_response == received_malware_verdicts_.end()) {
VLOG(1) << "Request " << request->deep_scanning_request().request_token()
VLOG(1) << "Request " << request->request_token()
<< " is waiting for malware scanning to complete.";
return;
}
DeepScanningClientResponse response;
response.set_token(request->deep_scanning_request().request_token());
response.set_token(request->request_token());
if (requested_dlp_scan_response) {
// Transfers ownership of the DLP response to |response|.
response.set_allocated_dlp_scan_verdict(
......@@ -340,17 +419,45 @@ void BinaryUploadService::MaybeFinishRequest(Request* request) {
received_malware_response->second.release());
}
FinishRequest(request, Result::SUCCESS, std::move(response));
FinishLegacyRequest(request, Result::SUCCESS, std::move(response));
}
void BinaryUploadService::OnTimeout(Request* request) {
if (IsActive(request))
FinishRequest(request, Result::TIMEOUT, DeepScanningClientResponse());
FinishRequest(request, Result::TIMEOUT);
}
void BinaryUploadService::FinishRequest(Request* request, Result result) {
if (request->use_legacy_proto()) {
FinishLegacyRequest(request, result, DeepScanningClientResponse());
} else {
FinishConnectorRequest(request, result,
enterprise_connectors::ContentAnalysisResponse());
}
}
void BinaryUploadService::FinishConnectorRequest(
Request* request,
Result result,
enterprise_connectors::ContentAnalysisResponse response) {
RecordRequestMetrics(request, result, response);
// We add the request here in case we never actually uploaded anything, so it
// wasn't added in OnGetRequestData
WebUIInfoSingleton::GetInstance()->AddToDeepScanRequests(
request->content_analysis_request());
WebUIInfoSingleton::GetInstance()->AddToDeepScanResponses(
active_tokens_[request], ResultToString(result), response);
std::string instance_id = request->fcm_notification_token();
request->FinishConnectorRequest(result, response);
FinishRequestCleanup(request, instance_id);
}
void BinaryUploadService::FinishRequest(Request* request,
Result result,
DeepScanningClientResponse response) {
void BinaryUploadService::FinishLegacyRequest(
Request* request,
Result result,
DeepScanningClientResponse response) {
RecordRequestMetrics(request, result, response);
// We add the request here in case we never actually uploaded anything, so it
......@@ -360,15 +467,19 @@ void BinaryUploadService::FinishRequest(Request* request,
WebUIInfoSingleton::GetInstance()->AddToDeepScanResponses(
active_tokens_[request], ResultToString(result), response);
std::string instance_id =
request->deep_scanning_request().fcm_notification_token();
std::string instance_id = request->fcm_notification_token();
request->FinishLegacyRequest(result, response);
FinishRequestCleanup(request, instance_id);
}
request->FinishRequest(result, response);
void BinaryUploadService::FinishRequestCleanup(Request* request,
const std::string& instance_id) {
active_requests_.erase(request);
active_timers_.erase(request);
active_uploads_.erase(request);
received_malware_verdicts_.erase(request);
received_dlp_verdicts_.erase(request);
received_connector_responses_.erase(request);
auto token_it = active_tokens_.find(request);
DCHECK(token_it != active_tokens_.end());
......@@ -401,17 +512,42 @@ void BinaryUploadService::InstanceIDUnregisteredCallback(bool) {
}
}
void BinaryUploadService::RecordRequestMetrics(
Request* request,
Result result,
const DeepScanningClientResponse& response) {
void BinaryUploadService::RecordRequestMetrics(Request* request,
Result result) {
base::UmaHistogramEnumeration("SafeBrowsingBinaryUploadRequest.Result",
result);
base::UmaHistogramCustomTimes("SafeBrowsingBinaryUploadRequest.Duration",
base::TimeTicks::Now() - start_times_[request],
base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(6), 50);
}
void BinaryUploadService::RecordRequestMetrics(
Request* request,
Result result,
const enterprise_connectors::ContentAnalysisResponse& response) {
RecordRequestMetrics(request, result);
for (const auto& result : response.results()) {
if (result.tag() == "malware") {
base::UmaHistogramBoolean(
"SafeBrowsingBinaryUploadRequest.MalwareResult",
result.status() !=
enterprise_connectors::ContentAnalysisResponse::Result::FAILURE);
}
if (result.tag() == "dlp") {
base::UmaHistogramBoolean(
"SafeBrowsingBinaryUploadRequest.DlpResult",
result.status() !=
enterprise_connectors::ContentAnalysisResponse::Result::FAILURE);
}
}
}
void BinaryUploadService::RecordRequestMetrics(
Request* request,
Result result,
const DeepScanningClientResponse& response) {
RecordRequestMetrics(request, result);
if (response.has_malware_scan_verdict()) {
base::UmaHistogramBoolean("SafeBrowsingBinaryUploadRequest.MalwareResult",
response.malware_scan_verdict().verdict() !=
......@@ -442,11 +578,13 @@ BinaryUploadService::Request::~Request() = default;
void BinaryUploadService::Request::set_request_dlp_scan(
DlpDeepScanningClientRequest dlp_request) {
DCHECK(use_legacy_proto_);
*deep_scanning_request_.mutable_dlp_scan_request() = std::move(dlp_request);
}
void BinaryUploadService::Request::set_request_malware_scan(
MalwareDeepScanningClientRequest malware_request) {
DCHECK(use_legacy_proto_);
*deep_scanning_request_.mutable_malware_scan_request() =
std::move(malware_request);
}
......@@ -487,33 +625,83 @@ void BinaryUploadService::Request::set_digest(const std::string& digest) {
}
void BinaryUploadService::Request::clear_dlp_scan_request() {
DCHECK(use_legacy_proto_);
deep_scanning_request_.clear_dlp_scan_request();
}
void BinaryUploadService::Request::set_analysis_connector(
enterprise_connectors::AnalysisConnector connector) {
DCHECK(!use_legacy_proto_);
content_analysis_request_.set_analysis_connector(connector);
}
void BinaryUploadService::Request::set_url(const std::string& url) {
DCHECK(!use_legacy_proto_);
content_analysis_request_.mutable_request_data()->set_url(url);
}
void BinaryUploadService::Request::set_csd(ClientDownloadRequest csd) {
DCHECK(!use_legacy_proto_);
*content_analysis_request_.mutable_request_data()->mutable_csd() =
std::move(csd);
}
void BinaryUploadService::Request::add_tag(const std::string& tag) {
DCHECK(!use_legacy_proto_);
content_analysis_request_.add_tags(tag);
}
void BinaryUploadService::Request::FinishRequest(
const std::string& BinaryUploadService::Request::device_token() const {
if (use_legacy_proto_)
return deep_scanning_request_.dm_token();
else
return content_analysis_request_.device_token();
}
const std::string& BinaryUploadService::Request::request_token() const {
if (use_legacy_proto_)
return deep_scanning_request_.request_token();
else
return content_analysis_request_.request_token();
}
const std::string& BinaryUploadService::Request::fcm_notification_token()
const {
if (use_legacy_proto_)
return deep_scanning_request_.fcm_notification_token();
else
return content_analysis_request_.fcm_notification_token();
}
void BinaryUploadService::Request::FinishRequest(Result result) {
if (use_legacy_proto_) {
std::move(callback_).Run(result, DeepScanningClientResponse());
} else {
std::move(content_analysis_callback_)
.Run(result, enterprise_connectors::ContentAnalysisResponse());
}
}
void BinaryUploadService::Request::FinishConnectorRequest(
Result result,
enterprise_connectors::ContentAnalysisResponse response) {
std::move(content_analysis_callback_).Run(result, response);
}
void BinaryUploadService::Request::FinishLegacyRequest(
Result result,
DeepScanningClientResponse response) {
std::move(callback_).Run(result, response);
}
void BinaryUploadService::Request::SerializeToString(
std::string* destination) const {
if (use_legacy_proto_)
deep_scanning_request_.SerializeToString(destination);
else
content_analysis_request_.SerializeToString(destination);
}
bool BinaryUploadService::IsActive(Request* request) {
return (active_requests_.find(request) != active_requests_.end());
}
......
......@@ -137,7 +137,13 @@ class BinaryUploadService : public KeyedService {
// Returns the URL to send the request to.
const GURL& url() const { return url_; }
bool use_legacy_proto() { return use_legacy_proto_; }
// Returns the metadata to upload, as a ContentAnalysisRequest.
const enterprise_connectors::ContentAnalysisRequest&
content_analysis_request() const {
return content_analysis_request_;
}
bool use_legacy_proto() const { return use_legacy_proto_; }
// Methods for modifying the DeepScanningClientRequest.
void set_request_dlp_scan(DlpDeepScanningClientRequest dlp_request);
......@@ -159,9 +165,22 @@ class BinaryUploadService : public KeyedService {
void set_filename(const std::string& filename);
void set_digest(const std::string& digest);
// Methods for accessing either internal proto requests.
const std::string& device_token() const;
const std::string& request_token() const;
const std::string& fcm_notification_token() const;
// Finish the request, with the given |result| and |response| from the
// server.
void FinishRequest(Result result, DeepScanningClientResponse response);
void FinishRequest(Result result);
void FinishConnectorRequest(
Result result,
enterprise_connectors::ContentAnalysisResponse response);
void FinishLegacyRequest(Result result,
DeepScanningClientResponse response);
// Calls SerializeToString on the appropriate proto request.
void SerializeToString(std::string* destination) const;
private:
const bool use_legacy_proto_;
......@@ -200,9 +219,14 @@ class BinaryUploadService : public KeyedService {
static GURL GetUploadUrl(bool is_advanced_protection_request);
protected:
void FinishRequest(Request* request,
Result result,
DeepScanningClientResponse response);
void FinishRequest(Request* request, Result result);
void FinishConnectorRequest(
Request* request,
Result result,
enterprise_connectors::ContentAnalysisResponse response);
void FinishLegacyRequest(Request* request,
Result result,
DeepScanningClientResponse response);
private:
friend class BinaryUploadServiceTest;
......@@ -222,9 +246,15 @@ class BinaryUploadService : public KeyedService {
bool success,
const std::string& response_data);
void OnGetResponse(Request* request, DeepScanningClientResponse response);
void OnGetConnectorResponse(
Request* request,
enterprise_connectors::ContentAnalysisResponse response);
void OnGetLegacyResponse(Request* request,
DeepScanningClientResponse response);
void MaybeFinishRequest(Request* request);
void MaybeFinishConnectorRequest(Request* request);
void MaybeFinishLegacyRequest(Request* request);
void OnTimeout(Request* request);
......@@ -240,10 +270,18 @@ class BinaryUploadService : public KeyedService {
// Callback once a request's instance ID is unregistered.
void InstanceIDUnregisteredCallback(bool);
void RecordRequestMetrics(Request* request, Result result);
void RecordRequestMetrics(
Request* request,
Result result,
const enterprise_connectors::ContentAnalysisResponse& response);
void RecordRequestMetrics(Request* request,
Result result,
const DeepScanningClientResponse& response);
// Called at the end of either Finish{Connector|Legacy}Request methods.
void FinishRequestCleanup(Request* request, const std::string& instance_id);
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<BinaryFCMService> binary_fcm_service_;
......@@ -261,6 +299,10 @@ class BinaryUploadService : public KeyedService {
base::flat_map<Request*, std::unique_ptr<DlpDeepScanningVerdict>>
received_dlp_verdicts_;
// Maps requests to each tag-result pair.
base::flat_map<Request*, enterprise_connectors::ContentAnalysisResponse>
received_connector_responses_;
// Indicates whether this browser can upload data for enterprise requests.
// Advanced Protection scans are validated using the user's Advanced
// Protection enrollment status.
......
......@@ -142,7 +142,7 @@ class BinaryUploadServiceTest : public testing::Test {
void ReceiveMessageForRequest(BinaryUploadService::Request* request,
const DeepScanningClientResponse& response) {
service_->OnGetResponse(request, response);
service_->OnGetLegacyResponse(request, response);
}
void ReceiveResponseFromUpload(BinaryUploadService::Request* request,
......
......@@ -671,7 +671,7 @@ void DeepScanningDialogDelegate::OnGotFileInfo(
// property (too large, unsupported file type, encrypted, ...) that make its
// upload pointless, so the request should finish early.
if (result != BinaryUploadService::Result::SUCCESS) {
request->FinishRequest(result, DeepScanningClientResponse());
request->FinishRequest(result);
return;
}
......
......@@ -46,8 +46,7 @@ class FakeBinaryUploadService : public BinaryUploadService {
// Finish the authentication request. Called after ShowForWebContents to
// simulate an async callback.
void ReturnAuthorizedResponse() {
FinishRequest(authorization_request_.get(), authorization_result_,
DeepScanningClientResponse());
FinishRequest(authorization_request_.get(), authorization_result_);
}
void SetResponseForText(BinaryUploadService::Result result,
......@@ -80,12 +79,13 @@ class FakeBinaryUploadService : public BinaryUploadService {
} else {
std::string file = request->deep_scanning_request().filename();
if (file.empty()) {
request->FinishRequest(prepared_text_result_, prepared_text_response_);
request->FinishLegacyRequest(prepared_text_result_,
prepared_text_response_);
} else {
ASSERT_TRUE(prepared_file_results_.count(file));
ASSERT_TRUE(prepared_file_responses_.count(file));
request->FinishRequest(prepared_file_results_[file],
prepared_file_responses_[file]);
request->FinishLegacyRequest(prepared_file_results_[file],
prepared_file_responses_[file]);
}
}
}
......
......@@ -19,8 +19,9 @@ void TestBinaryUploadService::MaybeUploadForDeepScanning(
std::unique_ptr<Request> request) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&Request::FinishRequest, std::move(request),
saved_result_, saved_response_));
FROM_HERE,
base::BindOnce(&Request::FinishLegacyRequest, std::move(request),
saved_result_, saved_response_));
was_called_ = true;
}
......
......@@ -67,7 +67,7 @@ class FakeBinaryUploadService : public BinaryUploadService {
void MaybeUploadForDeepScanning(std::unique_ptr<Request> request) override {
last_request_ = request->deep_scanning_request();
request->FinishRequest(saved_result_, saved_response_);
request->FinishLegacyRequest(saved_result_, saved_response_);
}
void SetResponse(BinaryUploadService::Result result,
......
......@@ -12,6 +12,7 @@ static_library("web_ui") {
deps = [
"//base",
"//components/enterprise/common/proto:connectors_proto",
"//components/password_manager/core/browser:hash_password_manager",
"//components/resources:components_resources_grit",
"//components/resources:components_scaled_resources_grit",
......
include_rules = [
"+components/enterprise/common/proto/connectors.pb.h",
"+components/grit/components_resources.h",
"+components/password_manager/core/browser/hash_password_manager.h",
"+components/user_prefs",
......
......@@ -24,6 +24,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "base/values.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/grit/components_resources.h"
#include "components/grit/components_scaled_resources.h"
#include "components/password_manager/core/browser/hash_password_manager.h"
......@@ -271,6 +272,26 @@ void WebUIInfoSingleton::AddToDeepScanRequests(
request.request_token(), deep_scan_requests_[request.request_token()]);
}
void WebUIInfoSingleton::AddToDeepScanRequests(
const enterprise_connectors::ContentAnalysisRequest& request) {
if (!HasListener())
return;
// Only update the request time the first time we see a token.
if (deep_scan_requests_.find(request.request_token()) ==
deep_scan_requests_.end()) {
deep_scan_requests_[request.request_token()].request_time =
base::Time::Now();
}
deep_scan_requests_[request.request_token()].content_analysis_request =
request;
for (auto* webui_listener : webui_instances_)
webui_listener->NotifyDeepScanJsListener(
request.request_token(), deep_scan_requests_[request.request_token()]);
}
void WebUIInfoSingleton::AddToDeepScanResponses(
const std::string& token,
const std::string& status,
......@@ -286,6 +307,21 @@ void WebUIInfoSingleton::AddToDeepScanResponses(
webui_listener->NotifyDeepScanJsListener(token, deep_scan_requests_[token]);
}
void WebUIInfoSingleton::AddToDeepScanResponses(
const std::string& token,
const std::string& status,
const enterprise_connectors::ContentAnalysisResponse& response) {
if (!HasListener())
return;
deep_scan_requests_[token].response_time = base::Time::Now();
deep_scan_requests_[token].response_status = status;
deep_scan_requests_[token].content_analysis_response = response;
for (auto* webui_listener : webui_instances_)
webui_listener->NotifyDeepScanJsListener(token, deep_scan_requests_[token]);
}
void WebUIInfoSingleton::ClearDeepScans() {
base::flat_map<std::string, DeepScanDebugData>().swap(deep_scan_requests_);
}
......@@ -1303,6 +1339,52 @@ base::Value SerializeReportingEvent(const base::Value& event) {
}
#if BUILDFLAG(FULL_SAFE_BROWSING)
std::string SerializeContentAnalysisRequest(
const enterprise_connectors::ContentAnalysisRequest& request) {
base::DictionaryValue request_dict;
request_dict.SetKey("device_token", base::Value(request.device_token()));
request_dict.SetKey("fcm_notification_token",
base::Value(request.fcm_notification_token()));
switch (request.analysis_connector()) {
case enterprise_connectors::ANALYSIS_CONNECTOR_UNSPECIFIED:
request_dict.SetStringKey("analysis_connector", "UNSPECIFIED");
break;
case enterprise_connectors::FILE_ATTACHED:
request_dict.SetStringKey("analysis_connector", "FILE_ATTACHED");
break;
case enterprise_connectors::FILE_DOWNLOADED:
request_dict.SetStringKey("analysis_connector", "FILE_DOWNLOADED");
break;
case enterprise_connectors::BULK_DATA_ENTRY:
request_dict.SetStringKey("analysis_connector", "BULK_DATA_ENTRY");
break;
}
if (request.has_request_data()) {
base::DictionaryValue request_data;
request_data.SetStringKey("url", request.request_data().url());
request_data.SetStringKey("filename", request.request_data().filename());
request_data.SetStringKey("digest", request.request_data().digest());
// TODO(domfc): Improve this once csd is populated for this proto.
request_data.SetStringKey("csd",
request.request_data().csd().SerializeAsString());
request_dict.SetKey("request_data", std::move(request_data));
}
base::ListValue tags;
for (const std::string& tag : request.tags())
tags.Append(base::Value(tag));
request_dict.SetKey("tags", std::move(tags));
request_dict.SetKey("request_token", base::Value(request.request_token()));
std::string request_serialized;
JSONStringValueSerializer serializer(&request_serialized);
serializer.set_pretty_print(true);
serializer.Serialize(request_dict);
return request_serialized;
}
std::string SerializeDeepScanningRequest(
const DeepScanningClientRequest& request) {
base::DictionaryValue request_dict;
......@@ -1361,6 +1443,68 @@ std::string SerializeDeepScanningRequest(
return request_serialized;
}
std::string SerializeContentAnalysisResponse(
const enterprise_connectors::ContentAnalysisResponse& response) {
base::DictionaryValue response_dict;
response_dict.SetStringKey("token", response.request_token());
base::ListValue result_values;
for (const auto& result : response.results()) {
base::DictionaryValue result_value;
switch (result.status()) {
case enterprise_connectors::ContentAnalysisResponse::Result::
STATUS_UNKNOWN:
result_value.SetStringKey("status", "STATUS_UNKNOWN");
break;
case enterprise_connectors::ContentAnalysisResponse::Result::SUCCESS:
result_value.SetStringKey("status", "SUCCESS");
break;
case enterprise_connectors::ContentAnalysisResponse::Result::FAILURE:
result_value.SetStringKey("status", "FAILURE");
break;
}
result_value.SetStringKey("tag", result.tag());
base::ListValue triggered_rules;
for (const auto& rule : result.triggered_rules()) {
base::DictionaryValue rule_value;
switch (rule.action()) {
case enterprise_connectors::ContentAnalysisResponse::Result::
TriggeredRule::ACTION_UNSPECIFIED:
rule_value.SetStringKey("action", "ACTION_UNSPECIFIED");
break;
case enterprise_connectors::ContentAnalysisResponse::Result::
TriggeredRule::REPORT_ONLY:
rule_value.SetStringKey("action", "REPORT_ONLY");
break;
case enterprise_connectors::ContentAnalysisResponse::Result::
TriggeredRule::WARN:
rule_value.SetStringKey("action", "WARN");
break;
case enterprise_connectors::ContentAnalysisResponse::Result::
TriggeredRule::BLOCK:
rule_value.SetStringKey("action", "BLOCK");
break;
}
rule_value.SetStringKey("rule_name", rule.rule_name());
rule_value.SetStringKey("rule_id", rule.rule_id());
triggered_rules.Append(std::move(rule_value));
}
result_value.SetKey("triggered_rules", std::move(triggered_rules));
result_values.Append(std::move(result_value));
}
response_dict.SetKey("results", std::move(result_values));
std::string response_serialized;
JSONStringValueSerializer serializer(&response_serialized);
serializer.set_pretty_print(true);
serializer.Serialize(response_dict);
return response_serialized;
}
std::string SerializeDeepScanningResponse(
const DeepScanningClientResponse& response) {
base::DictionaryValue response_dict;
......@@ -1470,6 +1614,9 @@ base::Value SerializeDeepScanDebugData(const std::string& token,
if (data.request.has_value()) {
value.SetStringKey("request",
SerializeDeepScanningRequest(data.request.value()));
} else if (data.content_analysis_request.has_value()) {
value.SetStringKey("request", SerializeContentAnalysisRequest(
data.content_analysis_request.value()));
}
if (!data.response_time.is_null()) {
......@@ -1483,6 +1630,9 @@ base::Value SerializeDeepScanDebugData(const std::string& token,
if (data.response.has_value()) {
value.SetStringKey("response",
SerializeDeepScanningResponse(data.response.value()));
} else if (data.content_analysis_response.has_value()) {
value.SetStringKey("response", SerializeContentAnalysisResponse(
data.content_analysis_response.value()));
}
return std::move(value);
......
......@@ -7,6 +7,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/core/browser/safe_browsing_network_context.h"
#include "components/safe_browsing/core/proto/csd.pb.h"
......@@ -42,10 +43,14 @@ struct DeepScanDebugData {
base::Time request_time;
base::Optional<DeepScanningClientRequest> request;
base::Optional<enterprise_connectors::ContentAnalysisRequest>
content_analysis_request;
base::Time response_time;
std::string response_status;
base::Optional<DeepScanningClientResponse> response;
base::Optional<enterprise_connectors::ContentAnalysisResponse>
content_analysis_response;
};
#endif
......@@ -327,12 +332,18 @@ class WebUIInfoSingleton {
// identifier that can be used in |AddToDeepScanResponses| to correlate a ping
// and response.
void AddToDeepScanRequests(const DeepScanningClientRequest& request);
void AddToDeepScanRequests(
const enterprise_connectors::ContentAnalysisRequest& request);
// Add the new response to |deep_scan_requests_| and send it to all the open
// chrome://safe-browsing tabs.
void AddToDeepScanResponses(const std::string& token,
const std::string& status,
const DeepScanningClientResponse& response);
void AddToDeepScanResponses(
const std::string& token,
const std::string& status,
const enterprise_connectors::ContentAnalysisResponse& response);
// Clear the list of deep scan requests and responses.
void ClearDeepScans();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment