зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1508310 - Implement Report-to header support - part 1 - Header parser, r=smaug
This commit is contained in:
Родитель
33b64b3e11
Коммит
2d4f513ae0
|
@ -100,6 +100,15 @@ BrowserUpgradeInsecureDisplayRequest = %1$S is upgrading an insecure display req
|
|||
RunningClearSiteDataValue=Clear-Site-Data header forced the clean up of “%S” data.
|
||||
UnknownClearSiteDataValue=Clear-Site-Data header found. Unknown value “%S”.
|
||||
|
||||
# Reporting API
|
||||
ReportingHeaderInvalidJSON=Reporting Header: invalid JSON value received.
|
||||
ReportingHeaderInvalidNameItem=Reporting Header: invalid name for group.
|
||||
ReportingHeaderDuplicateGroup=Reporting Header: ignoring duplicated group named “%S”.
|
||||
ReportingHeaderInvalidItem=Reporting Header: ignoring invalid item named “%S”.
|
||||
ReportingHeaderInvalidEndpoint=Reporting Header: ignoring invalid endpoint for item named “%S”.
|
||||
# LOCALIZATION NOTE(ReportingHeaderInvalidURLEndpoint): %1$S is the invalid URL, %2$S is the group name
|
||||
ReportingHeaderInvalidURLEndpoint=Reporting Header: ignoring invalid endpoint URL “%1$S” for item named “%2$S”.
|
||||
|
||||
FeaturePolicyUnsupportedFeatureName=Feature Policy: Skipping unsupported feature name “%S”.
|
||||
# TODO: would be nice to add a link to the Feature-Policy MDN documentation here. See bug 1449501
|
||||
FeaturePolicyInvalidEmptyAllowValue= Feature Policy: Skipping empty allow list for feature: “%S”.
|
||||
|
|
|
@ -0,0 +1,423 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ReportingHeader.h"
|
||||
|
||||
#include "js/JSON.h"
|
||||
#include "mozilla/dom/ReportingBinding.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "mozilla/dom/SimpleGlobalObject.h"
|
||||
#include "mozilla/OriginAttributes.h"
|
||||
#include "mozilla/Services.h"
|
||||
#include "mozilla/StaticPrefs.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpProtocolHandler.h"
|
||||
#include "nsIObserverService.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "nsIScriptError.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
StaticRefPtr<ReportingHeader> gReporting;
|
||||
|
||||
} // namespace
|
||||
|
||||
/* static */ void ReportingHeader::Initialize() {
|
||||
MOZ_ASSERT(!gReporting);
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ReportingHeader> service = new ReportingHeader();
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (NS_WARN_IF(!obs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs->AddObserver(service, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC, false);
|
||||
obs->AddObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
|
||||
gReporting = service;
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::Shutdown() {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
if (!gReporting) {
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<ReportingHeader> service = gReporting;
|
||||
gReporting = nullptr;
|
||||
|
||||
nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
|
||||
if (NS_WARN_IF(!obs)) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs->RemoveObserver(service, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC);
|
||||
obs->RemoveObserver(service, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
|
||||
}
|
||||
|
||||
ReportingHeader::ReportingHeader() = default;
|
||||
ReportingHeader::~ReportingHeader() = default;
|
||||
|
||||
NS_IMETHODIMP
|
||||
ReportingHeader::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
const char16_t* aData) {
|
||||
if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
|
||||
Shutdown();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!strcmp(aTopic, NS_HTTP_ON_EXAMINE_RESPONSE_TOPIC));
|
||||
|
||||
// Pref disabled.
|
||||
if (!StaticPrefs::dom_reporting_header_enabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> channel = do_QueryInterface(aSubject);
|
||||
if (NS_WARN_IF(!channel)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
ReportingFromChannel(channel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void ReportingHeader::ReportingFromChannel(nsIHttpChannel* aChannel) {
|
||||
MOZ_ASSERT(aChannel);
|
||||
|
||||
if (!StaticPrefs::dom_reporting_header_enabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// We want to use the final URI to check if Report-To should be allowed or
|
||||
// not.
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = aChannel->GetURI(getter_AddRefs(uri));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsSecureURI(uri)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString headerValue;
|
||||
rv =
|
||||
aChannel->GetResponseHeader(NS_LITERAL_CSTRING("Report-To"), headerValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
|
||||
if (NS_WARN_IF(!ssm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = ssm->GetChannelURIPrincipal(aChannel, getter_AddRefs(principal));
|
||||
if (NS_WARN_IF(NS_FAILED(rv)) || !principal) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString origin;
|
||||
rv = principal->GetOrigin(origin);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
UniquePtr<Client> client = ParseHeader(aChannel, uri, headerValue);
|
||||
if (client) {
|
||||
// Here we override the previous data.
|
||||
mOrigins.Put(origin, client.release());
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ UniquePtr<ReportingHeader::Client> ReportingHeader::ParseHeader(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI, const nsACString& aHeaderValue) {
|
||||
MOZ_ASSERT(aURI);
|
||||
// aChannel can be null in gtest
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
|
||||
JSObject* cleanGlobal =
|
||||
SimpleGlobalObject::Create(SimpleGlobalObject::GlobalType::BindingDetail);
|
||||
if (NS_WARN_IF(!cleanGlobal)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!jsapi.Init(cleanGlobal))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// WebIDL dictionary parses single items. Let's create a object to parse the
|
||||
// header.
|
||||
nsAutoString json;
|
||||
json.AppendASCII("{ \"items\": [");
|
||||
json.Append(NS_ConvertUTF8toUTF16(aHeaderValue));
|
||||
json.AppendASCII("]}");
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JS::Value> jsonValue(cx);
|
||||
bool ok = JS_ParseJSON(cx, PromiseFlatString(json).get(), json.Length(),
|
||||
&jsonValue);
|
||||
if (!ok) {
|
||||
LogToConsoleInvalidJSON(aChannel, aURI);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
dom::ReportingHeaderValue data;
|
||||
if (!data.Init(cx, jsonValue)) {
|
||||
LogToConsoleInvalidJSON(aChannel, aURI);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!data.mItems.WasPassed() || data.mItems.Value().IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
UniquePtr<Client> client = MakeUnique<Client>();
|
||||
|
||||
for (const dom::ReportingItem& item : data.mItems.Value()) {
|
||||
nsAutoString groupName;
|
||||
|
||||
if (item.mGroup.isUndefined()) {
|
||||
groupName.AssignLiteral("default");
|
||||
} else if (!item.mGroup.isString()) {
|
||||
LogToConsoleInvalidNameItem(aChannel, aURI);
|
||||
continue;
|
||||
} else {
|
||||
JS::Rooted<JSString*> groupStr(cx, item.mGroup.toString());
|
||||
MOZ_ASSERT(groupStr);
|
||||
|
||||
nsAutoJSString string;
|
||||
if (NS_WARN_IF(!string.init(cx, groupStr))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
groupName = string;
|
||||
}
|
||||
|
||||
if (!item.mMax_age.isNumber() || !item.mEndpoints.isObject()) {
|
||||
LogToConsoleIncompleteItem(aChannel, aURI, groupName);
|
||||
continue;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> endpoints(cx, &item.mEndpoints.toObject());
|
||||
MOZ_ASSERT(endpoints);
|
||||
|
||||
bool isArray = false;
|
||||
if (!JS_IsArrayObject(cx, endpoints, &isArray) || !isArray) {
|
||||
LogToConsoleIncompleteItem(aChannel, aURI, groupName);
|
||||
continue;
|
||||
}
|
||||
|
||||
uint32_t endpointsLength;
|
||||
if (!JS_GetArrayLength(cx, endpoints, &endpointsLength) ||
|
||||
endpointsLength == 0) {
|
||||
LogToConsoleIncompleteItem(aChannel, aURI, groupName);
|
||||
continue;
|
||||
}
|
||||
|
||||
bool found = false;
|
||||
for (const Group& group : client->mGroups) {
|
||||
if (group.mName == groupName) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
LogToConsoleDuplicateGroup(aChannel, aURI, groupName);
|
||||
continue;
|
||||
}
|
||||
|
||||
Group* group = client->mGroups.AppendElement();
|
||||
group->mName = groupName;
|
||||
group->mIncludeSubdomains = item.mInclude_subdomains;
|
||||
group->mTTL = item.mMax_age.toNumber();
|
||||
group->mCreationTime = TimeStamp::Now();
|
||||
|
||||
for (uint32_t i = 0; i < endpointsLength; ++i) {
|
||||
JS::Rooted<JS::Value> element(cx);
|
||||
if (!JS_GetElement(cx, endpoints, i, &element)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ReportingEndpoint endpoint;
|
||||
if (!endpoint.Init(cx, element)) {
|
||||
LogToConsoleIncompleteEndpoint(aChannel, aURI, groupName);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!endpoint.mUrl.isString() ||
|
||||
(!endpoint.mPriority.isUndefined() &&
|
||||
(!endpoint.mPriority.isNumber() ||
|
||||
endpoint.mPriority.toNumber() < 0)) ||
|
||||
(!endpoint.mWeight.isUndefined() &&
|
||||
(!endpoint.mWeight.isNumber() || endpoint.mWeight.toNumber() < 0))) {
|
||||
LogToConsoleIncompleteEndpoint(aChannel, aURI, groupName);
|
||||
continue;
|
||||
}
|
||||
|
||||
JS::Rooted<JSString*> endpointUrl(cx, endpoint.mUrl.toString());
|
||||
MOZ_ASSERT(endpointUrl);
|
||||
|
||||
nsAutoJSString endpointString;
|
||||
if (NS_WARN_IF(!endpointString.init(cx, endpointUrl))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_NewURI(getter_AddRefs(uri), endpointString);
|
||||
if (NS_FAILED(rv)) {
|
||||
LogToConsoleInvalidURLEndpoint(aChannel, aURI, groupName,
|
||||
endpointString);
|
||||
continue;
|
||||
}
|
||||
|
||||
Endpoint* ep = group->mEndpoints.AppendElement();
|
||||
ep->mUrl = uri;
|
||||
ep->mPriority =
|
||||
endpoint.mPriority.isUndefined() ? 1 : endpoint.mPriority.toNumber();
|
||||
ep->mWeight =
|
||||
endpoint.mWeight.isUndefined() ? 1 : endpoint.mWeight.toNumber();
|
||||
}
|
||||
}
|
||||
|
||||
if (client->mGroups.IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
bool ReportingHeader::IsSecureURI(nsIURI* aURI) const {
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
bool prioriAuthenticated = false;
|
||||
if (NS_WARN_IF(NS_FAILED(NS_URIChainHasFlags(
|
||||
aURI, nsIProtocolHandler::URI_IS_POTENTIALLY_TRUSTWORTHY,
|
||||
&prioriAuthenticated)))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return prioriAuthenticated;
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleInvalidJSON(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI) {
|
||||
nsTArray<nsString> params;
|
||||
LogToConsoleInternal(aChannel, aURI, "ReportingHeaderInvalidJSON", params);
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleDuplicateGroup(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI, const nsAString& aName) {
|
||||
nsTArray<nsString> params;
|
||||
params.AppendElement(aName);
|
||||
|
||||
LogToConsoleInternal(aChannel, aURI, "ReportingHeaderDuplicateGroup", params);
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleInvalidNameItem(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI) {
|
||||
nsTArray<nsString> params;
|
||||
LogToConsoleInternal(aChannel, aURI, "ReportingHeaderInvalidNameItem",
|
||||
params);
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleIncompleteItem(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI, const nsAString& aName) {
|
||||
nsTArray<nsString> params;
|
||||
params.AppendElement(aName);
|
||||
|
||||
LogToConsoleInternal(aChannel, aURI, "ReportingHeaderInvalidItem", params);
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleIncompleteEndpoint(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI, const nsAString& aName) {
|
||||
nsTArray<nsString> params;
|
||||
params.AppendElement(aName);
|
||||
|
||||
LogToConsoleInternal(aChannel, aURI, "ReportingHeaderInvalidEndpoint",
|
||||
params);
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleInvalidURLEndpoint(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI, const nsAString& aName,
|
||||
const nsAString& aURL) {
|
||||
nsTArray<nsString> params;
|
||||
params.AppendElement(aURL);
|
||||
params.AppendElement(aName);
|
||||
|
||||
LogToConsoleInternal(aChannel, aURI, "ReportingHeaderInvalidURLEndpoint",
|
||||
params);
|
||||
}
|
||||
|
||||
/* static */ void ReportingHeader::LogToConsoleInternal(
|
||||
nsIHttpChannel* aChannel, nsIURI* aURI, const char* aMsg,
|
||||
const nsTArray<nsString>& aParams) {
|
||||
MOZ_ASSERT(aURI);
|
||||
|
||||
if (!aChannel) {
|
||||
// We are in a gtest.
|
||||
return;
|
||||
}
|
||||
|
||||
uint64_t windowID = 0;
|
||||
|
||||
nsresult rv = aChannel->GetTopLevelContentWindowId(&windowID);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!windowID) {
|
||||
nsCOMPtr<nsILoadGroup> loadGroup;
|
||||
nsresult rv = aChannel->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loadGroup) {
|
||||
windowID = nsContentUtils::GetInnerWindowID(loadGroup);
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoString localizedMsg;
|
||||
rv = nsContentUtils::FormatLocalizedString(
|
||||
nsContentUtils::eSECURITY_PROPERTIES, aMsg, aParams, localizedMsg);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
rv = nsContentUtils::ReportToConsoleByWindowID(
|
||||
localizedMsg, nsIScriptError::infoFlag, NS_LITERAL_CSTRING("Reporting"),
|
||||
windowID, aURI);
|
||||
Unused << NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(ReportingHeader)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMPL_ADDREF(ReportingHeader)
|
||||
NS_IMPL_RELEASE(ReportingHeader)
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,95 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ReportingHeader_h
|
||||
#define mozilla_dom_ReportingHeader_h
|
||||
|
||||
#include "mozilla/TimeStamp.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsIObserver.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
class nsIHttpChannel;
|
||||
class nsIPrincipal;
|
||||
class nsIURI;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class ReportingHeader final : public nsIObserver {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIOBSERVER
|
||||
|
||||
static void Initialize();
|
||||
|
||||
// Exposed structs for gtests
|
||||
|
||||
struct Endpoint {
|
||||
nsCOMPtr<nsIURI> mUrl;
|
||||
uint32_t mPriority;
|
||||
uint32_t mWeight;
|
||||
};
|
||||
|
||||
struct Group {
|
||||
nsString mName;
|
||||
bool mIncludeSubdomains;
|
||||
int32_t mTTL;
|
||||
TimeStamp mCreationTime;
|
||||
nsTArray<Endpoint> mEndpoints;
|
||||
};
|
||||
|
||||
struct Client {
|
||||
nsTArray<Group> mGroups;
|
||||
};
|
||||
|
||||
static UniquePtr<Client> ParseHeader(nsIHttpChannel* aChannel, nsIURI* aURI,
|
||||
const nsACString& aHeaderValue);
|
||||
|
||||
private:
|
||||
ReportingHeader();
|
||||
~ReportingHeader();
|
||||
|
||||
static void Shutdown();
|
||||
|
||||
// Checks if a channel contains a Report-To header and parses its value.
|
||||
void ReportingFromChannel(nsIHttpChannel* aChannel);
|
||||
|
||||
// This method checks if the protocol handler of the URI has the
|
||||
// URI_IS_POTENTIALLY_TRUSTWORTHY flag.
|
||||
bool IsSecureURI(nsIURI* aURI) const;
|
||||
|
||||
static void LogToConsoleInvalidJSON(nsIHttpChannel* aChannel, nsIURI* aURI);
|
||||
|
||||
static void LogToConsoleDuplicateGroup(nsIHttpChannel* aChannel, nsIURI* aURI,
|
||||
const nsAString& aName);
|
||||
|
||||
static void LogToConsoleInvalidNameItem(nsIHttpChannel* aChannel,
|
||||
nsIURI* aURI);
|
||||
|
||||
static void LogToConsoleIncompleteItem(nsIHttpChannel* aChannel, nsIURI* aURI,
|
||||
const nsAString& aName);
|
||||
|
||||
static void LogToConsoleIncompleteEndpoint(nsIHttpChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
const nsAString& aName);
|
||||
|
||||
static void LogToConsoleInvalidURLEndpoint(nsIHttpChannel* aChannel,
|
||||
nsIURI* aURI,
|
||||
const nsAString& aName,
|
||||
const nsAString& aURL);
|
||||
|
||||
static void LogToConsoleInternal(nsIHttpChannel* aChannel, nsIURI* aURI,
|
||||
const char* aMsg,
|
||||
const nsTArray<nsString>& aParams);
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, Client> mOrigins;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_ReportingHeader_h
|
|
@ -9,6 +9,7 @@ EXPORTS.mozilla.dom = [
|
|||
'FeaturePolicyViolationReportBody.h',
|
||||
'Report.h',
|
||||
'ReportBody.h',
|
||||
'ReportingHeader.h',
|
||||
'ReportingObserver.h',
|
||||
'ReportingUtils.h',
|
||||
'TestingDeprecatedInterface.h',
|
||||
|
@ -19,6 +20,7 @@ UNIFIED_SOURCES += [
|
|||
'FeaturePolicyViolationReportBody.cpp',
|
||||
'Report.cpp',
|
||||
'ReportBody.cpp',
|
||||
'ReportingHeader.cpp',
|
||||
'ReportingObserver.cpp',
|
||||
'ReportingUtils.cpp',
|
||||
'TestingDeprecatedInterface.cpp',
|
||||
|
|
|
@ -55,3 +55,29 @@ interface TestingDeprecatedInterface {
|
|||
[Deprecated="DeprecatedTestingAttribute"]
|
||||
readonly attribute boolean deprecatedAttribute;
|
||||
};
|
||||
|
||||
// Used internally to process the JSON
|
||||
dictionary ReportingHeaderValue {
|
||||
sequence<ReportingItem> items;
|
||||
};
|
||||
|
||||
// Used internally to process the JSON
|
||||
dictionary ReportingItem {
|
||||
// This is a long.
|
||||
any max_age;
|
||||
// This is a sequence of ReportingEndpoint.
|
||||
any endpoints;
|
||||
// This is a string. If missing, the value is 'default'.
|
||||
any group;
|
||||
boolean include_subdomains = false;
|
||||
};
|
||||
|
||||
// Used internally to process the JSON
|
||||
dictionary ReportingEndpoint {
|
||||
// This is a string.
|
||||
any url;
|
||||
// This is an unsigned long.
|
||||
any priority;
|
||||
// This is an unsigned long.
|
||||
any weight;
|
||||
};
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
#include "mozilla/dom/PointerEventHandler.h"
|
||||
#include "mozilla/dom/RemoteWorkerService.h"
|
||||
#include "mozilla/dom/BlobURLProtocolHandler.h"
|
||||
#include "mozilla/dom/ReportingHeader.h"
|
||||
#include "nsThreadManager.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
|
||||
|
@ -286,6 +287,9 @@ nsresult nsLayoutStatics::Initialize() {
|
|||
|
||||
ClearSiteData::Initialize();
|
||||
|
||||
// Reporting API.
|
||||
ReportingHeader::Initialize();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -1908,6 +1908,12 @@ VARCACHE_PREF(
|
|||
)
|
||||
#undef PREF_VALUE
|
||||
|
||||
VARCACHE_PREF(
|
||||
"dom.reporting.header.enabled",
|
||||
dom_reporting_header_enabled,
|
||||
RelaxedAtomicBool, false
|
||||
)
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// End of prefs
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
Загрузка…
Ссылка в новой задаче