Commit f6e4791f authored by Jan Wilken Dörrie's avatar Jan Wilken Dörrie Committed by Commit Bot

Revert "Deduplicate document policy violation report"

This reverts commit a95e3a91.

Reason for revert: Likely culprit of https://crbug.com/1087277

Original change's description:
> Deduplicate document policy violation report
> 
> Most image policies can report multiple violations for a single cause(same image not following the rule) during layout, e.g. An unoptimized-lossless-image's bpp(byte per pixel) value can change multiple times if the image is being scaled in an animation.
> 
> To avoid unnecessary duplicated reports being generated. This CL adds Hash method for DocumentPolicyViolationReport to uniquely identify each report and avoid the duplication by remembering these hash values in LocalDOMWindow and filter out reports that are in record.
> 
> Some existing web tests rely on the fact that multiple copies of same report generated in same document. This CL also worked around that to either help make reports generated unique or isolate test cases to different documents(iframes).
> 
> Bug: 924684, 926199
> Change-Id: I230e32801c77980573b5ed55064d46f94aed3060
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2078837
> Commit-Queue: Charlie Hu <chenleihu@google.com>
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
> Reviewed-by: Jason Chase <chasej@chromium.org>
> Cr-Commit-Position: refs/heads/master@{#772406}

TBR=dcheng@chromium.org,chasej@chromium.org,chenleihu@google.com

Change-Id: I92e14abb1538a8983fa0c6b1248b355fab024707
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 924684, 926199, 1087277
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2218833Reviewed-by: default avatarJan Wilken Dörrie <jdoerrie@chromium.org>
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Cr-Commit-Position: refs/heads/master@{#772589}
parent db604224
......@@ -1146,7 +1146,6 @@ jumbo_source_set("unit_tests") {
"frame/csp/string_list_directive_test.cc",
"frame/deprecation_report_body_test.cc",
"frame/document_loading_rendering_test.cc",
"frame/document_policy_violation_report_body_test.cc",
"frame/dom_timer_test.cc",
"frame/find_in_page_test.cc",
"frame/frame_overlay_test.cc",
......@@ -1159,11 +1158,9 @@ jumbo_source_set("unit_tests") {
"frame/local_frame_test.cc",
"frame/local_frame_ukm_aggregator_test.cc",
"frame/local_frame_view_test.cc",
"frame/location_report_body_test.cc",
"frame/mhtml_archive_test.cc",
"frame/mhtml_loading_test.cc",
"frame/performance_monitor_test.cc",
"frame/report_test.cc",
"frame/reporting_context_test.cc",
"frame/root_frame_viewport_test.cc",
"frame/rotation_viewport_anchor_test.cc",
......
......@@ -59,7 +59,6 @@
#include "third_party/blink/renderer/core/execution_context/agent.h"
#include "third_party/blink/renderer/core/frame/csp/content_security_policy.h"
#include "third_party/blink/renderer/core/frame/local_frame_view.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/core/frame/viewport_data.h"
#include "third_party/blink/renderer/core/html/forms/html_input_element.h"
......@@ -72,8 +71,6 @@
#include "third_party/blink/renderer/core/testing/color_scheme_helper.h"
#include "third_party/blink/renderer/core/testing/page_test_base.h"
#include "third_party/blink/renderer/core/testing/scoped_mock_overlay_scrollbars.h"
#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/scheduler/public/event_loop.h"
......@@ -110,8 +107,6 @@ void DocumentTest::SetHtmlInnerHTML(const char* html_content) {
UpdateAllLifecyclePhasesForTest();
}
class DocumentSimTest : public SimTest {};
namespace {
class TestSynchronousMutationObserver
......@@ -1503,46 +1498,4 @@ INSTANTIATE_TEST_SUITE_P(
ViewportTestCase("cover", mojom::ViewportFit::kCover),
ViewportTestCase("invalid", mojom::ViewportFit::kAuto)));
namespace {
class MockReportingContext final : public ReportingContext {
public:
explicit MockReportingContext(ExecutionContext& ec) : ReportingContext(ec) {}
void QueueReport(Report* report, const Vector<String>& endpoint) override {
report_count++;
}
unsigned report_count = 0;
};
// Test that duplicated |Report|(ReportType::DocumentPolicyViolation) are not
// send to ReportingContext.
TEST_F(DocumentSimTest, DeduplicateDocumentPolicyViolation) {
blink::ScopedDocumentPolicyForTest sdp(true);
SimRequest::Params params;
params.response_http_headers = {
{"Document-Policy", "unoptimized-lossless-images;bpp=1.0"}};
SimRequest main_resource("https://example.com", "text/html", params);
LoadURL("https://example.com");
main_resource.Finish();
ExecutionContext* ec = GetDocument().GetExecutionContext();
MockReportingContext* mock_reporting_context =
MakeGarbageCollected<MockReportingContext>(*ec);
Supplement<ExecutionContext>::ProvideTo(*ec, mock_reporting_context);
EXPECT_FALSE(GetDocument().IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.1), ReportOptions::kReportOnFailure));
EXPECT_EQ(mock_reporting_context->report_count, 1u);
EXPECT_FALSE(GetDocument().IsFeatureEnabled(
mojom::blink::DocumentPolicyFeature::kUnoptimizedLosslessImages,
PolicyValue(1.1), ReportOptions::kReportOnFailure));
EXPECT_EQ(mock_reporting_context->report_count, 1u);
}
} // namespace
} // namespace blink
......@@ -3,27 +3,9 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
namespace blink {
DocumentPolicyViolationReportBody::DocumentPolicyViolationReportBody(
const String& feature_id,
const String& message,
const String& disposition,
// URL of the resource that violated the document policy.
const String& resource_url)
: LocationReportBody(resource_url),
feature_id_(feature_id),
message_("Document policy violation: " +
(message.IsEmpty()
? feature_id + " is not allowed in this document."
: message)),
disposition_(disposition) {
DCHECK(!feature_id.IsNull());
DCHECK(!disposition.IsNull());
}
void DocumentPolicyViolationReportBody::BuildJSONValue(
V8ObjectBuilder& builder) const {
LocationReportBody::BuildJSONValue(builder);
......@@ -32,13 +14,4 @@ void DocumentPolicyViolationReportBody::BuildJSONValue(
builder.AddStringOrNull("message", message());
}
unsigned DocumentPolicyViolationReportBody::MatchId() const {
unsigned hash = LocationReportBody::MatchId();
hash = WTF::HashInts(hash, featureId().Impl()->GetHash());
hash = WTF::HashInts(hash, disposition().Impl()->GetHash());
hash =
WTF::HashInts(hash, message().IsNull() ? 0 : message().Impl()->GetHash());
return hash;
}
} // namespace blink
......@@ -21,7 +21,14 @@ class CORE_EXPORT DocumentPolicyViolationReportBody
const String& message,
const String& disposition,
// URL of the resource that violated the document policy.
const String& resource_url);
const String& resource_url)
: LocationReportBody(resource_url),
feature_id_(feature_id),
message_("Document policy violation: " +
(message.IsEmpty()
? feature_id + " is not allowed in this document."
: message)),
disposition_(disposition) {}
const String& featureId() const { return feature_id_; }
const String& disposition() const { return disposition_; }
......@@ -31,8 +38,6 @@ class CORE_EXPORT DocumentPolicyViolationReportBody
~DocumentPolicyViolationReportBody() override = default;
unsigned MatchId() const override;
private:
const String feature_id_;
const String message_;
......
// 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 "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
#include <set>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace {
// Test whether DocumentPolicyViolationReportBody::MatchId() is a pure function,
// i.e. same input will give same return value. The input values are randomly
// picked values.
TEST(DocumentPolicyViolationReportBodyMatchIdTest,
SameInputGeneratesSameMatchId) {
String feature_id = "", message = "", disposition = "", resource_url = "";
EXPECT_EQ(DocumentPolicyViolationReportBody(feature_id, message, disposition,
resource_url)
.MatchId(),
DocumentPolicyViolationReportBody(feature_id, message, disposition,
resource_url)
.MatchId());
feature_id = "unoptimized_images", message = "document policy violation",
disposition = "report", resource_url = "resource url";
EXPECT_EQ(DocumentPolicyViolationReportBody(feature_id, message, disposition,
resource_url)
.MatchId(),
DocumentPolicyViolationReportBody(feature_id, message, disposition,
resource_url)
.MatchId());
}
bool AllDistinct(const std::vector<unsigned>& hashes) {
return hashes.size() ==
std::set<unsigned>(hashes.begin(), hashes.end()).size();
}
const struct {
const char* feature_id;
const char* message;
const char* disposition;
const char* resource_url;
} kDocumentPolicyViolationReportBodyInputs[] = {
{"", "b", "c", "d"},
{"a", "", "c", "d"},
{"a", "b", "", "d"},
{"a", "b", "c", ""},
};
TEST(DocumentPolicyViolationReportBodyMatchIdTest,
DifferentInputsGenerateDifferentMatchId) {
std::vector<unsigned> hashes;
for (const auto& input : kDocumentPolicyViolationReportBodyInputs) {
hashes.push_back(
DocumentPolicyViolationReportBody(input.feature_id, input.message,
input.disposition, input.resource_url)
.MatchId());
}
EXPECT_TRUE(AllDistinct(hashes));
}
TEST(DocumentPolicyViolationReportBodyMatchIdTest,
MatchIdGeneratedShouldNotBeZero) {
std::vector<unsigned> hashes;
for (const auto& input : kDocumentPolicyViolationReportBodyInputs) {
EXPECT_NE(
DocumentPolicyViolationReportBody(input.feature_id, input.message,
input.disposition, input.resource_url)
.MatchId(),
0u);
}
}
// In |DocumentPolicyViolationReportBody|, empty message string and null message
// string are both treated as empty string and a default message will be
// generated.
TEST(DocumentPolicyViolationReportBodyMatchIdTest,
EmptyMessageGenerateSameResult) {
EXPECT_EQ(
DocumentPolicyViolationReportBody("", g_empty_string, "", "").MatchId(),
DocumentPolicyViolationReportBody("", String() /* null string */, "", "")
.MatchId());
}
} // namespace
} // namespace blink
......@@ -465,20 +465,6 @@ void LocalDOMWindow::ReportDocumentPolicyViolation(
Report* report = MakeGarbageCollected<Report>(
ReportType::kDocumentPolicyViolation, Url().GetString(), body);
// Use Hash value of both URL and DocumentPolicyViolationReportBody to
// identify different reports. There are trade offs on storing full objects
// and storing hashcode. Storing full objects takes more memory. Storing
// hashcode has the potential of hash collision.
// Since reporting is not a part critical system or have security concern,
// dropping a valid report due to hash collision seems a reasonable price
// to pay for the memory saving.
unsigned report_id = report->MatchId();
DCHECK(report_id);
if (document_policy_violation_reports_sent_.Contains(report_id))
return;
document_policy_violation_reports_sent_.insert(report_id);
// Send the document policy violation report to any ReportingObservers.
const base::Optional<std::string> endpoint =
relevant_document_policy->GetFeatureEndpoint(feature);
......
......@@ -455,11 +455,6 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
// document. This helps to count them only once per page load.
// We don't use std::bitset to avoid to include feature_policy.mojom-blink.h.
mutable Vector<bool> potentially_violated_features_;
// Tracks which document policy violation reports have already been sent in
// this document, to avoid reporting duplicates. The value stored are
// the hash of each DocumentPolicyViolationReport.
mutable HashSet<unsigned> document_policy_violation_reports_sent_;
};
template <>
......
......@@ -3,7 +3,6 @@
// found in the LICENSE file.
#include "third_party/blink/renderer/core/frame/location_report_body.h"
#include "third_party/blink/renderer/platform/wtf/hash_functions.h"
namespace blink {
......@@ -39,15 +38,4 @@ void LocationReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
}
}
unsigned LocationReportBody::MatchId() const {
const base::Optional<uint32_t> line = lineNumber(), column = columnNumber();
unsigned hash = sourceFile().IsNull() ? 0 : sourceFile().Impl()->GetHash();
hash = WTF::HashInts(hash,
line ? DefaultHash<uint32_t>::Hash::GetHash(*line) : 0);
hash = WTF::HashInts(
hash, column ? DefaultHash<uint32_t>::Hash::GetHash(*column) : 0);
return hash;
}
} // namespace blink
......@@ -56,8 +56,6 @@ class CORE_EXPORT LocationReportBody : public ReportBody {
void BuildJSONValue(V8ObjectBuilder& builder) const override;
unsigned MatchId() const override;
protected:
const String source_file_;
const base::Optional<uint32_t> line_number_;
......
// 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 "third_party/blink/renderer/core/frame/location_report_body.h"
#include <set>
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
namespace blink {
namespace {
class TestLocationReportBody : public LocationReportBody {
public:
explicit TestLocationReportBody(
const String& source_file = g_empty_string,
base::Optional<uint32_t> line_number = base::nullopt,
base::Optional<uint32_t> column_number = base::nullopt)
: LocationReportBody(source_file, line_number, column_number) {}
};
// Test whether LocationReportBody::MatchId() is a pure function, i.e. same
// input will give same return value.
TEST(LocationReportBodyMatchIdTest, SameInputGeneratesSameMatchId) {
String url = "";
base::Optional<uint32_t> line = base::nullopt, column = base::nullopt;
EXPECT_EQ(TestLocationReportBody(url, line, column).MatchId(),
TestLocationReportBody(url, line, column).MatchId());
url = "https://example.com";
line = base::make_optional<uint32_t>(0);
column = base::make_optional<uint32_t>(0);
EXPECT_EQ(TestLocationReportBody(url, line, column).MatchId(),
TestLocationReportBody(url, line, column).MatchId());
}
bool AllDistinct(const std::vector<unsigned>& hashes) {
return hashes.size() ==
std::set<unsigned>(hashes.begin(), hashes.end()).size();
}
const struct {
const char* url;
const base::Optional<uint32_t> line_number;
const base::Optional<uint32_t> column_number;
} kLocationReportBodyInputs[] = {
{"url", base::nullopt, base::nullopt},
{"url", 0, base::nullopt},
{"url", base::nullopt, 0},
{"url", 0, 0},
{"url", 1, base::nullopt},
{"url", base::nullopt, 1},
{"url", 1, 1},
};
TEST(LocationReportBodyMatchIdTest, DifferentInputsGenerateDifferentMatchId) {
std::vector<unsigned> hashes;
for (const auto& input : kLocationReportBodyInputs) {
hashes.push_back(TestLocationReportBody(input.url, input.line_number,
input.column_number)
.MatchId());
}
EXPECT_TRUE(AllDistinct(hashes));
}
TEST(LocationReportBodyMatchIdTest, MatchIdGeneratedShouldNotBeZero) {
std::vector<unsigned> hashes;
for (const auto& input : kLocationReportBodyInputs) {
EXPECT_NE(TestLocationReportBody(input.url, input.line_number,
input.column_number)
.MatchId(),
0u);
}
}
// When URL is empty, LocationReportBody would call |SourceLocation::Capture()|
// to determine the location, and ignore |line_number| and |column_number|
// specified in constructor params.
TEST(LocationReportBodyMatchIdTest,
EmptyURLGenerateSameMatchIdRegardlessOfOtherParams) {
const unsigned empty_hash =
TestLocationReportBody("", base::nullopt, base::nullopt).MatchId();
for (const auto& input : kLocationReportBodyInputs) {
EXPECT_EQ(TestLocationReportBody("", input.line_number, input.column_number)
.MatchId(),
empty_hash);
}
}
} // namespace
} // namespace blink
......@@ -22,11 +22,4 @@ ScriptValue Report::toJSON(ScriptState* script_state) const {
return builder.GetScriptValue();
}
unsigned Report::MatchId() const {
unsigned hash = body()->MatchId();
hash = WTF::HashInts(hash, url().IsNull() ? 0 : url().Impl()->GetHash());
hash = WTF::HashInts(hash, type().Impl()->GetHash());
return hash;
}
} // namespace blink
......@@ -28,9 +28,7 @@ class CORE_EXPORT Report : public ScriptWrappable {
public:
Report(const String& type, const String& url, ReportBody* body)
: type_(type), url_(url), body_(body) {
DCHECK(!type.IsNull());
}
: type_(type), url_(url), body_(body) {}
~Report() override = default;
......@@ -45,8 +43,6 @@ class CORE_EXPORT Report : public ScriptWrappable {
ScriptValue toJSON(ScriptState* script_state) const;
unsigned MatchId() const;
private:
const String type_;
const String url_;
......
......@@ -20,8 +20,6 @@ class CORE_EXPORT ReportBody : public ScriptWrappable {
// This function is public for use in Report::toJSON
virtual void BuildJSONValue(V8ObjectBuilder& builder) const = 0;
virtual unsigned MatchId() const { return 0; }
};
} // namespace blink
......
// 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 "third_party/blink/renderer/core/frame/report.h"
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/core/frame/document_policy_violation_report_body.h"
#include "third_party/blink/renderer/core/frame/location_report_body.h"
namespace blink {
namespace {
// Test whether Report::MatchId() is a pure function, i.e. same input
// will give same return value.
// The input values are randomly picked values.
TEST(ReportMatchIdTest, SameInputGeneratesSameMatchId) {
String type = ReportType::kDocumentPolicyViolation, url = "", feature_id = "",
message = "", disposition = "report", resource_url = "";
ReportBody* body = MakeGarbageCollected<DocumentPolicyViolationReportBody>(
feature_id, message, disposition, resource_url);
EXPECT_EQ(Report(type, url, body).MatchId(),
Report(type, url, body).MatchId());
type = ReportType::kDocumentPolicyViolation, url = "https://example.com",
feature_id = "font-display-late-swap", message = "document policy violation",
disposition = "enforce", resource_url = "https://example.com/resource.png";
body = MakeGarbageCollected<DocumentPolicyViolationReportBody>(
feature_id, message, disposition, resource_url);
EXPECT_EQ(Report(type, url, body).MatchId(),
Report(type, url, body).MatchId());
}
bool AllDistinct(const std::vector<unsigned>& hashes) {
return hashes.size() ==
std::set<unsigned>(hashes.begin(), hashes.end()).size();
}
const struct {
const char* feature_id;
const char* message;
const char* disposition;
const char* resource_url;
const char* url;
} kReportInputs[] = {
{"a", "b", "c", "d", ""},
{"a", "b", "c", "d", "url"},
};
TEST(ReportMatchIdTest, DifferentInputsGenerateDifferentMatchId) {
std::vector<unsigned> hashes;
for (const auto& input : kReportInputs) {
hashes.push_back(
Report(ReportType::kDocumentPolicyViolation, input.url,
MakeGarbageCollected<DocumentPolicyViolationReportBody>(
input.feature_id, input.message, input.disposition,
input.resource_url))
.MatchId());
}
EXPECT_TRUE(AllDistinct(hashes));
}
TEST(ReportMatchIdTest, MatchIdGeneratedShouldNotBeZero) {
std::vector<unsigned> hashes;
for (const auto& input : kReportInputs) {
EXPECT_NE(Report(ReportType::kDocumentPolicyViolation, input.url,
MakeGarbageCollected<DocumentPolicyViolationReportBody>(
input.feature_id, input.message, input.disposition,
input.resource_url))
.MatchId(),
0u);
}
}
} // namespace
} // namespace blink
......@@ -22,9 +22,10 @@ class ReportingObserver;
// ReportingContext processes all reports for an ExecutionContext, and serves as
// a container for all active ReportingObservers on that ExecutionContext.
class CORE_EXPORT ReportingContext : public GarbageCollected<ReportingContext>,
public mojom::blink::ReportingObserver,
public Supplement<ExecutionContext> {
class CORE_EXPORT ReportingContext final
: public GarbageCollected<ReportingContext>,
public mojom::blink::ReportingObserver,
public Supplement<ExecutionContext> {
USING_GARBAGE_COLLECTED_MIXIN(ReportingContext);
public:
......@@ -41,8 +42,7 @@ class CORE_EXPORT ReportingContext : public GarbageCollected<ReportingContext>,
void Bind(mojo::PendingReceiver<mojom::blink::ReportingObserver> receiver);
// Queues a report for the Reporting API and in all registered observers.
virtual void QueueReport(Report*,
const Vector<String>& endpoints = {"default"});
void QueueReport(Report*, const Vector<String>& endpoints = {"default"});
void RegisterObserver(blink::ReportingObserver*);
void UnregisterObserver(blink::ReportingObserver*);
......
......@@ -461,8 +461,7 @@ TEST_F(DocumentLoaderSimTest, DocumentPolicyEnforcedReportHistogramTest) {
Window().ReportDocumentPolicyViolation(
mojom::blink::DocumentPolicyFeature::kFontDisplay,
mojom::blink::PolicyDisposition::kEnforce,
"first font display violation");
mojom::blink::PolicyDisposition::kEnforce);
histogram_tester.ExpectTotalCount("Blink.UseCounter.DocumentPolicy.Enforced",
1);
......@@ -472,8 +471,7 @@ TEST_F(DocumentLoaderSimTest, DocumentPolicyEnforcedReportHistogramTest) {
// Multiple reports should be recorded multiple times.
Window().ReportDocumentPolicyViolation(
mojom::blink::DocumentPolicyFeature::kFontDisplay,
mojom::blink::PolicyDisposition::kEnforce,
"second font display violation");
mojom::blink::PolicyDisposition::kEnforce);
histogram_tester.ExpectTotalCount("Blink.UseCounter.DocumentPolicy.Enforced",
2);
......@@ -495,7 +493,7 @@ TEST_F(DocumentLoaderSimTest, DocumentPolicyReportOnlyReportHistogramTest) {
Window().ReportDocumentPolicyViolation(
mojom::blink::DocumentPolicyFeature::kFontDisplay,
mojom::blink::PolicyDisposition::kReport, "first font display violation");
mojom::blink::PolicyDisposition::kReport);
histogram_tester.ExpectTotalCount(
"Blink.UseCounter.DocumentPolicy.ReportOnly", 1);
......@@ -505,8 +503,7 @@ TEST_F(DocumentLoaderSimTest, DocumentPolicyReportOnlyReportHistogramTest) {
// Multiple reports should be recorded multiple times.
Window().ReportDocumentPolicyViolation(
mojom::blink::DocumentPolicyFeature::kFontDisplay,
mojom::blink::PolicyDisposition::kReport,
"second font display violation");
mojom::blink::PolicyDisposition::kReport);
histogram_tester.ExpectTotalCount(
"Blink.UseCounter.DocumentPolicy.ReportOnly", 2);
......
<!DOCTYPE html>
<html>
<head>
<title>Test for font-display-late-swap feature policy set to report-only</title>
<link rel="help"
href="https://github.com/w3c/webappsec-feature-policy/blob/master/policies/font-display-late-swap.md">
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<style>
</style>
</head>
<body>
<p>
Tests if the correct number of violation reports are generated and each report corresponds to this feature.
4 reports should be created out of the 6 options below (reports for all except for 'fallback' and 'optional').
</p>
<table id="container">
<tr>
<head>
<title>Test for font-display-late-swap feature policy set to report-only</title>
<link rel="help" href="https://github.com/w3c/webappsec-feature-policy/blob/master/policies/font-display-late-swap.md">
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<style>
</style>
</head>
<body>
<p>
Tests if the correct number of violation reports are generated and each report corresponds to this feature.
4 reports should be created out of the 6 options below (reports for all except for 'fallback' and 'optional').
</p>
<table id="container">
<tr>
<th>not-set</th>
<th>auto</th>
<th>block</th>
<th>swap</th>
<th>fallback</th>
<th>optional</th>
</tr>
</table>
<script>
const fontDisplayValues = ['', 'auto', 'block', 'swap', 'fallback', 'optional'];
const table = document.getElementById('container');
const t = async_test('font-display-late-swap Report Format');
</tr>
</table>
<script>
const fontDisplayValues = ['', 'auto', 'block', 'swap', 'fallback', 'optional'];
const table = document.getElementById('container');
function makeFontFaceDeclaration(family, display) {
url = '/fonts/Ahem.ttf?pipe=trickle(d1)'; // Before the swap period is over
return `@font-face { font-family: ${family}; src: url("${url}"); font-display: ${display}; }`;
}
function makeFontFaceDeclaration(family, display) {
url = '/fonts/Ahem.ttf?pipe=trickle(d1)'; // Before the swap period is over
return '@font-face { font-family: ' + family + '; src: url("' + url + '"); font-display: ' + display + '; }';
}
window.onload = () => {
let tr = document.createElement('tr');
for (let display of fontDisplayValues) {
window.onload = () => {
let tr = document.createElement('tr');
for (let display of fontDisplayValues) {
const family = display + '-face';
const rule = makeFontFaceDeclaration(family, display);
// Create a separate iframe for testing purpose.
// For same document, violation reports with same content might be deduped.
let iframe = document.createElement('iframe');
iframe.src = 'font-display-document-policy-report-only.tentative.sub.html';
iframe.onload = t.step_func(() => {
iframe.contentWindow.postMessage({
family,
rule
}, '*');
});
document.styleSheets[0].insertRule(rule, 0);
let td = document.createElement('td');
td.appendChild(iframe);
td.textContent = 'a';
td.style.fontFamily = family + ', Arial';
tr.appendChild(td);
}
table.appendChild(tr);
}
table.appendChild(tr);
}
let reportCounter = 4;
window.onmessage = t.step_func((e) => {
const reports = JSON.parse(e.data);
assert_equals(reports.length, 1);
check_report_format(reports[0]);
});
let reportCounter = 4;
let t = async_test('font-display-late-swap Report Format');
let check_report_format = (report) => {
reportCounter--;
assert_equals(report.type, 'document-policy-violation');
assert_equals(report.url, document.getElementsByTagName('iframe')[0].contentWindow.location.href);
assert_equals(report.body.featureId, 'font-display-late-swap');
assert_equals(report.body.disposition, 'report');
assert_true('sourceFile' in report.body);
assert_true('lineNumber' in report.body);
assert_true('columnNumber' in report.body);
// Test is done when we have exactly 4 reports for the following
// font-display values: not set, 'auto', 'block', 'swap'
if (reportCounter == 0) t.done();
};
</script>
</body>
let check_report_format = (reports, observer) => {
reportCounter -= reports.length;
for (let report of reports) {
assert_equals(report.type, 'document-policy-violation');
assert_equals(report.url, document.location.href, 'Report URL');
assert_equals(report.body.featureId, 'font-display-late-swap');
assert_equals(report.body.disposition, 'report');
assert_true('sourceFile' in report.body);
assert_true('lineNumber' in report.body);
assert_true('columnNumber' in report.body);
}
// Test is done when we have exactly 4 reports for the following
// font-display values: not set, 'auto', 'block', 'swap'
if (reportCounter == 0) t.done();
};
new ReportingObserver(t.step_func(check_report_format),
{types: ['document-policy-violation'], buffered: true}).observe();
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<style></style>
</head>
<body>
<p>This is a subframe with 'no-font-display-late-swap'</p>
<p id="text"></p>
</body>
<script>
window.onmessage = (e) => {
const rule = e.data.rule;
const family = e.data.family;
function send_report(reports) {
// stringify reports because report is not clonable.
e.source.postMessage(JSON.stringify(reports), '*');
}
new ReportingObserver(send_report, {
types: ['document-policy-violation'],
buffered: true
})
.observe();
document.styleSheets[0].insertRule(rule, 0);
// Trigger font display violation.
const p = document.getElementById('text');
p.textContent = 'a';
p.style.fontFamily = `${family}, Arial`;
};
</script>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Test for font-display-late-swap feature policy set to reporting</title>
<link rel="help"
href="https://github.com/w3c/webappsec-feature-policy/blob/master/policies/font-display-late-swap.md">
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<style>
</style>
</head>
<body>
<p>
Tests if the correct number of violation reports are generated and each report corresponds to this feature.
4 reports should be created out of the 6 options below (reports for all except for 'fallback' and 'optional').
</p>
<table id="container">
<tr>
<head>
<title>Test for font-display-late-swap feature policy set to reporting</title>
<link rel="help" href="https://github.com/w3c/webappsec-feature-policy/blob/master/policies/font-display-late-swap.md">
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<style>
</style>
</head>
<body>
<p>
Tests if the correct number of violation reports are generated and each report corresponds to this feature.
4 reports should be created out of the 6 options below (reports for all except for 'fallback' and 'optional').
</p>
<table id="container">
<tr>
<th>not-set</th>
<th>auto</th>
<th>block</th>
<th>swap</th>
<th>fallback</th>
<th>optional</th>
</tr>
</table>
<script>
const fontDisplayValues = ['', 'auto', 'block', 'swap', 'fallback', 'optional'];
const table = document.getElementById('container');
const t = async_test('font-display-late-swap Report Format');
</tr>
</table>
<script>
const fontDisplayValues = ['', 'auto', 'block', 'swap', 'fallback', 'optional'];
const table = document.getElementById('container');
function makeFontFaceDeclaration(family, display) {
url = '/fonts/Ahem.ttf?pipe=trickle(d1)'; // Before the swap period is over
return `@font-face { font-family: ${family}; src: url("${url}"); font-display: ${display}; }`;
}
function makeFontFaceDeclaration(family, display) {
url = '/fonts/Ahem.ttf?pipe=trickle(d1)'; // Before the swap period is over
return '@font-face { font-family: ' + family + '; src: url("' + url + '"); font-display: ' + display + '; }';
}
window.onload = () => {
let tr = document.createElement('tr');
for (let display of fontDisplayValues) {
window.onload = () => {
let tr = document.createElement('tr');
for (let display of fontDisplayValues) {
const family = display + '-face';
const rule = makeFontFaceDeclaration(family, display);
// Create a separate iframe for testing purpose.
// For same document, violation reports with same content might be deduped.
let iframe = document.createElement('iframe');
iframe.src = 'font-display-document-policy-reporting.tentative.sub.html';
iframe.onload = t.step_func(() => {
iframe.contentWindow.postMessage({
family,
rule
}, '*');
});
document.styleSheets[0].insertRule(rule, 0);
let td = document.createElement('td');
td.appendChild(iframe);
td.textContent = 'a';
td.style.fontFamily = family + ', Arial';
tr.appendChild(td);
}
table.appendChild(tr);
}
table.appendChild(tr);
}
let reportCounter = 4;
window.onmessage = t.step_func((e) => {
const reports = JSON.parse(e.data);
assert_equals(reports.length, 1);
check_report_format(reports[0]);
});
let reportCounter = 4;
let t = async_test('font-display-late-swap Report Format');
let check_report_format = (report) => {
reportCounter--;
assert_equals(report.type, 'document-policy-violation');
assert_equals(report.url, document.getElementsByTagName('iframe')[0].contentWindow.location.href);
assert_equals(report.body.featureId, 'font-display-late-swap');
assert_equals(report.body.disposition, 'enforce');
assert_true('sourceFile' in report.body);
assert_true('lineNumber' in report.body);
assert_true('columnNumber' in report.body);
// Test is done when we have exactly 4 reports for the following
// font-display values: not set, 'auto', 'block', 'swap'
if (reportCounter == 0) t.done();
};
</script>
</body>
let check_report_format = (reports, observer) => {
reportCounter -= reports.length;
for (let report of reports) {
assert_equals(report.type, 'document-policy-violation');
assert_equals(report.url, document.location.href, 'Report URL');
assert_equals(report.body.featureId, 'font-display-late-swap');
assert_equals(report.body.disposition, 'enforce');
assert_true('sourceFile' in report.body);
assert_true('lineNumber' in report.body);
assert_true('columnNumber' in report.body);
}
// Test is done when we have exactly 4 reports for the following
// font-display values: not set, 'auto', 'block', 'swap'
if (reportCounter == 0) t.done();
};
new ReportingObserver(t.step_func(check_report_format),
{types: ['document-policy-violation'], buffered: true}).observe();
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<style></style>
</head>
<body>
<p>This is a subframe with 'no-font-display-late-swap'</p>
<p id="text"></p>
</body>
<script>
window.onmessage = (e) => {
const rule = e.data.rule;
const family = e.data.family;
function send_report(reports) {
// stringify reports because report is not clonable.
e.source.postMessage(JSON.stringify(reports), '*');
}
new ReportingObserver(send_report, {
types: ['document-policy-violation'],
buffered: true
})
.observe();
document.styleSheets[0].insertRule(rule, 0);
// Trigger font display violation.
const p = document.getElementById('text');
p.textContent = 'a';
p.style.fontFamily = `${family}, Arial`;
};
</script>
</html>
\ No newline at end of file
......@@ -19,15 +19,12 @@ header("Document-Policy: oversized-images;scale=2.0");
After the resize, there should not be any violations triggered.
It is expected that non of images on page are replaced by placeholders
after resize. (content in -expected.png)
-->
<!--
Note: give each image a unique URL so that the report generated
will not be deduped.
-->
<img src="resources/green-256x256.jpg?id=1" width="100" height="128">
<img src="resources/green-256x256.jpg?id=2" style="height: 100px; width: 128px">
<img src="resources/green-256x256.jpg?id=3" width="100" height="100">
<img src="resources/green-256x256.jpg?id=4" style="height: 100px; width: 100px">
-->
<img src="resources/green-256x256.jpg" width="100" height="128">
<img src="resources/green-256x256.jpg" style="height: 100px; width: 128px">
<img src="resources/green-256x256.jpg" width="100" height="100">
<img src="resources/green-256x256.jpg" style="height: 100px; width: 100px">
<script>
runAfterLayoutAndPaint(function() {
......
......@@ -6,16 +6,14 @@ header("Document-Policy: oversized-images;scale=2.0");
<base href="resources/">
</head>
<body>
<!-- Note: give each image a unique URL so that the report generated
will not be deduped. -->
<div width="600" height="500">
<img src="green-256x256.jpg?id=1">
<img src="green-256x256.jpg?id=2" width="100" height="256">
<img src="green-256x256.jpg?id=3" style="height: 100px; width: 256px">
<img src="green-256x256.jpg?id=4" width="128" height="128" >
<img src="green-256x256.jpg?id=5" width="50" height="50">
<img src="green-256x256.jpg?id=6" style="height: 50px; weight: 50px">
<img src="green-256x256.jpg?id=7" style="height: 1cm; weight: 1cm">
<img src="green-256x256.jpg?id=8" style="height: 1cm; weight: 1cm; border-radius: 5px; border: 1px solid blue;">
<img src="green-256x256.jpg">
<img src="green-256x256.jpg" width="100" height="256">
<img src="green-256x256.jpg" style="height: 100px; width: 256px">
<img src="green-256x256.jpg" width="128" height="128" >
<img src="green-256x256.jpg" width="50" height="50">
<img src="green-256x256.jpg" style="height: 50px; weight: 50px">
<img src="green-256x256.jpg" style="height: 1cm; weight: 1cm">
<img src="green-256x256.jpg" style="height: 1cm; weight: 1cm; border-radius: 5px; border: 1px solid blue;">
</div>
</body>
......@@ -3,10 +3,8 @@ header("Document-Policy: oversized-images;scale=2.0");
?>
<!DOCTYPE html>
<style>body { margin: 0; }</style>
<!-- Note: give each image a unique URL so that the report generated
will not be deduped. -->
<img src="green-256x256.jpg?id=1" width="100" height="100">
<img src="green-256x256.jpg?id=2" style="width: 100px; height: 100px">
<img src="green-256x256.jpg" width="100" height="100">
<img src="green-256x256.jpg" style="width: 100px; height: 100px">
<script>
document.body.offsetTop;
</script>
......@@ -3,10 +3,8 @@ header("Document-Policy: oversized-images;scale=2.0");
?>
<!DOCTYPE html>
<body>
<!-- Note: give each image a unique URL so that the report generated
will not be deduped. -->
<img src="green-256x256.jpg?id=1" intrinsicsize="100 x 100" width="127" height="127">
<img srcset="green-256x256.jpg?id=2 256w" sizes="100px" width="127" height="127">
<img srcset="green-256x256.jpg?id=3 256w" sizes="100px" width="128" height="128">
<img srcset="green-256x256.jpg?id=4 256w" sizes="100px" width="129" height="129">
<img src="green-256x256.jpg" intrinsicsize="100 x 100" width="127" height="127">
<img srcset="green-256x256.jpg 256w" sizes="100px" width="127" height="127">
<img srcset="green-256x256.jpg 256w" sizes="100px" width="128" height="128">
<img srcset="green-256x256.jpg 256w" sizes="100px" width="129" height="129">
</body>
......@@ -3,10 +3,8 @@ header("Document-Policy: oversized-images;scale=2.0");
?>
<!DOCTYPE html>
<body>
<!-- Note: give each image a unique URL so that the report generated
will not be deduped. -->
<img src="green-256x256.jpg?id=1" width="128" height="128" style="border: 10px solid red;">
<img src="green-256x256.jpg?id=2" width="120" height="120" style="border: 10px solid red;">
<img src="green-256x256.jpg?id=3" width="120" height="120" style="padding: 10px;">
<img src="green-256x256.jpg?id=4" width="120" height="120" style="border: 10px solid red; padding: 5px;">
<img src="green-256x256.jpg" width="128" height="128" style="border: 10px solid red;">
<img src="green-256x256.jpg" width="120" height="120" style="border: 10px solid red;">
<img src="green-256x256.jpg" width="120" height="120" style="padding: 10px;">
<img src="green-256x256.jpg" width="120" height="120" style="border: 10px solid red; padding: 5px;">
</body>
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