Commit 6e52cf21 authored by arthursonzogni's avatar arthursonzogni Committed by Commit Bot

[COOP] access reporting [5/N] Plumb report type.

All of this is put behind a flag disabled by default.
This is mostly based on the initial prototype:
https://chromium-review.googlesource.com/c/chromium/src/+/2223934/24

Define, plumb and use the "report-type" for COOP access reporting.

COOP access reporting:
[1/N] https://chromium-review.googlesource.com/c/chromium/src/+/2264294
[2/N] https://chromium-review.googlesource.com/c/chromium/src/+/2270185
[3/N] https://chromium-review.googlesource.com/c/chromium/src/+/2270472
[4/N] https://chromium-review.googlesource.com/c/chromium/src/+/2273120
[5/N] this patch.

Bug: chromium:1090273
Change-Id: I5e51b3da6a20c85c073ea1fd84ea74557760a42f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2309433
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
Reviewed-by: default avatarCamille Lamy <clamy@chromium.org>
Reviewed-by: default avatarPâris Meuleman <pmeuleman@chromium.org>
Reviewed-by: default avatarMike West <mkwst@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790420}
parent fa695cfe
...@@ -34,8 +34,7 @@ constexpr char kViolationTypeFromDocument[] = "navigation-from-document"; ...@@ -34,8 +34,7 @@ constexpr char kViolationTypeFromDocument[] = "navigation-from-document";
constexpr char kViolationTypeToDocument[] = "navigation-to-document"; constexpr char kViolationTypeToDocument[] = "navigation-to-document";
constexpr char kViolationType[] = "violation-type"; constexpr char kViolationType[] = "violation-type";
std::string CoopValueToString( std::string ToString(network::mojom::CrossOriginOpenerPolicyValue coop_value) {
network::mojom::CrossOriginOpenerPolicyValue coop_value) {
switch (coop_value) { switch (coop_value) {
case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone: case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone:
return kUnsafeNone; return kUnsafeNone;
...@@ -48,6 +47,15 @@ std::string CoopValueToString( ...@@ -48,6 +47,15 @@ std::string CoopValueToString(
} }
} }
const char* ToString(network::mojom::CoopAccessReportType report_type) {
switch (report_type) {
case network::mojom::CoopAccessReportType::kReportAccessTo:
return "access-to-coop-page";
case network::mojom::CoopAccessReportType::kReportAccessFrom:
return "access-from-coop-page";
}
}
RenderFrameHostImpl* GetSourceRfhForCoopReporting( RenderFrameHostImpl* GetSourceRfhForCoopReporting(
RenderFrameHostImpl* current_rfh) { RenderFrameHostImpl* current_rfh) {
CHECK(current_rfh); CHECK(current_rfh);
...@@ -159,15 +167,16 @@ void CrossOriginOpenerPolicyReporter::QueueOpenerBreakageReport( ...@@ -159,15 +167,16 @@ void CrossOriginOpenerPolicyReporter::QueueOpenerBreakageReport(
body.SetString(kViolationType, is_reported_from_document body.SetString(kViolationType, is_reported_from_document
? kViolationTypeFromDocument ? kViolationTypeFromDocument
: kViolationTypeToDocument); : kViolationTypeToDocument);
body.SetString(kEffectivePolicy, body.SetString(
CoopValueToString(is_report_only ? coop_.report_only_value kEffectivePolicy,
: coop_.value)); ToString(is_report_only ? coop_.report_only_value : coop_.value));
storage_partition_->GetNetworkContext()->QueueReport( storage_partition_->GetNetworkContext()->QueueReport(
"coop", *endpoint, context_url_, /*user_agent=*/base::nullopt, "coop", *endpoint, context_url_, /*user_agent=*/base::nullopt,
std::move(body)); std::move(body));
} }
void CrossOriginOpenerPolicyReporter::QueueAccessReport( void CrossOriginOpenerPolicyReporter::QueueAccessReport(
network::mojom::CoopAccessReportType report_type,
const std::string& property) { const std::string& property) {
// Cross-Origin-Opener-Policy-Report-Only is not required to provide // Cross-Origin-Opener-Policy-Report-Only is not required to provide
// endpoints. // endpoints.
...@@ -180,15 +189,15 @@ void CrossOriginOpenerPolicyReporter::QueueAccessReport( ...@@ -180,15 +189,15 @@ void CrossOriginOpenerPolicyReporter::QueueAccessReport(
network::features::kCrossOriginOpenerPolicyAccessReporting)); network::features::kCrossOriginOpenerPolicyAccessReporting));
base::DictionaryValue body; base::DictionaryValue body;
body.SetStringPath(kViolationType, ToString(report_type));
body.SetStringPath(kDisposition, kDispositionReporting); body.SetStringPath(kDisposition, kDispositionReporting);
body.SetStringPath(kEffectivePolicy, body.SetStringPath(kEffectivePolicy,
CoopValueToString(coop_.report_only_value)); ToString(coop_.report_only_value));
body.SetStringPath(kProperty, property); body.SetStringPath(kProperty, property);
// TODO(arthursonzogni): Fill "blocked-window-url". // TODO(arthursonzogni): Fill "blocked-window-url".
// TODO(arthursonzogni): Fill "source-file". // TODO(arthursonzogni): Fill "source-file".
// TODO(arthursonzogni): Fill "line-no". // TODO(arthursonzogni): Fill "line-no".
// TODO(arthursonzogni): Fill "col-no". // TODO(arthursonzogni): Fill "col-no".
// TODO(arthursonzogni): Fill "violation-type".
storage_partition_->GetNetworkContext()->QueueReport( storage_partition_->GetNetworkContext()->QueueReport(
"coop", endpoint, context_url_, base::nullopt, std::move(body)); "coop", endpoint, context_url_, base::nullopt, std::move(body));
} }
...@@ -321,8 +330,13 @@ void CrossOriginOpenerPolicyReporter::MonitorAccesses( ...@@ -321,8 +330,13 @@ void CrossOriginOpenerPolicyReporter::MonitorAccesses(
remote_reporter; remote_reporter;
Clone(remote_reporter.InitWithNewPipeAndPassReceiver()); Clone(remote_reporter.InitWithNewPipeAndPassReceiver());
network::mojom::CoopAccessReportType report_type =
accessing_node->current_frame_host()->coop_reporter() == this
? network::mojom::CoopAccessReportType::kReportAccessFrom
: network::mojom::CoopAccessReportType::kReportAccessTo;
accessing_rfh->GetAssociatedLocalMainFrame()->InstallCoopAccessMonitor( accessing_rfh->GetAssociatedLocalMainFrame()->InstallCoopAccessMonitor(
accessed_window_token, std::move(remote_reporter)); report_type, accessed_window_token, std::move(remote_reporter));
} }
} // namespace content } // namespace content
...@@ -45,7 +45,8 @@ class CONTENT_EXPORT CrossOriginOpenerPolicyReporter final ...@@ -45,7 +45,8 @@ class CONTENT_EXPORT CrossOriginOpenerPolicyReporter final
void QueueOpenerBreakageReport(const GURL& other_url, void QueueOpenerBreakageReport(const GURL& other_url,
bool is_reported_from_document, bool is_reported_from_document,
bool is_report_only) final; bool is_report_only) final;
void QueueAccessReport(const std::string& property) final; void QueueAccessReport(network::mojom::CoopAccessReportType report_type,
const std::string& property) final;
// Returns the "previous" URL that is safe to expose. // Returns the "previous" URL that is safe to expose.
// Reference, "Next document URL for reporting" section: // Reference, "Next document URL for reporting" section:
......
...@@ -7,6 +7,11 @@ module network.mojom; ...@@ -7,6 +7,11 @@ module network.mojom;
import "url/mojom/url.mojom"; import "url/mojom/url.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom"; import "mojo/public/mojom/base/unguessable_token.mojom";
enum CoopAccessReportType {
kReportAccessFrom, // The reports are sent to the 'accessing window'.
kReportAccessTo, // The reports are sent to the 'accessed window'.
};
// Reports potential COOP violations. Implemented in the browser process. // Reports potential COOP violations. Implemented in the browser process.
// TODO(ahemery, pmeuleman): Add extra coop breakage cases as listed in // TODO(ahemery, pmeuleman): Add extra coop breakage cases as listed in
// https://docs.google.com/document/d/1zWqwI8PFrezwQpBSejIMUfdtsIYl9-h8epasdrDXVIM/edit // https://docs.google.com/document/d/1zWqwI8PFrezwQpBSejIMUfdtsIYl9-h8epasdrDXVIM/edit
...@@ -27,7 +32,7 @@ interface CrossOriginOpenerPolicyReporter { ...@@ -27,7 +32,7 @@ interface CrossOriginOpenerPolicyReporter {
// When two browsing contexts from different virtual browsing context groups // When two browsing contexts from different virtual browsing context groups
// tries to access each other, a report it sent. // tries to access each other, a report it sent.
// - |property| is the name of the access property (postMessage, open, ...). // - |property| is the name of the access property (postMessage, open, ...).
QueueAccessReport(string property); QueueAccessReport(CoopAccessReportType report_type, string property);
// Connects a new pipe to this instance. // Connects a new pipe to this instance.
Clone(pending_receiver<CrossOriginOpenerPolicyReporter> receiver); Clone(pending_receiver<CrossOriginOpenerPolicyReporter> receiver);
......
...@@ -881,6 +881,7 @@ interface LocalMainFrame { ...@@ -881,6 +881,7 @@ interface LocalMainFrame {
// Check accesses made from this window to |accessed_window|. If this happens, // Check accesses made from this window to |accessed_window|. If this happens,
// a report will be sent to |reporter|. // a report will be sent to |reporter|.
InstallCoopAccessMonitor( InstallCoopAccessMonitor(
network.mojom.CoopAccessReportType report_type,
mojo_base.mojom.UnguessableToken accessed_window, mojo_base.mojom.UnguessableToken accessed_window,
pending_remote<network.mojom.CrossOriginOpenerPolicyReporter> reporter); pending_remote<network.mojom.CrossOriginOpenerPolicyReporter> reporter);
}; };
......
...@@ -426,12 +426,14 @@ void DOMWindow::PostMessageForTesting( ...@@ -426,12 +426,14 @@ void DOMWindow::PostMessageForTesting(
} }
void DOMWindow::InstallCoopAccessMonitor( void DOMWindow::InstallCoopAccessMonitor(
network::mojom::blink::CoopAccessReportType report_type,
LocalFrame* accessing_frame, LocalFrame* accessing_frame,
mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter> mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter>
pending_reporter) { pending_reporter) {
CoopAccessMonitor monitor; CoopAccessMonitor monitor;
DCHECK(accessing_frame->IsMainFrame()); DCHECK(accessing_frame->IsMainFrame());
monitor.report_type = report_type;
monitor.accessing_main_frame = accessing_frame->GetFrameToken(); monitor.accessing_main_frame = accessing_frame->GetFrameToken();
// TODO(arthursonzogni): Clean coop_access_monitor_ when a reporter is gone. // TODO(arthursonzogni): Clean coop_access_monitor_ when a reporter is gone.
...@@ -465,10 +467,8 @@ void DOMWindow::ReportCoopAccess(v8::Isolate* isolate, ...@@ -465,10 +467,8 @@ void DOMWindow::ReportCoopAccess(v8::Isolate* isolate,
// TODO(arthursonzogni): Capture and send the SourceLocation. // TODO(arthursonzogni): Capture and send the SourceLocation.
// TODO(arthursonzogni): Send the blocked-window-url. // TODO(arthursonzogni): Send the blocked-window-url.
// TODO(arthursonzogni): Send whether this was access-to-coop or
// access-from-coop.
it->reporter->QueueAccessReport(property_name); it->reporter->QueueAccessReport(it->report_type, property_name);
// TODO(arthursonzogni): In the access-from-coop case, dispatch a // TODO(arthursonzogni): In the access-from-coop case, dispatch a
// reportingObserver event. // reportingObserver event.
......
...@@ -137,6 +137,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData { ...@@ -137,6 +137,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData {
// Check accesses from |accessing_frame| and every same-origin iframe toward // Check accesses from |accessing_frame| and every same-origin iframe toward
// this window. A report is sent to |reporter| when this happens. // this window. A report is sent to |reporter| when this happens.
void InstallCoopAccessMonitor( void InstallCoopAccessMonitor(
network::mojom::blink::CoopAccessReportType report_type,
LocalFrame* accessing_frame, LocalFrame* accessing_frame,
mojo::PendingRemote< mojo::PendingRemote<
network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter); network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter);
...@@ -183,6 +184,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData { ...@@ -183,6 +184,7 @@ class CORE_EXPORT DOMWindow : public EventTargetWithInlineData {
// Check accesses made toward this window from |accessing_main_frame|. If this // Check accesses made toward this window from |accessing_main_frame|. If this
// happens a report will sent to |reporter|. // happens a report will sent to |reporter|.
struct CoopAccessMonitor { struct CoopAccessMonitor {
network::mojom::blink::CoopAccessReportType report_type;
base::UnguessableToken accessing_main_frame; base::UnguessableToken accessing_main_frame;
mojo::Remote<network::mojom::blink::CrossOriginOpenerPolicyReporter> mojo::Remote<network::mojom::blink::CrossOriginOpenerPolicyReporter>
reporter; reporter;
......
...@@ -2380,6 +2380,7 @@ void LocalFrame::GetStringForRange(const gfx::Range& range, ...@@ -2380,6 +2380,7 @@ void LocalFrame::GetStringForRange(const gfx::Range& range,
#endif #endif
void LocalFrame::InstallCoopAccessMonitor( void LocalFrame::InstallCoopAccessMonitor(
network::mojom::blink::CoopAccessReportType report_type,
const base::UnguessableToken& accessed_window, const base::UnguessableToken& accessed_window,
mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter> mojo::PendingRemote<network::mojom::blink::CrossOriginOpenerPolicyReporter>
reporter) { reporter) {
...@@ -2388,7 +2389,7 @@ void LocalFrame::InstallCoopAccessMonitor( ...@@ -2388,7 +2389,7 @@ void LocalFrame::InstallCoopAccessMonitor(
if (!accessed_frame) if (!accessed_frame)
return; return;
accessed_frame->DomWindow()->InstallCoopAccessMonitor(this, accessed_frame->DomWindow()->InstallCoopAccessMonitor(report_type, this,
std::move(reporter)); std::move(reporter));
} }
......
...@@ -620,6 +620,7 @@ class CORE_EXPORT LocalFrame final ...@@ -620,6 +620,7 @@ class CORE_EXPORT LocalFrame final
GetStringForRangeCallback callback) final; GetStringForRangeCallback callback) final;
#endif #endif
void InstallCoopAccessMonitor( void InstallCoopAccessMonitor(
network::mojom::blink::CoopAccessReportType report_type,
const base::UnguessableToken& accessed_window, const base::UnguessableToken& accessed_window,
mojo::PendingRemote< mojo::PendingRemote<
network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter) network::mojom::blink::CrossOriginOpenerPolicyReporter> reporter)
......
This is a testharness.js-based test.
FAIL Opener accesses openee (COOP-RO+COEP). Report to openee assert_not_equals: Report not received got disallowed value "timeout"
Harness: the test ran to completion.
This is a testharness.js-based test. This is a testharness.js-based test.
FAIL Openee (COOP-RO+COEP) accesses opener. Report to openee assert_not_equals: Report not received got disallowed value "timeout" FAIL Openee (COOP-RO+COEP) accesses opener. Report to openee promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'includes' of undefined"
Harness: the test ran to completion. Harness: the test ran to completion.
This is a testharness.js-based test. This is a testharness.js-based test.
FAIL cross-origin > w => w.blur() assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.blur()
FAIL cross-origin > w => w.close() assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.close()
FAIL cross-origin > w => w.closed assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.closed
FAIL cross-origin > w => w.focus() assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.focus()
FAIL cross-origin > w => w.frames assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.frames
FAIL cross-origin > w => w[0] assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w[0] assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w[0] = "" assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w[0] = "" assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w.length assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.length
FAIL cross-origin > w => w.location assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w.location assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w.location = "#" assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w.location = "#" assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w["test"] assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w["test"] assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w["test"] = "" assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w["test"] = "" assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w.opener assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.opener
FAIL cross-origin > w => w.opener = "" assert_not_equals: Report not received got disallowed value "timeout" FAIL cross-origin > w => w.opener = "" assert_not_equals: Report not received got disallowed value "timeout"
FAIL cross-origin > w => w.postMessage("") assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.postMessage("")
FAIL cross-origin > w => w.postMessage("", "") assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.postMessage("", "")
FAIL cross-origin > w => w.self assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.self
FAIL cross-origin > w => w.top assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.top
FAIL cross-origin > w => w.window assert_not_equals: Report not received got disallowed value "timeout" PASS cross-origin > w => w.window
FAIL same-site > w => w.blur() assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.blur() assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.close() assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.close() assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.closed assert_not_equals: Report not received got disallowed value "timeout" PASS same-site > w => w.closed
FAIL same-site > w => w.focus() assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.focus() assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.frames assert_not_equals: Report not received got disallowed value "timeout" PASS same-site > w => w.frames
FAIL same-site > w => w[0] assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w[0] assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w[0] = "" assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w[0] = "" assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.length assert_not_equals: Report not received got disallowed value "timeout" PASS same-site > w => w.length
FAIL same-site > w => w.location assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.location assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.location = "#" assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.location = "#" assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w["test"] assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w["test"] assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w["test"] = "" assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w["test"] = "" assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.opener assert_not_equals: Report not received got disallowed value "timeout" PASS same-site > w => w.opener
FAIL same-site > w => w.opener = "" assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.opener = "" assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.postMessage("") assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.postMessage("") assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.postMessage("", "") assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.postMessage("", "") assert_not_equals: Report not received got disallowed value "timeout"
FAIL same-site > w => w.self assert_not_equals: Report not received got disallowed value "timeout" PASS same-site > w => w.self
FAIL same-site > w => w.top assert_not_equals: Report not received got disallowed value "timeout" PASS same-site > w => w.top
FAIL same-site > w => w.window assert_not_equals: Report not received got disallowed value "timeout" FAIL same-site > w => w.window assert_not_equals: Report not received got disallowed value "timeout"
Harness: the test ran to completion. Harness: the test ran to completion.
...@@ -47,7 +47,7 @@ origin.forEach(([origin_name, origin]) => { ...@@ -47,7 +47,7 @@ origin.forEach(([origin_name, origin]) => {
const reportTo = reportToHeaders(report_token); const reportTo = reportToHeaders(report_token);
const openee_url = origin+ executor_path + const openee_url = origin+ executor_path +
reportTo.header + reportTo.coopSameOriginHeader + coep_header + reportTo.header + reportTo.coopReportOnlySameOriginHeader + coep_header +
`&uuid=${executor_token}`; `&uuid=${executor_token}`;
const openee = window.open(openee_url); const openee = window.open(openee_url);
t.add_cleanup(() => send(executor_token, "window.close()")) t.add_cleanup(() => send(executor_token, "window.close()"))
......
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