Skip to content

Commit

Permalink
PCM: Allow measurement of links in nested, cross-site iframes
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=229204
<rdar://problem/82310386>

Reviewed by Alex Christensen.

Developers have said it would be great to allow measurement of links served in
nested, cross-site iframes on the click source. The click still count as if it
happened on the first party click source site, and any attribution report still
goes to that first party. This change enables the *serving* of measurable links
in nested, cross-site iframes.

The standards issue where this was discussed:
privacycg/private-click-measurement#7

Source/WebCore:

Test: http/tests/privateClickMeasurement/store-private-click-measurement-nested.html

* html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::parsePrivateClickMeasurement const):
    Removed the block for nested, cross-site iframes.

LayoutTests:

* http/tests/privateClickMeasurement/resources/nestedTargetLink.html: Added.
* http/tests/privateClickMeasurement/store-private-click-measurement-nested-expected.txt: Added.
* http/tests/privateClickMeasurement/store-private-click-measurement-nested.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@283593 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
wilander@apple.com committed Oct 6, 2021
1 parent 7007bd3 commit 6745529
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 10 deletions.
21 changes: 21 additions & 0 deletions LayoutTests/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
2021-10-05 John Wilander <wilander@apple.com>

PCM: Allow measurement of links in nested, cross-site iframes
https://bugs.webkit.org/show_bug.cgi?id=229204
<rdar://problem/82310386>

Reviewed by Alex Christensen.

Developers have said it would be great to allow measurement of links served in
nested, cross-site iframes on the click source. The click still count as if it
happened on the first party click source site, and any attribution report still
goes to that first party. This change enables the *serving* of measurable links
in nested, cross-site iframes.

The standards issue where this was discussed:
https://github.com/privacycg/private-click-measurement/issues/7

* http/tests/privateClickMeasurement/resources/nestedTargetLink.html: Added.
* http/tests/privateClickMeasurement/store-private-click-measurement-nested-expected.txt: Added.
* http/tests/privateClickMeasurement/store-private-click-measurement-nested.html: Added.

2021-10-05 Fujii Hironori <Hironori.Fujii@sony.com>

[WinCairo] Unreviewed test gardening after r283550
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Nested target link</title>
</head>
<body>
<a style="font-size: xxx-large;" target="_top" href="http://localhost:8000/privateClickMeasurement/store-private-click-measurement-nested.html?stepTwo" attributionsourceid="3" attributiondestination="http://localhost:8000">Link</a><br>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Tests storage of private click measurement with nested links.

Unattributed Private Click Measurements:
WebCore::PrivateClickMeasurement 1
Source site: 127.0.0.1
Attribute on site: localhost
Source ID: 3
No attribution trigger data.
Application bundle identifier: testBundleID
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<!DOCTYPE html> <!-- webkit-test-runner [ useFlexibleViewport=true ] -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<script src="resources/util.js"></script>
<script src="/js-test-resources/ui-helper.js"></script>
</head>
<body onload="setTimeout(runTest, 0)">
<div id="description">Tests storage of private click measurement with nested links.</div>
<div id="output"></div>
<script>
prepareTest();

function activateLink() {
let element = document.getElementById("targetFrame");
let centerX = element.offsetLeft + element.offsetWidth / 2;
let centerY = element.offsetTop + element.offsetHeight / 2;
if (!UIHelper) {
document.getElementById("output").innerText = "FAIL No UIHelper.";
tearDownAndFinish();
}
UIHelper.activateAt(centerX, centerY).then(
function () {
},
function () {
document.getElementById("output").innerText = "FAIL Promise rejected.";
}
);
}

function runTest() {
if (window.testRunner) {
if (window.location.search === "?stepTwo") {
testRunner.dumpPrivateClickMeasurement();
testRunner.setPrivateClickMeasurementAppBundleIDForTesting("");
tearDownAndFinish();
} else {
testRunner.setPrivateClickMeasurementAppBundleIDForTesting("testBundleID");
let iframeElement = document.createElement("iframe");
iframeElement.setAttribute("sandbox", "allow-scripts allow-top-navigation");
iframeElement.id = "targetFrame";
iframeElement.width = "50px";
iframeElement.height = "50px";
iframeElement.onload = activateLink;
iframeElement.src = "http://localhost:8000/privateClickMeasurement/resources/nestedTargetLink.html";
document.body.appendChild(iframeElement);
}
} else {
document.getElementById("output").innerText = "FAIL No testRunner.";
}
}
</script>
</body>
</html>
23 changes: 23 additions & 0 deletions Source/WebCore/ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,26 @@
2021-10-05 John Wilander <wilander@apple.com>

