Commit 9e1301f0 authored by Sophie Chang's avatar Sophie Chang Committed by Commit Bot

Add support for any proto as metadata

Change-Id: I9d49e60dc62ec3e289a187da197fcdb699574e41
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2354462Reviewed-by: default avatarMichael Crouse <mcrouse@chromium.org>
Commit-Queue: Sophie Chang <sophiechang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797912}
parent bc2634bf
......@@ -159,6 +159,9 @@ bool IsOptimizationTypeAllowed(
optimization_metadata->set_delay_async_script_execution_metadata(
optimization.delay_async_script_execution_metadata());
break;
case optimization_guide::proto::Optimization::kAnyMetadata:
optimization_metadata->set_any_metadata(optimization.any_metadata());
break;
case optimization_guide::proto::Optimization::METADATA_NOT_SET:
// Some optimization types do not have metadata, make sure we do not
// DCHECK.
......@@ -1383,6 +1386,11 @@ void OptimizationGuideHintsManager::AddHintForTesting(
} else if (metadata->public_image_metadata()) {
*optimization->mutable_public_image_metadata() =
*metadata->public_image_metadata();
} else if (metadata->delay_async_script_execution_metadata()) {
*optimization->mutable_delay_async_script_execution_metadata() =
*metadata->delay_async_script_execution_metadata();
} else if (metadata->any_metadata()) {
*optimization->mutable_any_metadata() = *metadata->any_metadata();
} else {
NOTREACHED();
}
......
......@@ -1441,6 +1441,50 @@ TEST_F(OptimizationGuideHintsManagerTest,
optimization_type_decision);
}
TEST_F(OptimizationGuideHintsManagerTest,
CanApplyOptimizationAndPopulatesAnyMetadata) {
hints_manager()->RegisterOptimizationTypes(
{optimization_guide::proto::LOADING_PREDICTOR});
optimization_guide::proto::Configuration config;
optimization_guide::proto::Hint* hint = config.add_hints();
hint->set_key("somedomain.org");
hint->set_key_representation(optimization_guide::proto::HOST);
hint->set_version("someversion");
optimization_guide::proto::PageHint* page_hint = hint->add_page_hints();
page_hint->set_page_pattern("/news/");
optimization_guide::proto::Optimization* opt =
page_hint->add_whitelisted_optimizations();
opt->set_optimization_type(optimization_guide::proto::LOADING_PREDICTOR);
optimization_guide::proto::LoadingPredictorMetadata lp_metadata;
lp_metadata.add_subresources()->set_url("https://resource.com/");
lp_metadata.SerializeToString(opt->mutable_any_metadata()->mutable_value());
opt->mutable_any_metadata()->set_type_url(
"type.googleapis.com/com.foo.LoadingPredictorMetadata");
ProcessHints(config, "1.0.0.0");
std::unique_ptr<content::MockNavigationHandle> navigation_handle =
CreateMockNavigationHandleWithOptimizationGuideWebContentsObserver(
url_with_hints());
base::RunLoop run_loop;
hints_manager()->OnNavigationStartOrRedirect(navigation_handle.get(),
run_loop.QuitClosure());
run_loop.Run();
optimization_guide::OptimizationMetadata optimization_metadata;
optimization_guide::OptimizationTypeDecision optimization_type_decision =
hints_manager()->CanApplyOptimization(
navigation_handle->GetURL(),
optimization_guide::proto::LOADING_PREDICTOR, &optimization_metadata);
// Make sure loading predictor metadata is populated.
EXPECT_TRUE(
optimization_metadata
.ParsedMetadata<optimization_guide::proto::LoadingPredictorMetadata>()
.has_value());
EXPECT_EQ(optimization_guide::OptimizationTypeDecision::kAllowedByHint,
optimization_type_decision);
}
TEST_F(OptimizationGuideHintsManagerTest, IsGoogleURL) {
const struct {
const char* url;
......
......@@ -114,6 +114,7 @@ source_set("unit_tests") {
"optimization_guide_service_unittest.cc",
"optimization_guide_store_unittest.cc",
"optimization_guide_switches_unittest.cc",
"optimization_metadata_unittest.cc",
"prediction_model_unittest.cc",
"store_update_data_unittest.cc",
"url_pattern_with_wildcards_unittest.cc",
......
......@@ -5,7 +5,9 @@
#ifndef COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_METADATA_H_
#define COMPONENTS_OPTIMIZATION_GUIDE_OPTIMIZATION_METADATA_H_
#include "base/logging.h"
#include "base/optional.h"
#include "base/strings/string_split.h"
#include "components/optimization_guide/proto/hints.pb.h"
namespace optimization_guide {
......@@ -22,6 +24,44 @@ class OptimizationMetadata {
OptimizationMetadata(const OptimizationMetadata&);
~OptimizationMetadata();
// Validates that the metadata stored in |any_metadata_| is of the same type
// and is parseable as |T|. Will return metadata if all checks pass.
template <
class T,
class = typename std::enable_if<
std::is_convertible<T*, google::protobuf::MessageLite*>{}>::type>
base::Optional<T> ParsedMetadata() const {
if (!any_metadata_)
return base::nullopt;
// Verify type is the same - the Any type URL should be wrapped as:
// "type.googleapis.com/com.foo.Name".
std::vector<std::string> any_type_parts =
base::SplitString(any_metadata_->type_url(), ".", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (any_type_parts.empty())
return base::nullopt;
T metadata;
std::vector<std::string> type_parts =
base::SplitString(metadata.GetTypeName(), ".", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY);
if (type_parts.empty())
return base::nullopt;
std::string any_type_name = any_type_parts.back();
std::string type_name = type_parts.back();
if (type_name != any_type_name)
return base::nullopt;
// Return metadata if parseable.
if (metadata.ParseFromString(any_metadata_->value()))
return metadata;
return base::nullopt;
}
base::Optional<proto::Any> any_metadata() const { return any_metadata_; }
void set_any_metadata(const proto::Any& any_metadata) {
any_metadata_ = any_metadata;
}
base::Optional<proto::PreviewsMetadata> previews_metadata() const {
return previews_metadata_;
}
......@@ -67,6 +107,12 @@ class OptimizationMetadata {
}
private:
// Metadata applicable to the optimization type.
//
// Optimization types that are not specifically specified below will have
// metadata populated with this field.
base::Optional<proto::Any> any_metadata_;
// Only applicable for NOSCRIPT and RESOURCE_LOADING optimization types.
base::Optional<proto::PreviewsMetadata> previews_metadata_;
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/optimization_guide/optimization_metadata.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace optimization_guide {
TEST(OptimizationMetadataTest, ParsedMetadataAnyMetadataNotPopulatedTest) {
OptimizationMetadata optimization_metadata;
base::Optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
EXPECT_FALSE(parsed_dase_metadata.has_value());
}
TEST(OptimizationMetadataTest, ParsedMetadataNoTypeURLTest) {
proto::Any any_metadata;
proto::DelayAsyncScriptExecutionMetadata dase_metadata;
dase_metadata.set_delay_type(proto::DELAY_TYPE_FINISHED_PARSING);
dase_metadata.SerializeToString(any_metadata.mutable_value());
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
base::Optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
EXPECT_FALSE(parsed_dase_metadata.has_value());
}
TEST(OptimizationMetadataTest, ParsedMetadataMismatchedTypeTest) {
proto::Any any_metadata;
any_metadata.set_type_url("type.googleapis.com/com.foo.Whatever");
proto::DelayAsyncScriptExecutionMetadata dase_metadata;
dase_metadata.set_delay_type(proto::DELAY_TYPE_FINISHED_PARSING);
dase_metadata.SerializeToString(any_metadata.mutable_value());
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
base::Optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
EXPECT_FALSE(parsed_dase_metadata.has_value());
}
TEST(OptimizationMetadataTest, ParsedMetadataNotSerializableTest) {
proto::Any any_metadata;
any_metadata.set_type_url(
"type.googleapis.com/com.foo.DelayAsyncScriptExecutionMetadata");
any_metadata.set_value("12345678garbage");
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
base::Optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
EXPECT_FALSE(parsed_dase_metadata.has_value());
}
TEST(OptimizationMetadataTest, ParsedMetadataTest) {
proto::Any any_metadata;
any_metadata.set_type_url(
"type.googleapis.com/com.foo.DelayAsyncScriptExecutionMetadata");
proto::DelayAsyncScriptExecutionMetadata dase_metadata;
dase_metadata.set_delay_type(proto::DELAY_TYPE_FINISHED_PARSING);
dase_metadata.SerializeToString(any_metadata.mutable_value());
OptimizationMetadata optimization_metadata;
optimization_metadata.set_any_metadata(any_metadata);
base::Optional<proto::DelayAsyncScriptExecutionMetadata>
parsed_dase_metadata =
optimization_metadata
.ParsedMetadata<proto::DelayAsyncScriptExecutionMetadata>();
EXPECT_TRUE(parsed_dase_metadata.has_value());
EXPECT_EQ(parsed_dase_metadata->delay_type(),
proto::DELAY_TYPE_FINISHED_PARSING);
}
} // namespace optimization_guide
......@@ -203,6 +203,7 @@ message Optimization {
LoadingPredictorMetadata loading_predictor_metadata = 13;
DelayAsyncScriptExecutionMetadata delay_async_script_execution_metadata =
14;
Any any_metadata = 15;
}
}
......@@ -338,3 +339,11 @@ message Version {
// The source from which the hint was served from.
optional HintSource hint_source = 3;
}
message Any {
// A URL/resource name that uniquely identifies the type of the serialized
// protocol buffer message.
optional string type_url = 1;
// Must be a valid serialized protocol buffer of the above specified type.
optional bytes value = 2;
}
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