Commit 6a93b00b authored by Rodney Ding's avatar Rodney Ding Committed by Commit Bot

Adding toJSON to report and report_body

- declare BuildJSONValue in report_body as virtual
- make all sub-class implement override implementation

add toJSON to report_body, making it serializable

- Includes 4 different reports
- and parent class LocationReportBody

Bug: 917945
Change-Id: I2ef281aad171ec6a477ae562fab3257847ee4f41
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1895957Reviewed-by: default avatarDavid Bokan <bokan@chromium.org>
Reviewed-by: default avatarJason Chase <chasej@chromium.org>
Commit-Queue: Rodney Ding <rodneyding@google.com>
Cr-Commit-Position: refs/heads/master@{#714244}
parent 2dc64d2e
......@@ -1205,6 +1205,7 @@ jumbo_source_set("unit_tests") {
"frame/csp/csp_source_test.cc",
"frame/csp/media_list_directive_test.cc",
"frame/csp/source_list_directive_test.cc",
"frame/deprecation_report_body_test.cc",
"frame/document_loading_rendering_test.cc",
"frame/dom_timer_test.cc",
"frame/find_in_page_test.cc",
......
......@@ -19,6 +19,7 @@ blink_core_sources("frame") {
"csp/csp_directive_list.h",
"csp/csp_source.cc",
"csp/csp_source.h",
"csp/csp_violation_report_body.cc",
"csp/csp_violation_report_body.h",
"csp/execution_context_csp_delegate.cc",
"csp/execution_context_csp_delegate.h",
......@@ -36,6 +37,7 @@ blink_core_sources("frame") {
"deprecated_schedule_style_recalc_during_layout.h",
"deprecation.cc",
"deprecation.h",
"deprecation_report_body.cc",
"deprecation_report_body.h",
"device_single_window_event_controller.cc",
"device_single_window_event_controller.h",
......@@ -54,6 +56,7 @@ blink_core_sources("frame") {
"event_handler_registry.cc",
"event_handler_registry.h",
"external.h",
"feature_policy_violation_report_body.cc",
"feature_policy_violation_report_body.h",
"find_in_page.cc",
"find_in_page.h",
......@@ -83,6 +86,7 @@ blink_core_sources("frame") {
"hosts_using_features.h",
"intervention.cc",
"intervention.h",
"intervention_report_body.cc",
"intervention_report_body.h",
"layout_subtree_root_list.cc",
"layout_subtree_root_list.h",
......@@ -97,6 +101,7 @@ blink_core_sources("frame") {
"local_frame_view.h",
"location.cc",
"location.h",
"location_report_body.cc",
"location_report_body.h",
"navigation_rate_limiter.cc",
"navigation_rate_limiter.h",
......@@ -146,6 +151,7 @@ blink_core_sources("frame") {
"remote_frame_view.h",
"report.cc",
"report.h",
"report_body.cc",
"report_body.h",
"reporting_context.cc",
"reporting_context.h",
......@@ -171,6 +177,7 @@ blink_core_sources("frame") {
"settings_delegate.h",
"smart_clip.cc",
"smart_clip.h",
"test_report_body.cc",
"test_report_body.h",
"use_counter_helper.cc",
"use_counter_helper.h",
......
// Copyright 2019 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/csp/csp_violation_report_body.h"
namespace blink {
void CSPViolationReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
LocationReportBody::BuildJSONValue(builder);
builder.AddString("documentURL", documentURL());
builder.AddStringOrNull("referrer", referrer());
builder.AddStringOrNull("blockedURL", blockedURL());
builder.AddString("effectiveDirective", effectiveDirective());
builder.AddString("originalPolicy", originalPolicy());
builder.AddStringOrNull("sample", sample());
builder.AddString("disposition", disposition());
builder.AddNumber("statusCode", statusCode());
}
} // namespace blink
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_CSP_CSP_VIOLATION_REPORT_BODY_H_
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/events/security_policy_violation_event_init.h"
#include "third_party/blink/renderer/core/frame/location_report_body.h"
......@@ -45,6 +46,8 @@ class CORE_EXPORT CSPViolationReportBody : public LocationReportBody {
String disposition() const { return disposition_; }
uint16_t statusCode() const { return status_code_; }
void BuildJSONValue(V8ObjectBuilder& builder) const override;
private:
const String document_url_;
const String referrer_;
......
......@@ -18,4 +18,5 @@
readonly attribute unsigned short statusCode;
readonly attribute unsigned long? lineNumber;
readonly attribute unsigned long? columnNumber;
[CallWith=ScriptState] object toJSON();
};
// Copyright 2019 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/deprecation_report_body.h"
#include "third_party/blink/renderer/platform/text/date_components.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
namespace blink {
void DeprecationReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
LocationReportBody::BuildJSONValue(builder);
builder.AddString("id", id());
builder.AddString("message", message());
bool is_null = false;
double anticipated_removal_value = anticipatedRemoval(is_null);
if (is_null) {
builder.AddNull("anticipatedRemoval");
} else {
DateComponents anticipated_removal_date;
bool is_valid =
anticipated_removal_date.SetMillisecondsSinceEpochForDateTimeLocal(
anticipated_removal_value);
if (!is_valid) {
builder.AddNull("anticipatedRemoval");
} else {
// Adding extra 'Z' here to ensure that the string gives the same result
// as JSON.stringify(anticipatedRemoval) in javascript. Note here
// anticipatedRemoval will become a Date object in javascript.
String iso8601_date =
anticipated_removal_date.ToString(DateComponents::kMillisecond) + "Z";
builder.AddString("anticipatedRemoval", iso8601_date);
}
}
}
} // namespace blink
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_DEPRECATION_REPORT_BODY_H_
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/frame/location_report_body.h"
namespace blink {
......@@ -28,6 +29,8 @@ class CORE_EXPORT DeprecationReportBody : public LocationReportBody {
return anticipatedRemoval_;
}
void BuildJSONValue(V8ObjectBuilder& builder) const override;
private:
const String id_;
const String message_;
......
......@@ -13,4 +13,5 @@
readonly attribute DOMString? sourceFile;
readonly attribute unsigned long? lineNumber;
readonly attribute unsigned long? columnNumber;
[CallWith=ScriptState] object toJSON();
};
// Copyright 2019 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/deprecation_report_body.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
namespace blink {
namespace {
TEST(DeprecationReportBodyJSONTest, noAnticipatedRemoval) {
DeprecationReportBody body("test_id", 0, "test_message");
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
V8ObjectBuilder builder(script_state);
body.BuildJSONValue(builder);
ScriptValue json_object = builder.GetScriptValue();
EXPECT_TRUE(json_object.IsObject());
String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
kDoNotExternalize);
String expected =
"{\"sourceFile\":null,\"lineNumber\":null,\"columnNumber\":null,\"id\":"
"\"test_id\",\"message\":\"test_message\",\"anticipatedRemoval\":null}";
EXPECT_EQ(expected, json_string);
}
TEST(DeprecationReportBodyJSONTest, actualAnticipatedRemoval) {
DeprecationReportBody body("test_id", 1575950400000, "test_message");
V8TestingScope scope;
ScriptState* script_state = scope.GetScriptState();
V8ObjectBuilder builder(script_state);
body.BuildJSONValue(builder);
ScriptValue json_object = builder.GetScriptValue();
EXPECT_TRUE(json_object.IsObject());
String json_string = ToBlinkString<String>(
v8::JSON::Stringify(scope.GetContext(),
json_object.V8Value().As<v8::Object>())
.ToLocalChecked(),
kDoNotExternalize);
String expected =
"{\"sourceFile\":null,\"lineNumber\":null,\"columnNumber\":null,\"id\":"
"\"test_id\",\"message\":\"test_message\",\"anticipatedRemoval\":\"2019-"
"12-10T04:00:00.000Z\"}";
EXPECT_EQ(expected, json_string);
}
} // namespace
} // namespace blink
// Copyright 2019 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/feature_policy_violation_report_body.h"
namespace blink {
void FeaturePolicyViolationReportBody::BuildJSONValue(
V8ObjectBuilder& builder) const {
LocationReportBody::BuildJSONValue(builder);
builder.AddString("featureId", featureId());
builder.AddString("disposition", disposition());
builder.AddStringOrNull("message", message());
}
} // namespace blink
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_FEATURE_POLICY_VIOLATION_REPORT_BODY_H_
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/frame/location_report_body.h"
namespace blink {
......@@ -33,6 +34,7 @@ class CORE_EXPORT FeaturePolicyViolationReportBody : public LocationReportBody {
String featureId() const { return feature_id_; }
String disposition() const { return disposition_; }
String message() const { return message_; }
void BuildJSONValue(V8ObjectBuilder& builder) const override;
~FeaturePolicyViolationReportBody() override = default;
......
......@@ -13,4 +13,5 @@
readonly attribute unsigned long? columnNumber;
readonly attribute DOMString disposition;
readonly attribute DOMString? message;
[CallWith=ScriptState] object toJSON();
};
// Copyright 2019 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/intervention_report_body.h"
namespace blink {
void InterventionReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
LocationReportBody::BuildJSONValue(builder);
builder.AddString("id", id());
builder.AddString("message", message());
}
} // namespace blink
......@@ -6,6 +6,7 @@
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_INTERVENTION_REPORT_BODY_H_
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/frame/location_report_body.h"
namespace blink {
......@@ -21,6 +22,7 @@ class CORE_EXPORT InterventionReportBody : public LocationReportBody {
String id() const { return id_; }
String message() const { return message_; }
void BuildJSONValue(V8ObjectBuilder& builder) const override;
private:
const String id_;
......
......@@ -12,4 +12,5 @@
readonly attribute DOMString? sourceFile;
readonly attribute unsigned long? lineNumber;
readonly attribute unsigned long? columnNumber;
[CallWith=ScriptState] object toJSON();
};
// Copyright 2019 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"
namespace blink {
void LocationReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
builder.AddStringOrNull("sourceFile", sourceFile());
bool is_null = false;
uint32_t line_number = lineNumber(is_null);
if (is_null) {
builder.AddNull("lineNumber");
} else {
builder.AddNumber("lineNumber", line_number);
}
is_null = true;
uint32_t column_number = columnNumber(is_null);
if (is_null) {
builder.AddNull("columnNumber");
} else {
builder.AddNumber("columnNumber", column_number);
}
}
} // namespace blink
......@@ -9,11 +9,12 @@
#include <utility>
#include "third_party/blink/renderer/bindings/core/v8/source_location.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/frame/report_body.h"
namespace blink {
class LocationReportBody : public ReportBody {
class CORE_EXPORT LocationReportBody : public ReportBody {
public:
explicit LocationReportBody(std::unique_ptr<SourceLocation> location)
: source_file_(location->Url()),
......@@ -47,6 +48,8 @@ class LocationReportBody : public ReportBody {
return column_number_.value_or(0);
}
void BuildJSONValue(V8ObjectBuilder& builder) const override;
protected:
const String source_file_;
base::Optional<uint32_t> line_number_;
......
......@@ -11,4 +11,14 @@ constexpr const char ReportType::kFeaturePolicyViolation[];
constexpr const char ReportType::kIntervention[];
constexpr const char ReportType::kCSPViolation[];
ScriptValue Report::toJSON(ScriptState* script_state) const {
V8ObjectBuilder builder(script_state);
builder.AddString("type", type());
builder.AddString("url", url());
V8ObjectBuilder body_builder(script_state);
body()->BuildJSONValue(body_builder);
builder.Add("body", body_builder);
return builder.GetScriptValue();
}
} // namespace blink
......@@ -39,6 +39,8 @@ class CORE_EXPORT Report : public ScriptWrappable {
ScriptWrappable::Trace(visitor);
}
ScriptValue toJSON(ScriptState* script_state) const;
private:
const String type_;
const String url_;
......
......@@ -10,4 +10,5 @@
readonly attribute DOMString type;
readonly attribute DOMString url;
readonly attribute ReportBody? body;
[CallWith=ScriptState] object toJSON();
};
// Copyright 2019 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_body.h"
namespace blink {
ScriptValue ReportBody::toJSON(ScriptState* script_state) const {
V8ObjectBuilder result(script_state);
BuildJSONValue(result);
return result.GetScriptValue();
}
} // namespace blink
......@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORT_BODY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_REPORT_BODY_H_
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
namespace blink {
......@@ -14,6 +15,11 @@ class CORE_EXPORT ReportBody : public ScriptWrappable {
public:
~ReportBody() override = default;
ScriptValue toJSON(ScriptState* script_state) const;
// This function is public for use in Report::toJSON
virtual void BuildJSONValue(V8ObjectBuilder& builder) const = 0;
};
} // namespace blink
......
......@@ -7,4 +7,5 @@
[
NoInterfaceObject
] interface ReportBody {
[CallWith=ScriptState] object toJSON();
};
// Copyright 2019 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/test_report_body.h"
namespace blink {
void TestReportBody::BuildJSONValue(V8ObjectBuilder& builder) const {
builder.AddString("message", message());
}
} // namespace blink
......@@ -5,6 +5,7 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_TEST_REPORT_BODY_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FRAME_TEST_REPORT_BODY_H_
#include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h"
#include "third_party/blink/renderer/core/frame/report_body.h"
namespace blink {
......@@ -19,6 +20,8 @@ class TestReportBody : public ReportBody {
String message() const { return message_; }
void BuildJSONValue(V8ObjectBuilder& builder) const override;
private:
const String message_;
};
......
......@@ -8,4 +8,5 @@
NoInterfaceObject
] interface TestReportBody : ReportBody {
readonly attribute DOMString message;
[CallWith=ScriptState] object toJSON();
};
......@@ -3,6 +3,7 @@
<head>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../resources/feature-policy-report-json.js'></script>
</head>
<body>
<img src="./oversized.jpg" alt="oversized image" width="50" height="50">
......@@ -19,6 +20,7 @@
assert_equals(rbody.sourceFile, document.getElementsByTagName('img')[0].src);
assert_equals(rbody.lineNumber, null);
assert_equals(rbody.columnNumber, null);
check_report_json(reports[0]);
}),
{types: ['feature-policy-violation'], buffered: true}
).observe();
......
......@@ -3,6 +3,7 @@
<head>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../resources/feature-policy-report-json.js'></script>
</head>
<body>
<script>
......@@ -17,6 +18,7 @@ var check_report_format = (reports, observer) => {
assert_equals(typeof report.body.lineNumber, "number");
assert_equals(typeof report.body.columnNumber, "number");
assert_equals(report.body.disposition, "enforce");
check_report_json(report);
};
new ReportingObserver(t.step_func_done(check_report_format),
......
......@@ -3,6 +3,7 @@
<head>
<script src='/resources/testharness.js'></script>
<script src='/resources/testharnessreport.js'></script>
<script src='../resources/feature-policy-report-json.js'></script>
</head>
<body>
<script>
......@@ -17,6 +18,7 @@ var check_report_format = (reports, observer) => {
assert_equals(typeof report.body.lineNumber, "number");
assert_equals(typeof report.body.columnNumber, "number");
assert_equals(report.body.disposition, "enforce");
check_report_json(report);
};
new ReportingObserver(t.step_func_done(check_report_format),
......
/**
* @fileoverview functions for ensuring feature policy report is serializable
*/
const check_report_json = (report) => {
// Ensures toJSON method exists on report.
assert_equals(typeof report.toJSON, "function");
const report_json = report.toJSON();
// Ensures toJSON() call is successful.
assert_equals(report.type, report_json.type);
assert_equals(report.url, report_json.url);
assert_equals(report.body.featureId, report_json.body.featureId);
assert_equals(report.body.disposition, report_json.body.disposition);
assert_equals(report.body.sourceFile, report_json.body.sourceFile);
assert_equals(report.body.lineNumber, report_json.body.lineNumber);
assert_equals(report.body.columnNumber, report_json.body.columnNumber);
// Ensures JSON.stringify() serializes the report correctly.
assert_false(JSON.stringify(report) === "{}");
assert_equals(JSON.stringify(report), JSON.stringify(report_json));
}
\ No newline at end of file
......@@ -16,6 +16,13 @@
assert_equals(reports[0].type, "test");
assert_true(reports[0].url.endsWith("reporting/generateTestReport.html"));
assert_equals(reports[0].body.message, "Test message.");
// Ensure that the toJSON() call of the report are valid.
const reportJSON = reports[0].toJSON();
assert_equals(reports[0].type, reportJSON.type);
assert_equals(reports[0].url, reportJSON.url);
assert_equals(reports[0].body.message, reportJSON.body.message);
// Ensure that report can be successfully JSON serialized.
assert_equals(JSON.stringify(reports[0]), JSON.stringify(reportJSON));
});
test.done();
});
......
......@@ -30,6 +30,24 @@ async_test(function(test) {
assert_equals(reports[0].body.statusCode, 200);
assert_equals(reports[0].body.lineNumber, null);
assert_equals(reports[0].body.columnNumber, null);
// Ensure the toJSON call is successful.
const reportJSON = reports[0].toJSON();
assert_equals(reportJSON.type, reports[0].type);
assert_equals(reportJSON.url, reports[0].url);
assert_equals(typeof reportJSON.body, "object");
assert_equals(reportJSON.body.documentURL, reports[0].body.documentURL);
assert_equals(reportJSON.body.referrer, reports[0].body.referrer);
assert_equals(reportJSON.body.blockedURL, reports[0].body.blockedURL);
assert_equals(reportJSON.body.effectiveDirective, reports[0].body.effectiveDirective);
assert_equals(reportJSON.body.originalPolicy, reports[0].body.originalPolicy);
assert_equals(reportJSON.body.sourceFile, reports[0].body.sourceFile);
assert_equals(reportJSON.body.sample, reports[0].body.sample);
assert_equals(reportJSON.body.disposition, reports[0].body.disposition);
assert_equals(reportJSON.body.statusCode, reports[0].body.statusCode);
assert_equals(reportJSON.body.lineNumber, reports[0].body.lineNumber);
assert_equals(reportJSON.body.columnNumber, reports[0].body.columnNumber);
// Ensure that report can be successfully JSON serialized.
assert_equals(JSON.stringify(reports[0]), JSON.stringify(reportJSON));
});
test.done();
......
......@@ -26,6 +26,20 @@ async_test(function(test) {
assert_equals(typeof reports[0].body.lineNumber, "number");
assert_equals(typeof reports[0].body.columnNumber, "number");
assert_equals(typeof reports[0].body.message, "string");
// Ensure the toJSON call is successful.
const reportJSON = reports[0].toJSON();
assert_equals(reportJSON.type, reports[0].type);
assert_equals(reportJSON.url, reports[0].url);
assert_equals(typeof reportJSON.body, "object");
assert_equals(reportJSON.body.id, reports[0].body.id);
assert_equals(reportJSON.body.message, reports[0].body.message);
assert_equals(reportJSON.body.sourceFile, reports[0].body.sourceFile);
assert_equals(reportJSON.body.lineNumber, reports[0].body.lineNumber);
assert_equals(reportJSON.body.columnNumber, reports[0].body.columnNumber);
// Ensure that report can be successfully JSON serialized.
assert_false(JSON.stringify(reports[0]) === "{}");
assert_equals(JSON.stringify(reports[0]), JSON.stringify(reportJSON));
});
test.done();
......
......@@ -20,6 +20,23 @@ async_test(function(test) {
"reporting-observer/resources/deprecation.js"));
assert_equals(typeof report.body.lineNumber, "number");
assert_equals(typeof report.body.columnNumber, "number");
// Ensure the toJSON call is successful.
const reportJSON = report.toJSON();
assert_equals(reportJSON.type, report.type);
assert_equals(reportJSON.url, report.url);
assert_equals(typeof reportJSON.body, "object");
assert_equals(reportJSON.body.id, report.body.id);
assert_equals(reportJSON.body.message, report.body.message);
assert_equals(reportJSON.body.sourceFile, report.body.sourceFile);
assert_equals(reportJSON.body.lineNumber, report.body.lineNumber);
assert_equals(reportJSON.body.columnNumber, report.body.columnNumber);
assert_equals(
JSON.stringify(reportJSON.body.anticipatedRemoval),
JSON.stringify(report.body.anticipatedRemoval)
);
// Ensure that report can be successfully JSON serialized.
assert_false(JSON.stringify(report) === "{}");
assert_equals(JSON.stringify(report), JSON.stringify(reportJSON));
}
assert_not_equals(reports[0].body.id, reports[1].body.id);
});
......
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