PCM: Allow measurement of links in nested, cross-site iframes
https://bugs.webkit.org/show_bug.cgi?id=229204
<rdar://problem/82310386>

Reviewed by Alex Christensen.

Developers have said it would be great to allow measurement of links served in
nested, cross-site iframes on the click source. The click still count as if it
happened on the first party click source site, and any attribution report still
goes to that first party. This change enables the *serving* of measurable links
in nested, cross-site iframes.

The standards issue where this was discussed:
https://github.com/privacycg/private-click-measurement/issues/7

Test: http/tests/privateClickMeasurement/store-private-click-measurement-nested.html

* html/HTMLAnchorElement.cpp:
(WebCore::HTMLAnchorElement::parsePrivateClickMeasurement const):
Removed the block for nested, cross-site iframes.

2021-10-05 Aditya Keerthi <akeerthi@apple.com>

[iOS] Transcode videos selected from UIImagePickerController
Expand Down
22 changes: 12 additions & 10 deletions Source/WebCore/html/HTMLAnchorElement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -402,8 +402,9 @@ std::optional<PrivateClickMeasurement> HTMLAnchorElement::parsePrivateClickMeasu
using SourceSite = PrivateClickMeasurement::SourceSite;
using AttributionDestinationSite = PrivateClickMeasurement::AttributionDestinationSite;

RefPtr<Frame> frame = document().frame();
auto* page = document().page();
if (!page || page->sessionID().isEphemeral()
if (!frame ||!page || page->sessionID().isEphemeral()
|| !document().settings().privateClickMeasurementEnabled()
|| !UserGestureIndicator::processingUserGesture())
return std::nullopt;
Expand All @@ -421,12 +422,6 @@ std::optional<PrivateClickMeasurement> HTMLAnchorElement::parsePrivateClickMeasu
return std::nullopt;
}

RefPtr<Frame> frame = document().frame();
if (!frame || !frame->isMainFrame()) {
document().addConsoleMessage(MessageSource::Other, MessageLevel::Warning, "Private Click Measurement is only supported in the main frame."_s);
return std::nullopt;
}

auto attributionSourceID = parseHTMLNonNegativeInteger(attributionSourceIDAttr);
if (!attributionSourceID) {
document().addConsoleMessage(MessageSource::Other, MessageLevel::Warning, "attributionsourceid is not a non-negative integer which is required for Private Click Measurement."_s);
Expand All @@ -444,8 +439,15 @@ std::optional<PrivateClickMeasurement> HTMLAnchorElement::parsePrivateClickMeasu
return std::nullopt;
}

RegistrableDomain documentRegistrableDomain { document().url() };
if (documentRegistrableDomain.matches(destinationURL)) {
RegistrableDomain mainDocumentRegistrableDomain;
if (auto mainDocument = frame->mainFrame().document())
mainDocumentRegistrableDomain = RegistrableDomain { mainDocument->url() };
else {
document().addConsoleMessage(MessageSource::Other, MessageLevel::Warning, "Could not find a main document to use as source site for Private Click Measurement."_s);
return std::nullopt;
}

if (mainDocumentRegistrableDomain.matches(destinationURL)) {
document().addConsoleMessage(MessageSource::Other, MessageLevel::Warning, "attributiondestination can not be the same site as the current website."_s);
return std::nullopt;
}
Expand All @@ -455,7 +457,7 @@ std::optional<PrivateClickMeasurement> HTMLAnchorElement::parsePrivateClickMeasu
#else
String bundleID;
#endif
auto privateClickMeasurement = PrivateClickMeasurement { SourceID(attributionSourceID.value()), SourceSite(WTFMove(documentRegistrableDomain)), AttributionDestinationSite(destinationURL), bundleID, WallTime::now(), PrivateClickMeasurement::AttributionEphemeral::No };
auto privateClickMeasurement = PrivateClickMeasurement { SourceID(attributionSourceID.value()), SourceSite(WTFMove(mainDocumentRegistrableDomain)), AttributionDestinationSite(destinationURL), bundleID, WallTime::now(), PrivateClickMeasurement::AttributionEphemeral::No };

auto attributionSourceNonceAttr = attributeWithoutSynchronization(attributionsourcenonceAttr);
if (!attributionSourceNonceAttr.isEmpty()) {
Expand Down

0 comments on commit 6745529

Please sign in to comment.