1/N Add fuzzer for Protected Audience browser mojo API
In this CL, add the fuzzer logic and seed corpus needed to fuzz the JoinInterestGroup() Mojo API. All code involved in joining interest groups, including writing to the database, should be covered by fuzzer logic and basic_join.textproto seed corpus in this CL. While the fuzzer as-is will try to randomly invoke all methods in AdAuctionService, the infrastructure to allow deeper coverage into other the other AdAuctionService methods (such as, responding to auction network requests with valid scripts, etc.) will come in follow-up CLs. MojoLPM docs: https://chromium.googlesource.com/chromium/src/+/main/mojo/docs/mojolpm.md Bug: 1517411 Change-Id: I2831d7c55e250ddbaffca1f0a3935abd4fa396d0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5230380 Reviewed-by: Matt Menke <mmenke@chromium.org> Reviewed-by: Chris Bookholt <bookholt@chromium.org> Reviewed-by: Jonathan Metzman <metzman@chromium.org> Reviewed-by: Paul Semel <paulsemel@chromium.org> Commit-Queue: Caleb Raitto <caraitto@chromium.org> Cr-Commit-Position: refs/heads/main@{#1257537}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
ad0292f204
commit
c729f7c7df
@@ -41,6 +41,7 @@ source_set("browser") {
|
||||
"//content/app:*",
|
||||
"//content/public/browser:browser_sources",
|
||||
"//content/test/fuzzer:ad_auction_headers_util_fuzzer",
|
||||
"//content/test/fuzzer:ad_auction_service_mojolpm_fuzzer",
|
||||
"//content/test/fuzzer:browser_accessibility_fuzzer",
|
||||
"//content/test/fuzzer:clipboard_host_mojolpm_fuzzer",
|
||||
"//content/test/fuzzer:first_party_set_parser_fuzzer_support",
|
||||
|
@@ -9,4 +9,7 @@ specific_include_rules = {
|
||||
".*_unittest\.cc": [
|
||||
"+content/services/auction_worklet",
|
||||
],
|
||||
".*_fuzzer.cc": [
|
||||
"+third_party/libprotobuf-mutator/src/src/libfuzzer",
|
||||
],
|
||||
}
|
||||
|
@@ -0,0 +1,311 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// A MojoLPM fuzzer targeting the public API surfaces of the Protected Audiences
|
||||
// API.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <optional>
|
||||
#include <utility>
|
||||
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/functional/callback.h"
|
||||
#include "base/functional/callback_helpers.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/no_destructor.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/test/scoped_feature_list.h"
|
||||
#include "components/aggregation_service/features.h"
|
||||
#include "content/browser/interest_group/ad_auction_service_impl.h"
|
||||
#include "content/browser/interest_group/ad_auction_service_mojolpm_fuzzer.pb.h"
|
||||
#include "content/browser/interest_group/interest_group_features.h"
|
||||
#include "content/browser/renderer_host/render_frame_host_impl.h"
|
||||
#include "content/common/features.h"
|
||||
#include "content/public/browser/browser_context.h"
|
||||
#include "content/public/browser/content_browser_client.h"
|
||||
#include "content/public/browser/privacy_sandbox_invoking_api.h"
|
||||
#include "content/public/test/test_renderer_host.h"
|
||||
#include "content/public/test/url_loader_interceptor.h"
|
||||
#include "content/test/fuzzer/mojolpm_fuzzer_support.h"
|
||||
#include "content/test/test_content_browser_client.h"
|
||||
#include "content/test/test_render_frame_host.h"
|
||||
#include "content/test/test_web_contents.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
#include "third_party/blink/public/common/features.h"
|
||||
#include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom-mojolpm.h"
|
||||
#include "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom.h"
|
||||
#include "third_party/blink/public/mojom/interest_group/interest_group_types.mojom.h"
|
||||
#include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
class AllowInterestGroupContentBrowserClient
|
||||
: public content::TestContentBrowserClient {
|
||||
public:
|
||||
explicit AllowInterestGroupContentBrowserClient() = default;
|
||||
~AllowInterestGroupContentBrowserClient() override = default;
|
||||
|
||||
AllowInterestGroupContentBrowserClient(
|
||||
const AllowInterestGroupContentBrowserClient&) = delete;
|
||||
AllowInterestGroupContentBrowserClient& operator=(
|
||||
const AllowInterestGroupContentBrowserClient&) = delete;
|
||||
|
||||
// ContentBrowserClient overrides:
|
||||
bool IsInterestGroupAPIAllowed(content::RenderFrameHost* render_frame_host,
|
||||
InterestGroupApiOperation operation,
|
||||
const url::Origin& top_frame_origin,
|
||||
const url::Origin& api_origin) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsPrivacySandboxReportingDestinationAttested(
|
||||
content::BrowserContext* browser_context,
|
||||
const url::Origin& destination_origin,
|
||||
content::PrivacySandboxInvokingAPI invoking_api,
|
||||
bool post_impression_reporting) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsCookieDeprecationLabelAllowed(
|
||||
content::BrowserContext* browser_context) override {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// For handling network requests made by the Protected Audience API -- also
|
||||
// prevents those requests from being made to real servers.
|
||||
class NetworkResponder {
|
||||
private:
|
||||
bool RequestHandler(content::URLLoaderInterceptor::RequestParams* params) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Handles network requests.
|
||||
content::URLLoaderInterceptor network_interceptor_{
|
||||
base::BindRepeating(&NetworkResponder::RequestHandler,
|
||||
base::Unretained(this))};
|
||||
};
|
||||
|
||||
const char* const kCmdline[] = {"ad_auction_service_mojolpm_fuzzer", nullptr};
|
||||
|
||||
content::mojolpm::FuzzerEnvironment& GetEnvironment() {
|
||||
static base::NoDestructor<content::mojolpm::FuzzerEnvironment> environment(
|
||||
1, kCmdline);
|
||||
return *environment;
|
||||
}
|
||||
|
||||
scoped_refptr<base::SequencedTaskRunner> GetFuzzerTaskRunner() {
|
||||
return GetEnvironment().fuzzer_task_runner();
|
||||
}
|
||||
|
||||
// Per-testcase state needed to run the interface being tested.
|
||||
//
|
||||
// The lifetime of this is scoped to a single testcase, and it is created and
|
||||
// destroyed from the fuzzer sequence (checked with `this->sequence_checker_`).
|
||||
//
|
||||
// Test cases may create one or more service instances, send Mojo messages to
|
||||
// remotes for those service instances, and run IO and UI thread tasks (the
|
||||
// fuzzer itself runs on its own thread, distinct from the UI and IO threads).
|
||||
//
|
||||
// For each input Testcase proto, SetUp() is run first. (This is why expensive
|
||||
// "stateless" initialization happens just once, in GetEnvironment(), before
|
||||
// SetUp() is run). Then, "new service" actions from the Testcase proto instruct
|
||||
// the fuzzer to create new service implementation instances; they are owned by
|
||||
// the RFH through DocumentService, and the RFH is owned by `test_adapter_`.
|
||||
// Actions use an ID to determine which service instance to use, allowing
|
||||
// control over which remote to use when running remote actions. When all the
|
||||
// actions in the current Testcase proto have been executed, TearDown() is
|
||||
// called, and then this AdAuctionServiceTestcase is destroyed. After that, the
|
||||
// process repeats with the next Testcase proto input.
|
||||
class AdAuctionServiceTestcase
|
||||
: public ::mojolpm::Testcase<
|
||||
content::fuzzing::ad_auction_service::proto::Testcase,
|
||||
content::fuzzing::ad_auction_service::proto::Action> {
|
||||
public:
|
||||
using ProtoTestcase = content::fuzzing::ad_auction_service::proto::Testcase;
|
||||
using ProtoAction = content::fuzzing::ad_auction_service::proto::Action;
|
||||
explicit AdAuctionServiceTestcase(
|
||||
const content::fuzzing::ad_auction_service::proto::Testcase& testcase);
|
||||
~AdAuctionServiceTestcase();
|
||||
|
||||
void SetUp(base::OnceClosure done_closure) override;
|
||||
void TearDown(base::OnceClosure done_closure) override;
|
||||
|
||||
void RunAction(const ProtoAction& action,
|
||||
base::OnceClosure done_closure) override;
|
||||
|
||||
private:
|
||||
void SetUpOnUIThread();
|
||||
void TearDownOnUIThread();
|
||||
|
||||
// Create and bind a new AdAuctionServiceImpl instance, and register the
|
||||
// remote with MojoLPM.
|
||||
//
|
||||
// Runs on fuzzer thread, calling CreateAdAuctionServiceImplOnUIThread() on
|
||||
// the UI thread to create the implementation.
|
||||
void AddAdAuctionService(uint32_t id, base::OnceClosure done_closure);
|
||||
void CreateAdAuctionServiceImplOnUIThread(
|
||||
mojo::PendingReceiver<blink::mojom::AdAuctionService>&& receiver);
|
||||
|
||||
// All the below fields must be accessed on the UI thread.
|
||||
base::test::ScopedFeatureList feature_list_;
|
||||
base::test::ScopedFeatureList fenced_frame_feature_list_;
|
||||
|
||||
AllowInterestGroupContentBrowserClient content_browser_client_;
|
||||
raw_ptr<content::ContentBrowserClient> old_content_browser_client_ = nullptr;
|
||||
content::mojolpm::RenderViewHostTestHarnessAdapter test_adapter_;
|
||||
raw_ptr<content::TestRenderFrameHost> render_frame_host_ = nullptr;
|
||||
|
||||
// Must be destroyed before test_adapter_::TearDown().
|
||||
std::optional<NetworkResponder> network_responder_;
|
||||
};
|
||||
|
||||
AdAuctionServiceTestcase::AdAuctionServiceTestcase(
|
||||
const ProtoTestcase& testcase)
|
||||
: Testcase<ProtoTestcase, ProtoAction>(testcase) {
|
||||
feature_list_.InitWithFeatures(
|
||||
/*enabled_features=*/
|
||||
{blink::features::kInterestGroupStorage,
|
||||
blink::features::kAdInterestGroupAPI, blink::features::kFledge,
|
||||
blink::features::kFledgeClearOriginJoinedAdInterestGroups,
|
||||
blink::features::kFledgeNegativeTargeting,
|
||||
blink::features::kPrivateAggregationApiMultipleCloudProviders,
|
||||
aggregation_service::kAggregationServiceMultipleCloudProviders,
|
||||
features::kEnableUpdatingUserBiddingSignals,
|
||||
features::kEnableUpdatingExecutionModeToFrozenContext},
|
||||
/*disabled_features=*/{});
|
||||
fenced_frame_feature_list_.InitAndEnableFeatureWithParameters(
|
||||
blink::features::kFencedFrames, {{"implementation_type", "mparch"}});
|
||||
test_adapter_.SetUp();
|
||||
network_responder_.emplace();
|
||||
}
|
||||
|
||||
AdAuctionServiceTestcase::~AdAuctionServiceTestcase() {
|
||||
network_responder_.reset();
|
||||
test_adapter_.TearDown();
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::RunAction(const ProtoAction& action,
|
||||
base::OnceClosure run_closure) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(this->sequence_checker_);
|
||||
const auto ThreadId_UI =
|
||||
content::fuzzing::ad_auction_service::proto::RunThreadAction_ThreadId_UI;
|
||||
const auto ThreadId_IO =
|
||||
content::fuzzing::ad_auction_service::proto::RunThreadAction_ThreadId_IO;
|
||||
switch (action.action_case()) {
|
||||
case ProtoAction::kRunThread:
|
||||
// These actions ensure that any tasks currently queued on the named
|
||||
// thread have chance to run before the fuzzer continues.
|
||||
//
|
||||
// We don't provide any particular guarantees here; this does not mean
|
||||
// that the named thread is idle, nor does it prevent any other threads
|
||||
// from running (or the consequences of any resulting callbacks, for
|
||||
// example).
|
||||
if (action.run_thread().id() == ThreadId_UI) {
|
||||
content::GetUIThreadTaskRunner({})->PostTaskAndReply(
|
||||
FROM_HERE, base::DoNothing(), std::move(run_closure));
|
||||
} else if (action.run_thread().id() == ThreadId_IO) {
|
||||
content::GetIOThreadTaskRunner({})->PostTaskAndReply(
|
||||
FROM_HERE, base::DoNothing(), std::move(run_closure));
|
||||
}
|
||||
return;
|
||||
case ProtoAction::kNewAdAuctionService:
|
||||
// Create and bind a new AdAuctionServiceImpl instance, and register the
|
||||
// remote with MojoLPM.
|
||||
AddAdAuctionService(action.new_ad_auction_service().id(),
|
||||
std::move(run_closure));
|
||||
return;
|
||||
case ProtoAction::kAdAuctionServiceRemoteAction:
|
||||
// Invoke one of the service methods on AdAuctionService, with parameters
|
||||
// specified in the ad_auction_service_remote_action() proto, on the
|
||||
// remote given by the id in the proto.
|
||||
mojolpm::HandleRemoteAction(action.ad_auction_service_remote_action());
|
||||
break;
|
||||
case ProtoAction::ACTION_NOT_SET:
|
||||
break;
|
||||
}
|
||||
GetFuzzerTaskRunner()->PostTask(FROM_HERE, std::move(run_closure));
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::SetUp(base::OnceClosure done_closure) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(this->sequence_checker_);
|
||||
|
||||
content::GetUIThreadTaskRunner({})->PostTaskAndReply(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&AdAuctionServiceTestcase::SetUpOnUIThread,
|
||||
base::Unretained(this)),
|
||||
std::move(done_closure));
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::SetUpOnUIThread() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
test_adapter_.NavigateAndCommit(GURL("https://owner.test:443"));
|
||||
render_frame_host_ =
|
||||
static_cast<content::TestWebContents*>(test_adapter_.web_contents())
|
||||
->GetPrimaryMainFrame();
|
||||
render_frame_host_->InitializeRenderFrameIfNeeded();
|
||||
old_content_browser_client_ =
|
||||
SetBrowserClientForTesting(&content_browser_client_);
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::TearDown(base::OnceClosure done_closure) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(this->sequence_checker_);
|
||||
content::GetUIThreadTaskRunner({})->PostTaskAndReply(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&AdAuctionServiceTestcase::TearDownOnUIThread,
|
||||
base::Unretained(this)),
|
||||
std::move(done_closure));
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::TearDownOnUIThread() {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
SetBrowserClientForTesting(old_content_browser_client_);
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::AddAdAuctionService(
|
||||
uint32_t id,
|
||||
base::OnceClosure run_closure) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(this->sequence_checker_);
|
||||
mojo::Remote<blink::mojom::AdAuctionService> remote;
|
||||
auto receiver = remote.BindNewPipeAndPassReceiver();
|
||||
mojolpm::GetContext()->AddInstance(id, std::move(remote));
|
||||
content::GetUIThreadTaskRunner({})->PostTaskAndReply(
|
||||
FROM_HERE,
|
||||
base::BindOnce(
|
||||
&AdAuctionServiceTestcase::CreateAdAuctionServiceImplOnUIThread,
|
||||
base::Unretained(this), std::move(receiver)),
|
||||
std::move(run_closure));
|
||||
}
|
||||
|
||||
void AdAuctionServiceTestcase::CreateAdAuctionServiceImplOnUIThread(
|
||||
mojo::PendingReceiver<blink::mojom::AdAuctionService>&& receiver) {
|
||||
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
content::AdAuctionServiceImpl::CreateMojoService(render_frame_host_,
|
||||
std::move(receiver));
|
||||
}
|
||||
|
||||
DEFINE_BINARY_PROTO_FUZZER(
|
||||
const content::fuzzing::ad_auction_service::proto::Testcase&
|
||||
proto_testcase) {
|
||||
if (!proto_testcase.actions_size() || !proto_testcase.sequences_size() ||
|
||||
!proto_testcase.sequence_indexes_size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
GetEnvironment();
|
||||
|
||||
AdAuctionServiceTestcase testcase(proto_testcase);
|
||||
|
||||
base::RunLoop main_run_loop;
|
||||
GetFuzzerTaskRunner()->PostTask(
|
||||
FROM_HERE,
|
||||
base::BindOnce(&mojolpm::RunTestcase<AdAuctionServiceTestcase>,
|
||||
base::Unretained(&testcase), GetFuzzerTaskRunner(),
|
||||
main_run_loop.QuitClosure()));
|
||||
main_run_loop.Run();
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
// Copyright 2024 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Message format for the MojoLPM fuzzer for the AdAuctionService interface.
|
||||
|
||||
syntax = "proto2";
|
||||
|
||||
package content.fuzzing.ad_auction_service.proto;
|
||||
|
||||
import "third_party/blink/public/mojom/interest_group/ad_auction_service.mojom.mojolpm.proto";
|
||||
|
||||
// Bind a new AdAuctionService remote
|
||||
message NewAdAuctionServiceAction {
|
||||
required uint32 id = 1;
|
||||
}
|
||||
|
||||
// Run the specific sequence for (an indeterminate) period. This is not
|
||||
// intended to create a specific ordering, but to allow the fuzzer to delay a
|
||||
// later task until previous tasks have completed.
|
||||
message RunThreadAction {
|
||||
enum ThreadId {
|
||||
IO = 0;
|
||||
UI = 1;
|
||||
}
|
||||
|
||||
required ThreadId id = 1;
|
||||
}
|
||||
|
||||
// Actions that can be performed by the fuzzer.
|
||||
message Action {
|
||||
oneof action {
|
||||
NewAdAuctionServiceAction new_ad_auction_service = 1;
|
||||
RunThreadAction run_thread = 2;
|
||||
mojolpm.blink.mojom.AdAuctionService.RemoteAction
|
||||
ad_auction_service_remote_action = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// Sequence provides a level of indirection which allows Testcase to compactly
|
||||
// express repeated sequences of actions.
|
||||
message Sequence {
|
||||
repeated uint32 action_indexes = 1 [packed = true];
|
||||
}
|
||||
|
||||
// Testcase is the top-level message type interpreted by the fuzzer.
|
||||
message Testcase {
|
||||
repeated Action actions = 1;
|
||||
repeated Sequence sequences = 2;
|
||||
repeated uint32 sequence_indexes = 3 [packed = true];
|
||||
}
|
51
content/test/data/fuzzer_corpus/ad_auction_service_mojolpm_fuzzer/basic_join.textproto
Normal file
51
content/test/data/fuzzer_corpus/ad_auction_service_mojolpm_fuzzer/basic_join.textproto
Normal file
@@ -0,0 +1,51 @@
|
||||
actions {
|
||||
new_ad_auction_service {
|
||||
id: 1
|
||||
}
|
||||
}
|
||||
actions {
|
||||
ad_auction_service_remote_action {
|
||||
id: 1
|
||||
m_join_interest_group {
|
||||
m_group {
|
||||
new {
|
||||
id: 1
|
||||
m_name: "shoes"
|
||||
m_owner: {
|
||||
new {
|
||||
id: 1
|
||||
m_scheme: "https"
|
||||
m_host: "owner.test"
|
||||
m_port: 443
|
||||
}
|
||||
}
|
||||
m_expiry {
|
||||
new {
|
||||
id: 1
|
||||
# Set a large time that's far in the future (int64 max) -- the
|
||||
# browser will clamp this to the max expiration.
|
||||
m_internal_value: 0x7FFFFFFFFFFFFFFF
|
||||
}
|
||||
}
|
||||
|
||||
# The default values of required fields need to be explicitly set to
|
||||
# avoid build warnings.
|
||||
m_priority: 0.0
|
||||
m_enable_bidding_signals_prioritization: false
|
||||
m_all_sellers_capabilities {
|
||||
}
|
||||
m_execution_mode: InterestGroup_ExecutionMode_kCompatibilityMode
|
||||
m_trusted_bidding_signals_slot_size_mode: InterestGroup_TrustedBiddingSignalsSlotSizeMode_kNone
|
||||
m_auction_server_request_flags {
|
||||
}
|
||||
m_max_trusted_bidding_signals_url_length: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sequences {
|
||||
action_indexes: 0
|
||||
action_indexes: 1
|
||||
}
|
||||
sequence_indexes: 0
|
@@ -423,6 +423,26 @@ mojolpm_fuzzer_test("clipboard_host_mojolpm_fuzzer") {
|
||||
proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ]
|
||||
}
|
||||
|
||||
mojolpm_fuzzer_test("ad_auction_service_mojolpm_fuzzer") {
|
||||
sources =
|
||||
[ "../../browser/interest_group/ad_auction_service_mojolpm_fuzzer.cc" ]
|
||||
|
||||
proto_source =
|
||||
"../../browser/interest_group/ad_auction_service_mojolpm_fuzzer.proto"
|
||||
testcase_proto_kind = "content.fuzzing.ad_auction_service.proto.Testcase"
|
||||
|
||||
deps = [
|
||||
":mojolpm_fuzzer_support",
|
||||
"//content/browser:browser",
|
||||
"//content/browser:for_content_tests",
|
||||
"//content/public/browser:browser_sources",
|
||||
]
|
||||
|
||||
proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ]
|
||||
|
||||
seed_corpus_sources = [ "//content/test/data/fuzzer_corpus/ad_auction_service_mojolpm_fuzzer/basic_join.textproto" ]
|
||||
}
|
||||
|
||||
if (enable_mojom_fuzzer) {
|
||||
static_library("controller_presentation_service_delegate_for_fuzzing") {
|
||||
# Should only be used in the fuzzer this was made for
|
||||
|
@@ -193,6 +193,9 @@ these:
|
||||
* ParseUpdateJson in interest_group_update_manager.cc
|
||||
* Update AdAuctionServiceImplTest.UpdateAllUpdatableFields
|
||||
|
||||
If the new field is a required Mojo field, set a value for it in all the
|
||||
texprotos in the ad_auction_service_mojolpm_fuzzer/ directory.
|
||||
|
||||
See crrev.com/c/3517534 for an example (adding the priority field), and also
|
||||
remember to update bidder_worklet.cc too.
|
||||
|
||||
|
Reference in New Issue
Block a user