Skip to content

Commit

Permalink
Add support for FrozenContext execution mode.
Browse files Browse the repository at this point in the history
Change-Id: I5a27be85e17ba45c35ec9033e67b7654c0d0548c
BUG: 1330341
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3664757
Reviewed-by: Maks Orlovich <morlovich@chromium.org>
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
Commit-Queue: Russ Hamilton <behamilton@google.com>
Cr-Commit-Position: refs/heads/main@{#1122397}
  • Loading branch information
brusshamilton authored and Chromium LUCI CQ committed Mar 27, 2023
1 parent 4d756ff commit 75d0df9
Show file tree
Hide file tree
Showing 33 changed files with 938 additions and 605 deletions.
23 changes: 15 additions & 8 deletions content/browser/interest_group/auction_runner_unittest.cc
Expand Up @@ -8505,7 +8505,7 @@ TEST_F(AuctionRunnerTest, ExecutionModeGroupByOrigin) {
// distinct groups are kept separate.
const char kScript[] = R"(
if (!('count' in globalThis))
globalThis.count = 0;
globalThis.count = 1;
function generateBid() {
++count;
return {ad: ["ad"], bid:count, render:"https://response.test/"};
Expand All @@ -8531,22 +8531,29 @@ TEST_F(AuctionRunnerTest, ExecutionModeGroupByOrigin) {
kSellerScript);

std::vector<StorageInterestGroup> bidders;
// Add 5 group-by-origin, 2 regular execution mode IGs.
for (int i = 0; i < 7; ++i) {
// Add 5 group-by-origin, 2 frozen, 2 regular execution mode IGs.
for (int i = 0; i < 9; ++i) {
StorageInterestGroup ig = MakeInterestGroup(
kBidder1, kBidder1Name + base::NumberToString(i), kBidder1Url,
/* trusted_bidding_signals_url=*/absl::nullopt,
/* trusted_bidding_signals_keys=*/{}, GURL("https://response.test/"));
ig.joining_origin = url::Origin::Create(GURL("https://sports.example.org"));
ig.interest_group.execution_mode =
i < 5 ? blink::InterestGroup::ExecutionMode::kGroupedByOriginMode
: blink::InterestGroup::ExecutionMode::kCompatibilityMode;
if (i < 5) {
ig.interest_group.execution_mode =
blink::InterestGroup::ExecutionMode::kGroupedByOriginMode;
} else if (i < 7) {
ig.interest_group.execution_mode =
blink::InterestGroup::ExecutionMode::kFrozenContext;
} else {
ig.interest_group.execution_mode =
blink::InterestGroup::ExecutionMode::kCompatibilityMode;
}
bidders.push_back(std::move(ig));
}

// Add one with different join origin.
StorageInterestGroup ig = MakeInterestGroup(
kBidder1, kBidder1Name + std::string("8"), kBidder1Url,
kBidder1, kBidder1Name + std::string("10"), kBidder1Url,
/* trusted_bidding_signals_url=*/absl::nullopt,
/* trusted_bidding_signals_keys=*/{}, GURL("https://response.test/"));
ig.joining_origin = url::Origin::Create(GURL("https://shopping.example.us"));
Expand All @@ -8559,7 +8566,7 @@ TEST_F(AuctionRunnerTest, ExecutionModeGroupByOrigin) {
EXPECT_THAT(result_.errors, testing::ElementsAre());
ASSERT_TRUE(result_.winning_group_id);
EXPECT_THAT(result_.report_urls,
testing::ElementsAre(GURL("https://adplatform.com/metrics/5")));
testing::ElementsAre(GURL("https://adplatform.com/metrics/6")));
}

// Test the case where the only bidder times out due to the
Expand Down
78 changes: 46 additions & 32 deletions content/services/auction_worklet/auction_v8_helper.cc
Expand Up @@ -563,53 +563,67 @@ v8::MaybeLocal<v8::WasmModuleObject> AuctionV8Helper::CloneWasmModule(
in->GetCompiledModule());
}

v8::MaybeLocal<v8::Value> AuctionV8Helper::RunScript(
bool AuctionV8Helper::RunScript(v8::Local<v8::Context> context,
v8::Local<v8::UnboundScript> script,
const DebugId* debug_id,
absl::optional<base::TimeDelta> script_timeout,
std::vector<std::string>& error_out) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(isolate(), context->GetIsolate());

std::string script_name = FormatScriptName(script);
DebugContextScope maybe_debug(inspector(), context, debug_id, script_name);

v8::TryCatch try_catch(isolate());
ScriptTimeoutHelper timeout_helper(this, timer_task_runner_,
script_timeout.value_or(script_timeout_));

TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data",
[&](perfetto::TracedValue trace_context) {
TraceTopLevel(script_name, std::move(trace_context));
});

v8::Local<v8::Script> local_script = script->BindToCurrentContext();

v8::MaybeLocal<v8::Value> result = local_script->Run(context);
if (try_catch.HasTerminated()) {
error_out.push_back(
base::StrCat({script_name, " top-level execution timed out."}));
return false;
}

if (try_catch.HasCaught()) {
error_out.push_back(FormatExceptionMessage(context, try_catch.Message()));
return false;
}

if (result.IsEmpty()) {
return false;
}

return true;
}

v8::MaybeLocal<v8::Value> AuctionV8Helper::CallFunction(
v8::Local<v8::Context> context,
v8::Local<v8::UnboundScript> script,
const DebugId* debug_id,
ExecMode exec_mode,
const std::string& script_name,
base::StringPiece function_name,
base::span<v8::Local<v8::Value>> args,
absl::optional<base::TimeDelta> script_timeout,
std::vector<std::string>& error_out) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK_EQ(isolate(), context->GetIsolate());

std::string script_name = FormatScriptName(script);
DebugContextScope maybe_debug(inspector(), context, debug_id, script_name);

v8::Local<v8::String> v8_function_name;
if (!CreateUtf8String(function_name).ToLocal(&v8_function_name))
return v8::MaybeLocal<v8::Value>();

v8::TryCatch try_catch(isolate());
ScriptTimeoutHelper timeout_helper(this, timer_task_runner_,
script_timeout.value_or(script_timeout_));

// Run top-level, to create the function from `script` and do any init that's
// needed.
if (exec_mode != ExecMode::kFunctionOnly) {
TRACE_EVENT1("devtools.timeline", "EvaluateScript", "data",
[&](perfetto::TracedValue trace_context) {
TraceTopLevel(script_name, std::move(trace_context));
});

v8::Local<v8::Script> local_script = script->BindToCurrentContext();

v8::MaybeLocal<v8::Value> result = local_script->Run(context);
if (try_catch.HasTerminated()) {
error_out.push_back(
base::StrCat({script_name, " top-level execution timed out."}));
return v8::MaybeLocal<v8::Value>();
}

if (try_catch.HasCaught()) {
error_out.push_back(FormatExceptionMessage(context, try_catch.Message()));
return v8::MaybeLocal<v8::Value>();
}

if (result.IsEmpty())
return v8::MaybeLocal<v8::Value>();
v8::Local<v8::String> v8_function_name;
if (!CreateUtf8String(function_name).ToLocal(&v8_function_name)) {
return v8::MaybeLocal<v8::Value>();
}

v8::Local<v8::Value> function;
Expand Down
49 changes: 32 additions & 17 deletions content/services/auction_worklet/auction_v8_helper.h
Expand Up @@ -63,9 +63,6 @@ class CONTENT_EXPORT AuctionV8Helper
// Timeout for script execution.
static const base::TimeDelta kScriptTimeout;

// Controls how much RunScript() actually executes; see there for more.
enum class ExecMode { kTopLevelAndFunction, kFunctionOnly };

// Helper class to set up v8 scopes to use Isolate. All methods expect a
// FullIsolateScope to be have been created on the current thread, and a
// context to be entered.
Expand Down Expand Up @@ -258,17 +255,35 @@ class CONTENT_EXPORT AuctionV8Helper
v8::MaybeLocal<v8::WasmModuleObject> CloneWasmModule(
v8::Local<v8::WasmModuleObject> in);

// Binds a script and runs it in the passed in context, returning the result.
// Note that the returned value could include references to objects or
// functions contained within the context, so is likely not safe to use in
// other contexts without sanitization.
// Binds a script and runs it in the passed in context, returning true if it
// succeeded.
//
// If `exec_mode` is kTopLevelAndFunction, the script body itself will be run.
// This should normally happen at least the first time the script is run in
// the given context.
// If `debug_id` is not nullptr, and a debugger connection has been
// instantiated, will notify debugger of `context`.
//
// Regardless of the mode, function `function_name` will be called passing in
// `args` as arguments.
// Assumes passed in context is the active context. Passed in context must be
// using the Helper's isolate.
//
// If `script_timeout` has no value, kScriptTimeout will be used as the
// default timeout.
//
// In case of an error sets `error_out`.
bool RunScript(v8::Local<v8::Context> context,
v8::Local<v8::UnboundScript> script,
const DebugId* debug_id,
absl::optional<base::TimeDelta> script_timeout,
std::vector<std::string>& error_out);

// Calls a bound function (by name) attached to the global context in the
// passed in context and returns the value returned by the function. Note that
// the returned value could include references to objects or functions
// contained within the context, so is likely not safe to use in other
// contexts without sanitization.
//
// `script_name` is the name of the script for debugging. Can be found by
// calling `FormatScriptName` on the `script` passed to `RunScript()`.
//
// `function_name` will be called passing in `args` as arguments.
//
// If `debug_id` is not nullptr, and a debugger connection has been
// instantiated, will notify debugger of `context`.
Expand All @@ -280,11 +295,10 @@ class CONTENT_EXPORT AuctionV8Helper
// default timeout.
//
// In case of an error sets `error_out`.
v8::MaybeLocal<v8::Value> RunScript(
v8::MaybeLocal<v8::Value> CallFunction(
v8::Local<v8::Context> context,
v8::Local<v8::UnboundScript> script,
const DebugId* debug_id,
ExecMode exec_mode,
const std::string& script_name,
base::StringPiece function_name,
base::span<v8::Local<v8::Value>> args,
absl::optional<base::TimeDelta> script_timeout,
Expand Down Expand Up @@ -345,6 +359,9 @@ class CONTENT_EXPORT AuctionV8Helper
// Helper for formatting script name for debug messages.
std::string FormatScriptName(v8::Local<v8::UnboundScript> script);

static std::string FormatExceptionMessage(v8::Local<v8::Context> context,
v8::Local<v8::Message> message);

private:
friend class base::RefCountedDeleteOnSequence<AuctionV8Helper>;
friend class base::DeleteHelper<AuctionV8Helper>;
Expand All @@ -364,8 +381,6 @@ class CONTENT_EXPORT AuctionV8Helper
void AbortDebuggerPauses(int context_group_id);
void FreeContextGroupId(int context_group_id);

static std::string FormatExceptionMessage(v8::Local<v8::Context> context,
v8::Local<v8::Message> message);
static std::string FormatValue(v8::Isolate* isolate,
v8::Local<v8::Value> val);

Expand Down

0 comments on commit 75d0df9

Please sign in to comment.