Scanner: Define protos and implement ScannerProvider::Call method.
Includes validation for input and output objects. Has logic to wrap the
protos within a Proto3Any.
Added more tests to cover the InvalidInput, MalformedResponse and
BlockedOutputs errors.
Bug: 363101024
Test: autoninja -C out/Default components_unittests
Change-Id: I32ccc041e256ac0f4e53b68006d64859f2425dd5
Cq-Include-Trybots: luci.chromium.try:linux-chromeos-rel;luci.chrome.try:linux-chromeos-chrome
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5921060
Reviewed-by: Xinglong Luan <[email protected]>
Commit-Queue: Callistus Tan <[email protected]>
Reviewed-by: Michael Cui <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1368101}
diff --git a/components/manta/scanner_provider.cc b/components/manta/scanner_provider.cc
index b7a0fd70..4f053a2f 100644
--- a/components/manta/scanner_provider.cc
+++ b/components/manta/scanner_provider.cc
@@ -6,15 +6,18 @@
#include <memory>
#include <string>
+#include <utility>
#include "base/check.h"
#include "base/functional/bind.h"
+#include "base/strings/strcat.h"
#include "base/time/time.h"
#include "components/endpoint_fetcher/endpoint_fetcher.h"
#include "components/manta/base_provider.h"
#include "components/manta/features.h"
#include "components/manta/manta_service_callbacks.h"
#include "components/manta/manta_status.h"
+#include "components/manta/proto/common.pb.h"
#include "components/manta/proto/manta.pb.h"
#include "components/manta/proto/scanner.pb.h"
#include "components/signin/public/identity_manager/identity_manager.h"
@@ -27,22 +30,78 @@
constexpr char kOauthConsumerName[] = "manta_scanner";
constexpr base::TimeDelta kTimeout = base::Seconds(30);
+bool IsValidScannerInput(const proto::ScannerInput& scanner_input) {
+ return scanner_input.image().size() > 0;
+}
+
+std::unique_ptr<proto::ScannerOutput> GetScannerOutput(
+ const proto::Response& manta_response) {
+ // There should only be one output data.
+ if (manta_response.output_data_size() != 1) {
+ return nullptr;
+ }
+ const proto::OutputData& output_data = manta_response.output_data(0);
+
+ // There should be a custom proto.
+ if (!output_data.has_custom()) {
+ return nullptr;
+ }
+
+ // The custom proto should be a ScannerOutput.
+ if (output_data.custom().type_url() != kScannerOutputTypeUrl) {
+ return nullptr;
+ }
+
+ const proto::Proto3Any& custom_data = output_data.custom();
+
+ auto scanner_output = std::make_unique<proto::ScannerOutput>();
+ scanner_output->ParseFromString(custom_data.value());
+
+ return scanner_output;
+}
+
void OnServerResponseOrErrorReceived(
ScannerProvider::ScannerProtoResponseCallback callback,
std::unique_ptr<proto::Response> manta_response,
MantaStatus manta_status) {
+ // Check for Manta error status.
if (manta_status.status_code != MantaStatusCode::kOk) {
std::move(callback).Run(nullptr, std::move(manta_status));
return;
}
- DCHECK(manta_response != nullptr);
+ // Check for a valid Manta response.
+ if (manta_response == nullptr) {
+ std::move(callback).Run(nullptr, {MantaStatusCode::kMalformedResponse});
+ return;
+ }
- // TODO: b/363101024 - Parse ScannerResponse from manta_response.
- std::unique_ptr<proto::ScannerResponse> scanner_response =
- std::make_unique<proto::ScannerResponse>();
+ // Check that the Manta response has output data.
+ if (manta_response->output_data_size() == 0) {
+ std::string message;
- std::move(callback).Run(std::move(scanner_response), std::move(manta_status));
+ // If there are no outputs, the response might have been filtered.
+ if (manta_response->filtered_data_size() > 0 &&
+ manta_response->filtered_data(0).is_output_data()) {
+ message = base::StrCat({"filtered output for: ",
+ proto::FilteredReason_Name(
+ manta_response->filtered_data(0).reason())});
+ }
+ std::move(callback).Run(nullptr,
+ {MantaStatusCode::kBlockedOutputs, message});
+ return;
+ }
+
+ // Try to extract a ScannerOutput object from the Manta response.
+ std::unique_ptr<proto::ScannerOutput> scanner_output =
+ GetScannerOutput(*manta_response);
+ if (scanner_output == nullptr) {
+ std::move(callback).Run(nullptr, {MantaStatusCode::kMalformedResponse});
+ return;
+ }
+
+ // All checks passed, run callback with valid ScannerOutput.
+ std::move(callback).Run(std::move(scanner_output), std::move(manta_status));
}
} // namespace
@@ -56,10 +115,25 @@
ScannerProvider::~ScannerProvider() = default;
void ScannerProvider::Call(
+ const manta::proto::ScannerInput& scanner_input,
ScannerProvider::ScannerProtoResponseCallback done_callback) {
+ // Check for valid ScannerInput.
+ if (!IsValidScannerInput(scanner_input)) {
+ std::move(done_callback).Run(nullptr, {MantaStatusCode::kInvalidInput});
+ return;
+ }
+ // Populate Manta request with the specified ScannerInput as the custom input
+ // data.
proto::Request request;
request.set_feature_name(proto::FeatureName::CHROMEOS_SCANNER);
+ proto::InputData* input_data = request.add_input_data();
+ input_data->set_tag("scanner_input");
+
+ proto::Proto3Any& custom = *input_data->mutable_custom();
+ custom.set_type_url(kScannerInputTypeUrl);
+ custom.set_value(scanner_input.SerializeAsString());
+
// TODO: b/363101024 - Populate annotation tag.
RequestInternal(
GURL{GetProviderEndpoint(features::IsScannerUseProdServerEnabled())},