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 @@ ...@@ -4,6 +4,7 @@
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h"
#include <algorithm>
#include <memory> #include <memory>
#include <utility> #include <utility>
...@@ -23,6 +24,7 @@ ...@@ -23,6 +24,7 @@
#include "chrome/browser/safe_browsing/cloud_content_scanning/binary_fcm_service.h" #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/cloud_content_scanning/multipart_uploader.h"
#include "chrome/browser/safe_browsing/dm_token_utils.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/prefs/pref_service.h"
#include "components/safe_browsing/content/web_ui/safe_browsing_ui.h" #include "components/safe_browsing/content/web_ui/safe_browsing_ui.h"
#include "components/safe_browsing/core/common/safe_browsing_prefs.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h"
...@@ -43,10 +45,16 @@ const char kSbAppUploadUrl[] = ...@@ -43,10 +45,16 @@ const char kSbAppUploadUrl[] =
"https://safebrowsing.google.com/safebrowsing/uploads/app"; "https://safebrowsing.google.com/safebrowsing/uploads/app";
bool IsAdvancedProtectionRequest(const BinaryUploadService::Request& request) { bool IsAdvancedProtectionRequest(const BinaryUploadService::Request& request) {
return !request.deep_scanning_request().has_dlp_scan_request() && if (request.use_legacy_proto()) {
request.deep_scanning_request().has_malware_scan_request() && return !request.deep_scanning_request().has_dlp_scan_request() &&
request.deep_scanning_request().malware_scan_request().population() == request.deep_scanning_request().has_malware_scan_request() &&
MalwareDeepScanningClientRequest::POPULATION_TITANIUM; request.deep_scanning_request()
.malware_scan_request()
.population() ==
MalwareDeepScanningClientRequest::POPULATION_TITANIUM;
} else {
return request.device_token().empty();
}
} }
std::string ResultToString(BinaryUploadService::Result result) { std::string ResultToString(BinaryUploadService::Result result) {
...@@ -126,7 +134,7 @@ void BinaryUploadService::MaybeUploadForDeepScanningCallback( ...@@ -126,7 +134,7 @@ void BinaryUploadService::MaybeUploadForDeepScanningCallback(
if (!authorized) { if (!authorized) {
// TODO(crbug/1028133): Add extra logic to handle UX for non-authorized // TODO(crbug/1028133): Add extra logic to handle UX for non-authorized
// users. // users.
request->FinishRequest(Result::UNAUTHORIZED, DeepScanningClientResponse()); request->FinishRequest(Result::UNAUTHORIZED);
return; return;
} }
UploadForDeepScanning(std::move(request)); UploadForDeepScanning(std::move(request));
...@@ -149,14 +157,19 @@ void BinaryUploadService::UploadForDeepScanning( ...@@ -149,14 +157,19 @@ void BinaryUploadService::UploadForDeepScanning(
content::GetUIThreadTaskRunner({})->PostTask( content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&BinaryUploadService::FinishRequest, FROM_HERE, base::BindOnce(&BinaryUploadService::FinishRequest,
weakptr_factory_.GetWeakPtr(), raw_request, weakptr_factory_.GetWeakPtr(), raw_request,
Result::FAILED_TO_GET_TOKEN, Result::FAILED_TO_GET_TOKEN));
DeepScanningClientResponse()));
return; return;
} }
binary_fcm_service_->SetCallbackForToken( if (raw_request->use_legacy_proto()) {
token, base::BindRepeating(&BinaryUploadService::OnGetResponse, binary_fcm_service_->SetCallbackForToken(
weakptr_factory_.GetWeakPtr(), raw_request)); 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( binary_fcm_service_->GetInstanceID(
base::BindOnce(&BinaryUploadService::OnGetInstanceID, base::BindOnce(&BinaryUploadService::OnGetInstanceID,
weakptr_factory_.GetWeakPtr(), raw_request)); weakptr_factory_.GetWeakPtr(), raw_request));
...@@ -173,8 +186,7 @@ void BinaryUploadService::OnGetInstanceID(Request* request, ...@@ -173,8 +186,7 @@ void BinaryUploadService::OnGetInstanceID(Request* request,
return; return;
if (instance_id == BinaryFCMService::kInvalidId) { if (instance_id == BinaryFCMService::kInvalidId) {
FinishRequest(request, Result::FAILED_TO_GET_TOKEN, FinishRequest(request, Result::FAILED_TO_GET_TOKEN);
DeepScanningClientResponse());
return; return;
} }
...@@ -197,7 +209,7 @@ void BinaryUploadService::OnGetRequestData(Request* request, ...@@ -197,7 +209,7 @@ void BinaryUploadService::OnGetRequestData(Request* request,
return; return;
if (result != Result::SUCCESS) { if (result != Result::SUCCESS) {
FinishRequest(request, result, DeepScanningClientResponse()); FinishRequest(request, result);
return; return;
} }
...@@ -240,7 +252,7 @@ void BinaryUploadService::OnGetRequestData(Request* request, ...@@ -240,7 +252,7 @@ void BinaryUploadService::OnGetRequestData(Request* request,
)"); )");
std::string metadata; std::string metadata;
request->deep_scanning_request().SerializeToString(&metadata); request->SerializeToString(&metadata);
base::Base64Encode(metadata, &metadata); base::Base64Encode(metadata, &metadata);
GURL url = request->url().is_valid() GURL url = request->url().is_valid()
...@@ -251,11 +263,19 @@ void BinaryUploadService::OnGetRequestData(Request* request, ...@@ -251,11 +263,19 @@ void BinaryUploadService::OnGetRequestData(Request* request,
traffic_annotation, traffic_annotation,
base::BindOnce(&BinaryUploadService::OnUploadComplete, base::BindOnce(&BinaryUploadService::OnUploadComplete,
weakptr_factory_.GetWeakPtr(), request)); 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(); upload_request->Start();
active_uploads_[request] = std::move(upload_request); active_uploads_[request] = std::move(upload_request);
WebUIInfoSingleton::GetInstance()->AddToDeepScanRequests(
request->deep_scanning_request());
} }
void BinaryUploadService::OnUploadComplete(Request* request, void BinaryUploadService::OnUploadComplete(Request* request,
...@@ -265,53 +285,112 @@ void BinaryUploadService::OnUploadComplete(Request* request, ...@@ -265,53 +285,112 @@ void BinaryUploadService::OnUploadComplete(Request* request,
return; return;
if (!success) { if (!success) {
FinishRequest(request, Result::UPLOAD_FAILURE, FinishRequest(request, Result::UPLOAD_FAILURE);
DeepScanningClientResponse());
return; return;
} }
DeepScanningClientResponse response; if (request->use_legacy_proto()) {
if (!response.ParseFromString(response_data)) { DeepScanningClientResponse response;
FinishRequest(request, Result::UPLOAD_FAILURE, if (!response.ParseFromString(response_data)) {
DeepScanningClientResponse()); FinishRequest(request, Result::UPLOAD_FAILURE);
return; 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 for (const auto& result : response.results()) {
// check for those. if (result.has_tag() && !result.tag().empty()) {
OnGetResponse(request, response); 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, void BinaryUploadService::OnGetLegacyResponse(
DeepScanningClientResponse response) { Request* request,
DeepScanningClientResponse response) {
if (!IsActive(request)) if (!IsActive(request))
return; return;
if (response.has_dlp_scan_verdict()) { if (response.has_dlp_scan_verdict()) {
VLOG(1) << "Request " << request->deep_scanning_request().request_token() VLOG(1) << "Request " << request->request_token()
<< " finished DLP scanning"; << " finished DLP scanning";
received_dlp_verdicts_[request].reset(response.release_dlp_scan_verdict()); received_dlp_verdicts_[request].reset(response.release_dlp_scan_verdict());
} }
if (response.has_malware_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"; << " finished malware scanning";
received_malware_verdicts_[request].reset( received_malware_verdicts_[request].reset(
response.release_malware_scan_verdict()); response.release_malware_scan_verdict());
} }
MaybeFinishRequest(request); MaybeFinishLegacyRequest(request);
} }
void BinaryUploadService::MaybeFinishRequest(Request* 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 = bool requested_dlp_scan_response =
request->deep_scanning_request().has_dlp_scan_request(); request->deep_scanning_request().has_dlp_scan_request();
auto received_dlp_response = received_dlp_verdicts_.find(request); auto received_dlp_response = received_dlp_verdicts_.find(request);
if (requested_dlp_scan_response && if (requested_dlp_scan_response &&
received_dlp_response == received_dlp_verdicts_.end()) { 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."; << " is waiting for DLP scanning to complete.";
return; return;
} }
...@@ -321,13 +400,13 @@ void BinaryUploadService::MaybeFinishRequest(Request* request) { ...@@ -321,13 +400,13 @@ void BinaryUploadService::MaybeFinishRequest(Request* request) {
auto received_malware_response = received_malware_verdicts_.find(request); auto received_malware_response = received_malware_verdicts_.find(request);
if (requested_malware_scan_response && if (requested_malware_scan_response &&
received_malware_response == received_malware_verdicts_.end()) { 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."; << " is waiting for malware scanning to complete.";
return; return;
} }
DeepScanningClientResponse response; DeepScanningClientResponse response;
response.set_token(request->deep_scanning_request().request_token()); response.set_token(request->request_token());
if (requested_dlp_scan_response) { if (requested_dlp_scan_response) {
// Transfers ownership of the DLP response to |response|. // Transfers ownership of the DLP response to |response|.
response.set_allocated_dlp_scan_verdict( response.set_allocated_dlp_scan_verdict(
...@@ -340,17 +419,45 @@ void BinaryUploadService::MaybeFinishRequest(Request* request) { ...@@ -340,17 +419,45 @@ void BinaryUploadService::MaybeFinishRequest(Request* request) {
received_malware_response->second.release()); received_malware_response->second.release());
} }
FinishRequest(request, Result::SUCCESS, std::move(response)); FinishLegacyRequest(request, Result::SUCCESS, std::move(response));
} }
void BinaryUploadService::OnTimeout(Request* request) { void BinaryUploadService::OnTimeout(Request* request) {
if (IsActive(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, void BinaryUploadService::FinishLegacyRequest(
Result result, Request* request,
DeepScanningClientResponse response) { Result result,
DeepScanningClientResponse response) {
RecordRequestMetrics(request, result, response); RecordRequestMetrics(request, result, response);
// We add the request here in case we never actually uploaded anything, so it // We add the request here in case we never actually uploaded anything, so it
...@@ -360,15 +467,19 @@ void BinaryUploadService::FinishRequest(Request* request, ...@@ -360,15 +467,19 @@ void BinaryUploadService::FinishRequest(Request* request,
WebUIInfoSingleton::GetInstance()->AddToDeepScanResponses( WebUIInfoSingleton::GetInstance()->AddToDeepScanResponses(
active_tokens_[request], ResultToString(result), response); active_tokens_[request], ResultToString(result), response);
std::string instance_id = std::string instance_id = request->fcm_notification_token();
request->deep_scanning_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_requests_.erase(request);
active_timers_.erase(request); active_timers_.erase(request);
active_uploads_.erase(request); active_uploads_.erase(request);
received_malware_verdicts_.erase(request); received_malware_verdicts_.erase(request);
received_dlp_verdicts_.erase(request); received_dlp_verdicts_.erase(request);
received_connector_responses_.erase(request);
auto token_it = active_tokens_.find(request); auto token_it = active_tokens_.find(request);
DCHECK(token_it != active_tokens_.end()); DCHECK(token_it != active_tokens_.end());
...@@ -401,17 +512,42 @@ void BinaryUploadService::InstanceIDUnregisteredCallback(bool) { ...@@ -401,17 +512,42 @@ void BinaryUploadService::InstanceIDUnregisteredCallback(bool) {
} }
} }
void BinaryUploadService::RecordRequestMetrics( void BinaryUploadService::RecordRequestMetrics(Request* request,
Request* request, Result result) {
Result result,
const DeepScanningClientResponse& response) {
base::UmaHistogramEnumeration("SafeBrowsingBinaryUploadRequest.Result", base::UmaHistogramEnumeration("SafeBrowsingBinaryUploadRequest.Result",
result); result);
base::UmaHistogramCustomTimes("SafeBrowsingBinaryUploadRequest.Duration", base::UmaHistogramCustomTimes("SafeBrowsingBinaryUploadRequest.Duration",
base::TimeTicks::Now() - start_times_[request], base::TimeTicks::Now() - start_times_[request],
base::TimeDelta::FromMilliseconds(1), base::TimeDelta::FromMilliseconds(1),
base::TimeDelta::FromMinutes(6), 50); 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()) { if (response.has_malware_scan_verdict()) {
base::UmaHistogramBoolean("SafeBrowsingBinaryUploadRequest.MalwareResult", base::UmaHistogramBoolean("SafeBrowsingBinaryUploadRequest.MalwareResult",
response.malware_scan_verdict().verdict() != response.malware_scan_verdict().verdict() !=
...@@ -442,11 +578,13 @@ BinaryUploadService::Request::~Request() = default; ...@@ -442,11 +578,13 @@ BinaryUploadService::Request::~Request() = default;
void BinaryUploadService::Request::set_request_dlp_scan( void BinaryUploadService::Request::set_request_dlp_scan(
DlpDeepScanningClientRequest dlp_request) { DlpDeepScanningClientRequest dlp_request) {
DCHECK(use_legacy_proto_);
*deep_scanning_request_.mutable_dlp_scan_request() = std::move(dlp_request); *deep_scanning_request_.mutable_dlp_scan_request() = std::move(dlp_request);
} }
void BinaryUploadService::Request::set_request_malware_scan( void BinaryUploadService::Request::set_request_malware_scan(
MalwareDeepScanningClientRequest malware_request) { MalwareDeepScanningClientRequest malware_request) {
DCHECK(use_legacy_proto_);
*deep_scanning_request_.mutable_malware_scan_request() = *deep_scanning_request_.mutable_malware_scan_request() =
std::move(malware_request); std::move(malware_request);
} }
...@@ -487,33 +625,83 @@ void BinaryUploadService::Request::set_digest(const std::string& digest) { ...@@ -487,33 +625,83 @@ void BinaryUploadService::Request::set_digest(const std::string& digest) {
} }
void BinaryUploadService::Request::clear_dlp_scan_request() { void BinaryUploadService::Request::clear_dlp_scan_request() {
DCHECK(use_legacy_proto_);
deep_scanning_request_.clear_dlp_scan_request(); deep_scanning_request_.clear_dlp_scan_request();
} }
void BinaryUploadService::Request::set_analysis_connector( void BinaryUploadService::Request::set_analysis_connector(
enterprise_connectors::AnalysisConnector connector) { enterprise_connectors::AnalysisConnector connector) {
DCHECK(!use_legacy_proto_);
content_analysis_request_.set_analysis_connector(connector); content_analysis_request_.set_analysis_connector(connector);
} }
void BinaryUploadService::Request::set_url(const std::string& url) { void BinaryUploadService::Request::set_url(const std::string& url) {
DCHECK(!use_legacy_proto_);
content_analysis_request_.mutable_request_data()->set_url(url); content_analysis_request_.mutable_request_data()->set_url(url);
} }
void BinaryUploadService::Request::set_csd(ClientDownloadRequest csd) { void BinaryUploadService::Request::set_csd(ClientDownloadRequest csd) {
DCHECK(!use_legacy_proto_);
*content_analysis_request_.mutable_request_data()->mutable_csd() = *content_analysis_request_.mutable_request_data()->mutable_csd() =
std::move(csd); std::move(csd);
} }
void BinaryUploadService::Request::add_tag(const std::string& tag) { void BinaryUploadService::Request::add_tag(const std::string& tag) {
DCHECK(!use_legacy_proto_);
content_analysis_request_.add_tags(tag); 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, Result result,
DeepScanningClientResponse response) { DeepScanningClientResponse response) {
std::move(callback_).Run(result, 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) { bool BinaryUploadService::IsActive(Request* request) {
return (active_requests_.find(request) != active_requests_.end()); return (active_requests_.find(request) != active_requests_.end());
} }
......
...@@ -137,7 +137,13 @@ class BinaryUploadService : public KeyedService { ...@@ -137,7 +137,13 @@ class BinaryUploadService : public KeyedService {
// Returns the URL to send the request to. // Returns the URL to send the request to.
const GURL& url() const { return url_; } 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. // Methods for modifying the DeepScanningClientRequest.
void set_request_dlp_scan(DlpDeepScanningClientRequest dlp_request); void set_request_dlp_scan(DlpDeepScanningClientRequest dlp_request);
...@@ -159,9 +165,22 @@ class BinaryUploadService : public KeyedService { ...@@ -159,9 +165,22 @@ class BinaryUploadService : public KeyedService {
void set_filename(const std::string& filename); void set_filename(const std::string& filename);
void set_digest(const std::string& digest); 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 // Finish the request, with the given |result| and |response| from the
// server. // 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: private:
const bool use_legacy_proto_; const bool use_legacy_proto_;
...@@ -200,9 +219,14 @@ class BinaryUploadService : public KeyedService { ...@@ -200,9 +219,14 @@ class BinaryUploadService : public KeyedService {
static GURL GetUploadUrl(bool is_advanced_protection_request); static GURL GetUploadUrl(bool is_advanced_protection_request);
protected: protected:
void FinishRequest(Request* request, void FinishRequest(Request* request, Result result);
Result result, void FinishConnectorRequest(
DeepScanningClientResponse response); Request* request,
Result result,
enterprise_connectors::ContentAnalysisResponse response);
void FinishLegacyRequest(Request* request,
Result result,
DeepScanningClientResponse response);
private: private:
friend class BinaryUploadServiceTest; friend class BinaryUploadServiceTest;
...@@ -222,9 +246,15 @@ class BinaryUploadService : public KeyedService { ...@@ -222,9 +246,15 @@ class BinaryUploadService : public KeyedService {
bool success, bool success,
const std::string& response_data); 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 MaybeFinishRequest(Request* request);
void MaybeFinishConnectorRequest(Request* request);
void MaybeFinishLegacyRequest(Request* request);
void OnTimeout(Request* request); void OnTimeout(Request* request);
...@@ -240,10 +270,18 @@ class BinaryUploadService : public KeyedService { ...@@ -240,10 +270,18 @@ class BinaryUploadService : public KeyedService {
// Callback once a request's instance ID is unregistered. // Callback once a request's instance ID is unregistered.
void InstanceIDUnregisteredCallback(bool); void InstanceIDUnregisteredCallback(bool);
void RecordRequestMetrics(Request* request, Result result);
void RecordRequestMetrics(
Request* request,
Result result,
const enterprise_connectors::ContentAnalysisResponse& response);
void RecordRequestMetrics(Request* request, void RecordRequestMetrics(Request* request,
Result result, Result result,
const DeepScanningClientResponse& response); 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_; scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
std::unique_ptr<BinaryFCMService> binary_fcm_service_; std::unique_ptr<BinaryFCMService> binary_fcm_service_;
...@@ -261,6 +299,10 @@ class BinaryUploadService : public KeyedService { ...@@ -261,6 +299,10 @@ class BinaryUploadService : public KeyedService {
base::flat_map<Request*, std::unique_ptr<DlpDeepScanningVerdict>> base::flat_map<Request*, std::unique_ptr<DlpDeepScanningVerdict>>
received_dlp_verdicts_; 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. // Indicates whether this browser can upload data for enterprise requests.
// Advanced Protection scans are validated using the user's Advanced // Advanced Protection scans are validated using the user's Advanced
// Protection enrollment status. // Protection enrollment status.
......
...@@ -142,7 +142,7 @@ class BinaryUploadServiceTest : public testing::Test { ...@@ -142,7 +142,7 @@ class BinaryUploadServiceTest : public testing::Test {
void ReceiveMessageForRequest(BinaryUploadService::Request* request, void ReceiveMessageForRequest(BinaryUploadService::Request* request,
const DeepScanningClientResponse& response) { const DeepScanningClientResponse& response) {
service_->OnGetResponse(request, response); service_->OnGetLegacyResponse(request, response);
} }
void ReceiveResponseFromUpload(BinaryUploadService::Request* request, void ReceiveResponseFromUpload(BinaryUploadService::Request* request,
......
...@@ -671,7 +671,7 @@ void DeepScanningDialogDelegate::OnGotFileInfo( ...@@ -671,7 +671,7 @@ void DeepScanningDialogDelegate::OnGotFileInfo(
// property (too large, unsupported file type, encrypted, ...) that make its // property (too large, unsupported file type, encrypted, ...) that make its
// upload pointless, so the request should finish early. // upload pointless, so the request should finish early.
if (result != BinaryUploadService::Result::SUCCESS) { if (result != BinaryUploadService::Result::SUCCESS) {
request->FinishRequest(result, DeepScanningClientResponse()); request->FinishRequest(result);
return; return;
} }
......
...@@ -46,8 +46,7 @@ class FakeBinaryUploadService : public BinaryUploadService { ...@@ -46,8 +46,7 @@ class FakeBinaryUploadService : public BinaryUploadService {
// Finish the authentication request. Called after ShowForWebContents to // Finish the authentication request. Called after ShowForWebContents to
// simulate an async callback. // simulate an async callback.
void ReturnAuthorizedResponse() { void ReturnAuthorizedResponse() {
FinishRequest(authorization_request_.get(), authorization_result_, FinishRequest(authorization_request_.get(), authorization_result_);
DeepScanningClientResponse());
} }
void SetResponseForText(BinaryUploadService::Result result, void SetResponseForText(BinaryUploadService::Result result,
...@@ -80,12 +79,13 @@ class FakeBinaryUploadService : public BinaryUploadService { ...@@ -80,12 +79,13 @@ class FakeBinaryUploadService : public BinaryUploadService {
} else { } else {
std::string file = request->deep_scanning_request().filename(); std::string file = request->deep_scanning_request().filename();
if (file.empty()) { if (file.empty()) {
request->FinishRequest(prepared_text_result_, prepared_text_response_); request->FinishLegacyRequest(prepared_text_result_,
prepared_text_response_);
} else { } else {
ASSERT_TRUE(prepared_file_results_.count(file)); ASSERT_TRUE(prepared_file_results_.count(file));
ASSERT_TRUE(prepared_file_responses_.count(file)); ASSERT_TRUE(prepared_file_responses_.count(file));
request->FinishRequest(prepared_file_results_[file], request->FinishLegacyRequest(prepared_file_results_[file],
prepared_file_responses_[file]); prepared_file_responses_[file]);
} }
} }
} }
......
...@@ -19,8 +19,9 @@ void TestBinaryUploadService::MaybeUploadForDeepScanning( ...@@ -19,8 +19,9 @@ void TestBinaryUploadService::MaybeUploadForDeepScanning(
std::unique_ptr<Request> request) { std::unique_ptr<Request> request) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
content::GetUIThreadTaskRunner({})->PostTask( content::GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&Request::FinishRequest, std::move(request), FROM_HERE,
saved_result_, saved_response_)); base::BindOnce(&Request::FinishLegacyRequest, std::move(request),
saved_result_, saved_response_));
was_called_ = true; was_called_ = true;
} }
......
...@@ -67,7 +67,7 @@ class FakeBinaryUploadService : public BinaryUploadService { ...@@ -67,7 +67,7 @@ class FakeBinaryUploadService : public BinaryUploadService {
void MaybeUploadForDeepScanning(std::unique_ptr<Request> request) override { void MaybeUploadForDeepScanning(std::unique_ptr<Request> request) override {
last_request_ = request->deep_scanning_request(); last_request_ = request->deep_scanning_request();
request->FinishRequest(saved_result_, saved_response_); request->FinishLegacyRequest(saved_result_, saved_response_);
} }
void SetResponse(BinaryUploadService::Result result, void SetResponse(BinaryUploadService::Result result,
......
...@@ -12,6 +12,7 @@ static_library("web_ui") { ...@@ -12,6 +12,7 @@ static_library("web_ui") {
deps = [ deps = [
"//base", "//base",
"//components/enterprise/common/proto:connectors_proto",
"//components/password_manager/core/browser:hash_password_manager", "//components/password_manager/core/browser:hash_password_manager",
"//components/resources:components_resources_grit", "//components/resources:components_resources_grit",
"//components/resources:components_scaled_resources_grit", "//components/resources:components_scaled_resources_grit",
......
include_rules = [ include_rules = [
"+components/enterprise/common/proto/connectors.pb.h",
"+components/grit/components_resources.h", "+components/grit/components_resources.h",
"+components/password_manager/core/browser/hash_password_manager.h", "+components/password_manager/core/browser/hash_password_manager.h",
"+components/user_prefs", "+components/user_prefs",
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/grit/components_resources.h" #include "components/grit/components_resources.h"
#include "components/grit/components_scaled_resources.h" #include "components/grit/components_scaled_resources.h"
#include "components/password_manager/core/browser/hash_password_manager.h" #include "components/password_manager/core/browser/hash_password_manager.h"
...@@ -271,6 +272,26 @@ void WebUIInfoSingleton::AddToDeepScanRequests( ...@@ -271,6 +272,26 @@ void WebUIInfoSingleton::AddToDeepScanRequests(
request.request_token(), deep_scan_requests_[request.request_token()]); 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( void WebUIInfoSingleton::AddToDeepScanResponses(
const std::string& token, const std::string& token,
const std::string& status, const std::string& status,
...@@ -286,6 +307,21 @@ void WebUIInfoSingleton::AddToDeepScanResponses( ...@@ -286,6 +307,21 @@ void WebUIInfoSingleton::AddToDeepScanResponses(
webui_listener->NotifyDeepScanJsListener(token, deep_scan_requests_[token]); 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() { void WebUIInfoSingleton::ClearDeepScans() {
base::flat_map<std::string, DeepScanDebugData>().swap(deep_scan_requests_); base::flat_map<std::string, DeepScanDebugData>().swap(deep_scan_requests_);
} }
...@@ -1303,6 +1339,52 @@ base::Value SerializeReportingEvent(const base::Value& event) { ...@@ -1303,6 +1339,52 @@ base::Value SerializeReportingEvent(const base::Value& event) {
} }
#if BUILDFLAG(FULL_SAFE_BROWSING) #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( std::string SerializeDeepScanningRequest(
const DeepScanningClientRequest& request) { const DeepScanningClientRequest& request) {
base::DictionaryValue request_dict; base::DictionaryValue request_dict;
...@@ -1361,6 +1443,68 @@ std::string SerializeDeepScanningRequest( ...@@ -1361,6 +1443,68 @@ std::string SerializeDeepScanningRequest(
return request_serialized; 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( std::string SerializeDeepScanningResponse(
const DeepScanningClientResponse& response) { const DeepScanningClientResponse& response) {
base::DictionaryValue response_dict; base::DictionaryValue response_dict;
...@@ -1470,6 +1614,9 @@ base::Value SerializeDeepScanDebugData(const std::string& token, ...@@ -1470,6 +1614,9 @@ base::Value SerializeDeepScanDebugData(const std::string& token,
if (data.request.has_value()) { if (data.request.has_value()) {
value.SetStringKey("request", value.SetStringKey("request",
SerializeDeepScanningRequest(data.request.value())); 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()) { if (!data.response_time.is_null()) {
...@@ -1483,6 +1630,9 @@ base::Value SerializeDeepScanDebugData(const std::string& token, ...@@ -1483,6 +1630,9 @@ base::Value SerializeDeepScanDebugData(const std::string& token,
if (data.response.has_value()) { if (data.response.has_value()) {
value.SetStringKey("response", value.SetStringKey("response",
SerializeDeepScanningResponse(data.response.value())); 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); return std::move(value);
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include "base/bind.h" #include "base/bind.h"
#include "base/macros.h" #include "base/macros.h"
#include "components/enterprise/common/proto/connectors.pb.h"
#include "components/safe_browsing/buildflags.h" #include "components/safe_browsing/buildflags.h"
#include "components/safe_browsing/core/browser/safe_browsing_network_context.h" #include "components/safe_browsing/core/browser/safe_browsing_network_context.h"
#include "components/safe_browsing/core/proto/csd.pb.h" #include "components/safe_browsing/core/proto/csd.pb.h"
...@@ -42,10 +43,14 @@ struct DeepScanDebugData { ...@@ -42,10 +43,14 @@ struct DeepScanDebugData {
base::Time request_time; base::Time request_time;
base::Optional<DeepScanningClientRequest> request; base::Optional<DeepScanningClientRequest> request;
base::Optional<enterprise_connectors::ContentAnalysisRequest>
content_analysis_request;
base::Time response_time; base::Time response_time;
std::string response_status; std::string response_status;
base::Optional<DeepScanningClientResponse> response; base::Optional<DeepScanningClientResponse> response;
base::Optional<enterprise_connectors::ContentAnalysisResponse>
content_analysis_response;
}; };
#endif #endif
...@@ -327,12 +332,18 @@ class WebUIInfoSingleton { ...@@ -327,12 +332,18 @@ class WebUIInfoSingleton {
// identifier that can be used in |AddToDeepScanResponses| to correlate a ping // identifier that can be used in |AddToDeepScanResponses| to correlate a ping
// and response. // and response.
void AddToDeepScanRequests(const DeepScanningClientRequest& request); 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 // Add the new response to |deep_scan_requests_| and send it to all the open
// chrome://safe-browsing tabs. // chrome://safe-browsing tabs.
void AddToDeepScanResponses(const std::string& token, void AddToDeepScanResponses(const std::string& token,
const std::string& status, const std::string& status,
const DeepScanningClientResponse& response); 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. // Clear the list of deep scan requests and responses.
void ClearDeepScans(); 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