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
......@@ -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