Commit eba5d1bd authored by John Delaney's avatar John Delaney Committed by Commit Bot

Stop reporting window.postMessage AsyncTasks to AdTracker

What:
Stop reporting the AsyncTask from LocalDomWindow::DisaptchPostMessage()
to the ad tracker.

Why:
A common loading flow for pages is:
 - show an ad in an iframe
 - wait for a postmessage from the ad to indicate it has finished
 - render some content

Currently, anything a non-ad script does in response to a postMessage
from an ad iframe gets considered an ad. We would like to use the
ad status of the script processing the postMessage as a sole indicator
of whether an ad is being created, rather than the frame the
message was sent from.

This is only an issue for same-renderer postMessages, as we currently
do not route any information alongside the messages sent to a different
renderer.

Bug: 1127829
Change-Id: Id3e5e8c9fa313ad50fa915c28114c7fc11bbc1f9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2416747
Commit-Queue: John Delaney <johnidel@chromium.org>
Reviewed-by: default avatarNate Chapin <japhet@chromium.org>
Reviewed-by: default avatarJosh Karlin <jkarlin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808980}
parent 17bb64ec
......@@ -491,6 +491,54 @@ TEST_F(AdTrackerSimTest, ScriptDetectedByContext) {
ad_tracker_->IsAdScriptInStack(AdTracker::StackType::kBottomAndTop));
}
TEST_F(AdTrackerSimTest, EventHandlerForPostMessageFromAdFrame_NoAdInStack) {
const char kAdScriptUrl[] = "https://example.com/ad_script.js";
SimSubresourceRequest ad_script(kAdScriptUrl, "text/javascript");
const char kVanillaUrl[] = "https://example.com/vanilla_script.js";
SimSubresourceRequest vanilla_script(kVanillaUrl, "text/javascript");
SimSubresourceRequest image_resource("https://example.com/image.gif",
"image/gif");
ad_tracker_->SetAdSuffix("ad_script.js");
// Create an iframe that's considered an ad.
main_resource_->Complete(R"(<body>
<script src='vanilla_script.js'></script>
<script src='ad_script.js'></script>
</body>)");
// Register a postMessage handler which is not considered to be ad script,
// which loads an image.
vanilla_script.Complete(R"SCRIPT(
window.addEventListener('message', e => {
image = document.createElement("img");
image.src = "image.gif";
document.body.appendChild(image);
});)SCRIPT");
// Post message from an ad iframe to the non-ad script in the parent frame.
ad_script.Complete(R"SCRIPT(
frame = document.createElement("iframe");
document.body.appendChild(frame);
iframeDocument = frame.contentWindow.document;
iframeDocument.open();
iframeDocument.write(
"<html><script>window.parent.postMessage('a', '*');</script></html>");
iframeDocument.close();
)SCRIPT");
// Wait for script to run.
base::RunLoop().RunUntilIdle();
image_resource.Complete("data");
// The image should not be considered an ad even if it was loaded in response
// to an ad initiated postMessage.
EXPECT_FALSE(
ad_tracker_->RequestWithUrlTaggedAsAd("https://example.com/image.gif"));
}
TEST_F(AdTrackerSimTest, RedirectToAdUrl) {
SimRequest::Params params;
params.redirect_url = "https://example.com/ad_script.js";
......
......@@ -942,7 +942,11 @@ void LocalDOMWindow::DispatchPostMessage(
scoped_refptr<const SecurityOrigin> intended_target_origin,
std::unique_ptr<SourceLocation> location,
const base::UnguessableToken& source_agent_cluster_id) {
probe::AsyncTask async_task(this, event->async_task_id());
// Do not report postMessage tasks to the ad tracker. This allows non-ad
// script to perform operations in response to events created by ad frames.
probe::AsyncTask async_task(this, event->async_task_id(), nullptr /* step */,
true /* enabled */,
probe::AsyncTask::AdTrackingType::kIgnore);
if (!IsCurrentlyDisplayedInFrame())
return;
......
......@@ -77,13 +77,15 @@ base::TimeDelta ProbeBase::Duration() const {
AsyncTask::AsyncTask(ExecutionContext* context,
AsyncTaskId* task,
const char* step,
bool enabled)
bool enabled,
AdTrackingType ad_tracking_type)
: debugger_(enabled && context ? ThreadDebugger::From(context->GetIsolate())
: nullptr),
task_(task),
recurring_(step),
ad_tracker_(enabled ? AdTracker::FromExecutionContext(context)
: nullptr) {
ad_tracker_(enabled && ad_tracking_type == AdTrackingType::kReport
? AdTracker::FromExecutionContext(context)
: nullptr) {
if (recurring_) {
TRACE_EVENT_FLOW_STEP0("devtools.timeline.async", "AsyncTask",
TRACE_ID_LOCAL(reinterpret_cast<uintptr_t>(task)),
......
......@@ -75,6 +75,15 @@ class CORE_EXPORT AsyncTask {
STACK_ALLOCATED();
public:
// Represents how this AsyncTask should be reported to the AdTracker.
enum class AdTrackingType {
// Don't report this task to the ad tracker.
kIgnore,
// Causes all scripts and tasks executed within this task to be considered
// executing as ads.
kReport,
};
// Args:
// context: The ExecutionContext in which the task is executed.
// task: An identifier for the AsyncTask.
......@@ -82,10 +91,12 @@ class CORE_EXPORT AsyncTask {
// indicates a recurring task with the value used for tracing events.
// enabled: Whether the task is asynchronous. If false, the task is not
// reported to the debugger and AdTracker.
// ad_tracking_type: Whether this is reported to the AdTracker.
AsyncTask(ExecutionContext* context,
AsyncTaskId* task,
const char* step = nullptr,
bool enabled = true);
bool enabled = true,
AdTrackingType ad_tracking_type = AdTrackingType::kReport);
~AsyncTask();
private:
......
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