Implement ReportingObserverOptions and the |buffered| option.
As per this spec:
https://wicg.github.io/reporting/#dictdef-reportingobserveroptions
Bug: 731810
Change-Id: I50840a97c2858fd04f397fd9799156d8e1e873c5
Reviewed-on: https://chromium-review.googlesource.com/1101312
Commit-Queue: Paul Meyer <paulmeyer@chromium.org>
Reviewed-by: Nate Chapin <japhet@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568274}
diff --git a/third_party/WebKit/LayoutTests/reporting-observer/buffering.html b/third_party/WebKit/LayoutTests/reporting-observer/buffering.html
new file mode 100644
index 0000000..0368a10
--- /dev/null
+++ b/third_party/WebKit/LayoutTests/reporting-observer/buffering.html
@@ -0,0 +1,51 @@
+<!doctype html>
+<script src="../resources/testharness.js"></script>
+<script src="../resources/testharnessreport.js"></script>
+<script src="resources/intervention.js"></script>
+
+<div id="target" style="padding: 10px; background-color: blue;">
+ <p>Testing ReportingObserver's |buffered| option.</p>
+</div>
+
+<script>
+async_test(function(test) {
+ var observer1 = new ReportingObserver(function(reports, observer) {
+ test.step(function() {
+ // Both reports should be observed, since the |buffered| option is set to
+ // true.
+ assert_equals(reports.length, 2);
+ });
+
+ test.done();
+ }, { buffered: true });
+
+ // Generate two reports (deprecation and intervention), one before
+ // and one after calling observe().
+ causeIntervention();
+ observer1.observe();
+ window.webkitStorageInfo;
+ observer1.disconnect();
+}, "Buffered reports observed");
+
+
+async_test(function(test) {
+ var observer2 = new ReportingObserver(function(reports, observer) {
+ test.step(function() {
+ // Only the second report should be observed, since the |buffered| option
+ // is set to false by default.
+ assert_equals(reports.length, 1);
+ assert_equals(reports[0].type, "deprecation");
+ assert_equals(reports[0].body.id, "PrefixedWindowURL");
+ });
+
+ test.done();
+ });
+
+ // Generate two reports (deprecation and intervention), one before
+ // and one after calling observe().
+ causeIntervention();
+ observer2.observe();
+ window.webkitURL; // id = "PrefixedWindowURL"
+ observer2.disconnect();
+}, "Buffered reports not observed");
+</script>
diff --git a/third_party/blink/renderer/core/core_idl_files.gni b/third_party/blink/renderer/core/core_idl_files.gni
index 63601ab..5836b3a 100644
--- a/third_party/blink/renderer/core/core_idl_files.gni
+++ b/third_party/blink/renderer/core/core_idl_files.gni
@@ -611,6 +611,7 @@
"fetch/response_init.idl",
"fileapi/blob_property_bag.idl",
"fileapi/file_property_bag.idl",
+ "frame/reporting_observer_options.idl",
"frame/scroll_into_view_options.idl",
"frame/scroll_options.idl",
"frame/scroll_to_options.idl",
diff --git a/third_party/blink/renderer/core/frame/deprecation.cc b/third_party/blink/renderer/core/frame/deprecation.cc
index 02913ee..cfc92fa 100644
--- a/third_party/blink/renderer/core/frame/deprecation.cc
+++ b/third_party/blink/renderer/core/frame/deprecation.cc
@@ -771,9 +771,7 @@
Report* report = new Report("deprecation", document->Url().GetString(), body);
// Send the deprecation report to any ReportingObservers.
- ReportingContext* reporting_context = ReportingContext::From(document);
- if (reporting_context->ObserverExists())
- reporting_context->QueueReport(report);
+ ReportingContext::From(document)->QueueReport(report);
// Send the deprecation report to the Reporting API.
mojom::blink::ReportingServiceProxyPtr service;
diff --git a/third_party/blink/renderer/core/frame/deprecation_report_body.idl b/third_party/blink/renderer/core/frame/deprecation_report_body.idl
index a9d36bf..41b6e3d 100644
--- a/third_party/blink/renderer/core/frame/deprecation_report_body.idl
+++ b/third_party/blink/renderer/core/frame/deprecation_report_body.idl
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+// https://wicg.github.io/reporting/#deprecation-report
[
NoInterfaceObject,
diff --git a/third_party/blink/renderer/core/frame/intervention.cc b/third_party/blink/renderer/core/frame/intervention.cc
index 8b631d03..9bc1bafc 100644
--- a/third_party/blink/renderer/core/frame/intervention.cc
+++ b/third_party/blink/renderer/core/frame/intervention.cc
@@ -39,9 +39,7 @@
new Report("intervention", document->Url().GetString(), body);
// Send the intervention report to any ReportingObservers.
- ReportingContext* reporting_context = ReportingContext::From(document);
- if (reporting_context->ObserverExists())
- reporting_context->QueueReport(report);
+ ReportingContext::From(document)->QueueReport(report);
// Send the intervention report to the Reporting API.
mojom::blink::ReportingServiceProxyPtr service;
diff --git a/third_party/blink/renderer/core/frame/intervention_report_body.idl b/third_party/blink/renderer/core/frame/intervention_report_body.idl
index 0a44ecc..52f0b82 100644
--- a/third_party/blink/renderer/core/frame/intervention_report_body.idl
+++ b/third_party/blink/renderer/core/frame/intervention_report_body.idl
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-// https://github.com/WICG/reporting/blob/master/EXPLAINER.md#reportingobserver---observing-reports-from-javascript
+// https://wicg.github.io/reporting/#intervention-report
[
NoInterfaceObject,
diff --git a/third_party/blink/renderer/core/frame/reporting_context.cc b/third_party/blink/renderer/core/frame/reporting_context.cc
index d41250e..b8c64581 100644
--- a/third_party/blink/renderer/core/frame/reporting_context.cc
+++ b/third_party/blink/renderer/core/frame/reporting_context.cc
@@ -4,8 +4,9 @@
#include "third_party/blink/renderer/core/frame/reporting_context.h"
-#include "third_party/blink/public/platform/task_type.h"
+#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_observer.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
@@ -30,45 +31,34 @@
}
void ReportingContext::QueueReport(Report* report) {
- if (!ObserverExists())
- return;
+ report_buffer_.insert(report);
- reports_.push_back(report);
+ // Only the most recent 100 reports will remain buffered.
+ // https://wicg.github.io/reporting/#notify-observers
+ if (report_buffer_.size() > 100)
+ report_buffer_.RemoveFirst();
- // When the first report of a batch is queued, make a task to report the whole
- // batch (in the queue) to all ReportingObservers.
- if (reports_.size() == 1) {
- execution_context_->GetTaskRunner(TaskType::kMiscPlatformAPI)
- ->PostTask(FROM_HERE, WTF::Bind(&ReportingContext::SendReports,
- WrapWeakPersistent(this)));
- }
-}
-
-void ReportingContext::SendReports() {
- // The reports queued to be sent to callbacks are copied (and cleared) before
- // being sent to observers, since additional reports may be queued as a result
- // of the callbacks.
- auto reports_to_send = reports_;
- reports_.clear();
for (auto observer : observers_)
- observer->ReportToCallback(reports_to_send);
+ observer->QueueReport(report);
}
void ReportingContext::RegisterObserver(ReportingObserver* observer) {
observers_.insert(observer);
+ if (!observer->Buffered())
+ return;
+
+ observer->ClearBuffered();
+ for (auto report : report_buffer_)
+ observer->QueueReport(report);
}
void ReportingContext::UnregisterObserver(ReportingObserver* observer) {
observers_.erase(observer);
}
-bool ReportingContext::ObserverExists() {
- return observers_.size();
-}
-
void ReportingContext::Trace(blink::Visitor* visitor) {
visitor->Trace(observers_);
- visitor->Trace(reports_);
+ visitor->Trace(report_buffer_);
visitor->Trace(execution_context_);
Supplement<ExecutionContext>::Trace(visitor);
}
diff --git a/third_party/blink/renderer/core/frame/reporting_context.h b/third_party/blink/renderer/core/frame/reporting_context.h
index ed322d7..f75fbdef8 100644
--- a/third_party/blink/renderer/core/frame/reporting_context.h
+++ b/third_party/blink/renderer/core/frame/reporting_context.h
@@ -30,23 +30,17 @@
// already exist for the given context, one is created.
static ReportingContext* From(ExecutionContext*);
- // Queues a report to be reported to all observers.
+ // Queues a report in all registered observers.
void QueueReport(Report*);
- // Sends all queued reports to all observers.
- void SendReports();
-
void RegisterObserver(ReportingObserver*);
void UnregisterObserver(ReportingObserver*);
- // Returns whether there is at least one active ReportingObserver.
- bool ObserverExists();
-
void Trace(blink::Visitor*) override;
private:
HeapListHashSet<Member<ReportingObserver>> observers_;
- HeapVector<Member<Report>> reports_;
+ HeapListHashSet<Member<Report>> report_buffer_;
Member<ExecutionContext> execution_context_;
};
diff --git a/third_party/blink/renderer/core/frame/reporting_observer.cc b/third_party/blink/renderer/core/frame/reporting_observer.cc
index 9db714b..1caf300 100644
--- a/third_party/blink/renderer/core/frame/reporting_observer.cc
+++ b/third_party/blink/renderer/core/frame/reporting_observer.cc
@@ -4,26 +4,56 @@
#include "third_party/blink/renderer/core/frame/reporting_observer.h"
+#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/report.h"
#include "third_party/blink/renderer/core/frame/reporting_context.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
+#include "third_party/blink/renderer/platform/web_task_runner.h"
namespace blink {
ReportingObserver* ReportingObserver::Create(
ExecutionContext* execution_context,
- V8ReportingObserverCallback* callback) {
- return new ReportingObserver(execution_context, callback);
+ V8ReportingObserverCallback* callback,
+ ReportingObserverOptions options) {
+ return new ReportingObserver(execution_context, callback, options);
}
ReportingObserver::ReportingObserver(ExecutionContext* execution_context,
- V8ReportingObserverCallback* callback)
- : execution_context_(execution_context), callback_(callback) {}
+ V8ReportingObserverCallback* callback,
+ ReportingObserverOptions options)
+ : execution_context_(execution_context),
+ callback_(callback),
+ options_(options) {}
-void ReportingObserver::ReportToCallback(
- const HeapVector<Member<Report>>& reports) {
- callback_->InvokeAndReportException(this, reports, this);
+void ReportingObserver::ReportToCallback() {
+ // The reports queued to be sent to callbacks are copied (and cleared) before
+ // being sent, since additional reports may be queued as a result of the
+ // callbacks.
+ auto reports_to_send = report_queue_;
+ report_queue_.clear();
+ callback_->InvokeAndReportException(this, reports_to_send, this);
+}
+
+void ReportingObserver::QueueReport(Report* report) {
+ report_queue_.push_back(report);
+
+ // When the first report of a batch is queued, make a task to report the whole
+ // batch.
+ if (report_queue_.size() == 1) {
+ execution_context_->GetTaskRunner(TaskType::kMiscPlatformAPI)
+ ->PostTask(FROM_HERE, WTF::Bind(&ReportingObserver::ReportToCallback,
+ WrapWeakPersistent(this)));
+ }
+}
+
+bool ReportingObserver::Buffered() {
+ return options_.buffered();
+}
+
+void ReportingObserver::ClearBuffered() {
+ return options_.setBuffered(false);
}
void ReportingObserver::observe() {
@@ -37,6 +67,7 @@
void ReportingObserver::Trace(blink::Visitor* visitor) {
visitor->Trace(execution_context_);
visitor->Trace(callback_);
+ visitor->Trace(report_queue_);
ScriptWrappable::Trace(visitor);
}
diff --git a/third_party/blink/renderer/core/frame/reporting_observer.h b/third_party/blink/renderer/core/frame/reporting_observer.h
index 5c7350e4..4c282d62 100644
--- a/third_party/blink/renderer/core/frame/reporting_observer.h
+++ b/third_party/blink/renderer/core/frame/reporting_observer.h
@@ -7,6 +7,8 @@
#include "third_party/blink/renderer/bindings/core/v8/v8_reporting_observer_callback.h"
#include "third_party/blink/renderer/core/core_export.h"
+#include "third_party/blink/renderer/core/frame/report.h"
+#include "third_party/blink/renderer/core/frame/reporting_observer_options.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
@@ -20,10 +22,21 @@
public:
static ReportingObserver* Create(ExecutionContext*,
- V8ReportingObserverCallback*);
+ V8ReportingObserverCallback*,
+ ReportingObserverOptions);
- // Call the callback with reports.
- void ReportToCallback(const HeapVector<Member<Report>>& reports);
+ // Call the callback with all reports in |report_queue_|.
+ void ReportToCallback();
+
+ // Queues a report to be reported via callback soon (possibly in a batch).
+ void QueueReport(Report* report);
+
+ // Returns the state of the |buffered| option.
+ bool Buffered();
+
+ // Sets the |buffered| option to false. This should be called after queueing
+ // all buffered reports, so that they are not reported multiple times.
+ void ClearBuffered();
void observe();
void disconnect();
@@ -31,10 +44,14 @@
void Trace(blink::Visitor*) override;
private:
- explicit ReportingObserver(ExecutionContext*, V8ReportingObserverCallback*);
+ explicit ReportingObserver(ExecutionContext*,
+ V8ReportingObserverCallback*,
+ ReportingObserverOptions);
Member<ExecutionContext> execution_context_;
Member<V8ReportingObserverCallback> callback_;
+ ReportingObserverOptions options_;
+ HeapVector<Member<Report>> report_queue_;
};
} // namespace blink
diff --git a/third_party/blink/renderer/core/frame/reporting_observer.idl b/third_party/blink/renderer/core/frame/reporting_observer.idl
index f3cbb925..ef1a601c 100644
--- a/third_party/blink/renderer/core/frame/reporting_observer.idl
+++ b/third_party/blink/renderer/core/frame/reporting_observer.idl
@@ -7,7 +7,7 @@
callback ReportingObserverCallback = void (sequence<Report> reports, ReportingObserver observer);
[
- Constructor(ReportingObserverCallback callback),
+ Constructor(ReportingObserverCallback callback, optional ReportingObserverOptions options),
ConstructorCallWith=ExecutionContext,
RuntimeEnabled=ReportingObserver
] interface ReportingObserver {
diff --git a/third_party/blink/renderer/core/frame/reporting_observer_options.idl b/third_party/blink/renderer/core/frame/reporting_observer_options.idl
new file mode 100644
index 0000000..daa436e
--- /dev/null
+++ b/third_party/blink/renderer/core/frame/reporting_observer_options.idl
@@ -0,0 +1,9 @@
+// Copyright 2018 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.
+
+// https://wicg.github.io/reporting/#dictdef-reportingobserveroptions
+
+dictionary ReportingObserverOptions {
+ boolean buffered = false;
+};