Bug 1508310 - Implement Report-to header support - part 4 - IPC to get endpoint from content process, r=smaug

This commit is contained in:
Andrea Marchesini 2018-12-01 21:26:09 +01:00
Родитель 59571892c5
Коммит ace9fa800a
19 изменённых файлов: 456 добавлений и 4 удалений

Просмотреть файл

@ -3808,6 +3808,7 @@ void ReportDeprecation(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
aLineNumber, aColumnNumber);
ReportingUtils::Report(aWindow, nsGkAtoms::deprecation,
NS_LITERAL_STRING("default"),
NS_ConvertUTF8toUTF16(spec), body);
}

Просмотреть файл

@ -0,0 +1,32 @@
/* -*- 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/EndpointForReportChild.h"
namespace mozilla {
namespace dom {
EndpointForReportChild::EndpointForReportChild() = default;
EndpointForReportChild::~EndpointForReportChild() = default;
void EndpointForReportChild::Initialize(
const ReportDeliver::ReportData& aData) {
mReportData = aData;
}
mozilla::ipc::IPCResult EndpointForReportChild::Recv__delete__(
const nsCString& aEndpointURL) {
if (!aEndpointURL.IsEmpty()) {
mReportData.mEndpointURL = aEndpointURL;
ReportDeliver::Fetch(mReportData);
}
return IPC_OK();
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,35 @@
/* -*- 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_EndpointForReportChild_h
#define mozilla_dom_EndpointForReportChild_h
#include "mozilla/dom/ReportDeliver.h"
#include "mozilla/dom/PEndpointForReportChild.h"
namespace mozilla {
namespace dom {
class EndpointForReport;
class EndpointForReportChild final : public PEndpointForReportChild {
public:
EndpointForReportChild();
~EndpointForReportChild();
void Initialize(const ReportDeliver::ReportData& aReportData);
mozilla::ipc::IPCResult Recv__delete__(
const nsCString& aEndpointURL) override;
private:
ReportDeliver::ReportData mReportData;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_EndpointForReportChild_h

Просмотреть файл

@ -0,0 +1,44 @@
/* -*- 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/EndpointForReportParent.h"
#include "mozilla/dom/ReportingHeader.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "mozilla/Unused.h"
#include "nsThreadUtils.h"
namespace mozilla {
namespace dom {
EndpointForReportParent::EndpointForReportParent()
: mPBackgroundThread(NS_GetCurrentThread()), mActive(true) {}
EndpointForReportParent::~EndpointForReportParent() = default;
void EndpointForReportParent::ActorDestroy(ActorDestroyReason aWhy) {
mActive = false;
}
void EndpointForReportParent::Run(
const nsString& aGroupName,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo) {
RefPtr<EndpointForReportParent> self = this;
NS_DispatchToMainThread(NS_NewRunnableFunction(
"EndpointForReportParent::Run", [self, aGroupName, aPrincipalInfo]() {
nsAutoCString uri;
ReportingHeader::GetEndpointForReport(aGroupName, aPrincipalInfo, uri);
self->mPBackgroundThread->Dispatch(NS_NewRunnableFunction(
"EndpointForReportParent::Answer", [self, uri]() {
if (self->mActive) {
Unused << self->Send__delete__(self, uri);
}
}));
}));
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,38 @@
/* -*- 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_EndpointForReportParent_h
#define mozilla_dom_EndpointForReportParent_h
#include "mozilla/dom/PEndpointForReportParent.h"
namespace mozilla {
namespace dom {
class EndpointForReport;
class EndpointForReportParent final : public PEndpointForReportParent {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(EndpointForReportParent)
EndpointForReportParent();
void Run(const nsString& aGroupName,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
private:
~EndpointForReportParent();
void ActorDestroy(ActorDestroyReason aWhy) override;
nsCOMPtr<nsIThread> mPBackgroundThread;
bool mActive;
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_EndpointForReportParent_h

Просмотреть файл

@ -0,0 +1,19 @@
/* 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 protocol PBackground;
namespace mozilla {
namespace dom {
protocol PEndpointForReport
{
manager PBackground;
child:
async __delete__(nsCString endpointURL);
};
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,66 @@
/* -*- 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/EndpointForReportChild.h"
#include "mozilla/dom/ReportDeliver.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/ipc/PBackgroundSharedTypes.h"
#include "nsGlobalWindowInner.h"
namespace mozilla {
namespace dom {
/* static */ void ReportDeliver::Record(nsPIDOMWindowInner* aWindow,
const nsAString& aType,
const nsAString& aGroupName,
const nsAString& aURL,
ReportBody* aBody) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aBody);
nsAutoString reportBodyJSON;
aBody->ToJSON(reportBodyJSON);
nsCOMPtr<nsIPrincipal> principal =
nsGlobalWindowInner::Cast(aWindow)->GetPrincipal();
if (NS_WARN_IF(!principal)) {
return;
}
mozilla::ipc::PrincipalInfo principalInfo;
nsresult rv = PrincipalToPrincipalInfo(principal, &principalInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
mozilla::ipc::PBackgroundChild* actorChild =
mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread();
PEndpointForReportChild* actor =
actorChild->SendPEndpointForReportConstructor(nsString(aGroupName),
principalInfo);
if (NS_WARN_IF(!actor)) {
return;
}
ReportData data;
data.mType = aType;
data.mURL = aURL;
data.mReportBodyJSON = reportBodyJSON;
data.mPrincipal = principal;
data.mFailures = 0;
static_cast<EndpointForReportChild*>(actor)->Initialize(data);
}
/* static */ void ReportDeliver::Fetch(const ReportData& aReportData) {
// TODO
}
} // namespace dom
} // namespace mozilla

Просмотреть файл

@ -0,0 +1,37 @@
/* -*- 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_ReportDeliver_h
#define mozilla_dom_ReportDeliver_h
class nsIPrincipal;
class nsPIDOMWindowInner;
namespace mozilla {
namespace dom {
class ReportDeliver final {
public:
struct ReportData {
nsString mType;
nsString mURL;
nsCString mEndpointURL;
nsString mReportBodyJSON;
nsCOMPtr<nsIPrincipal> mPrincipal;
uint32_t mFailures;
};
static void Record(nsPIDOMWindowInner* aWindow, const nsAString& aType,
const nsAString& aGroupName, const nsAString& aURL,
ReportBody* aBody);
static void Fetch(const ReportData& aReportData);
};
} // namespace dom
} // namespace mozilla
#endif // mozilla_dom_ReportDeliver_h

Просмотреть файл

@ -19,6 +19,7 @@
#include "nsIHttpProtocolHandler.h"
#include "nsIObserverService.h"
#include "nsIPrincipal.h"
#include "nsIRandomGenerator.h"
#include "nsIScriptError.h"
#include "nsNetUtil.h"
#include "nsXULAppAPI.h"
@ -411,6 +412,92 @@ bool ReportingHeader::IsSecureURI(nsIURI* aURI) const {
Unused << NS_WARN_IF(NS_FAILED(rv));
}
/* static */ void ReportingHeader::GetEndpointForReport(
const nsAString& aGroupName,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
nsACString& aEndpointURI) {
MOZ_ASSERT(aEndpointURI.IsEmpty());
if (!gReporting) {
return;
}
nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(aPrincipalInfo);
if (NS_WARN_IF(!principal)) {
return;
}
nsAutoCString origin;
nsresult rv = principal->GetOrigin(origin);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
Client* client = gReporting->mOrigins.Get(origin);
if (!client) {
return;
}
for (const Group& group : client->mGroups) {
if (group.mName == aGroupName) {
GetEndpointForReportInternal(group, aEndpointURI);
break;
}
}
}
/* static */ void ReportingHeader::GetEndpointForReportInternal(
const ReportingHeader::Group& aGroup, nsACString& aEndpointURI) {
TimeDuration diff = TimeStamp::Now() - aGroup.mCreationTime;
if (diff.ToSeconds() > aGroup.mTTL) {
// Expired.
return;
}
if (aGroup.mEndpoints.IsEmpty()) {
return;
}
int64_t minPriority = -1;
uint32_t totalWeight = 0;
for (const Endpoint& endpoint : aGroup.mEndpoints) {
if (minPriority == -1 || minPriority > endpoint.mPriority) {
minPriority = endpoint.mPriority;
totalWeight = endpoint.mWeight;
} else if (minPriority == endpoint.mPriority) {
totalWeight += endpoint.mWeight;
}
}
nsCOMPtr<nsIRandomGenerator> randomGenerator =
do_GetService("@mozilla.org/security/random-generator;1");
if (NS_WARN_IF(!randomGenerator)) {
return;
}
uint32_t randomNumber = 0;
uint8_t* buffer;
nsresult rv =
randomGenerator->GenerateRandomBytes(sizeof(randomNumber), &buffer);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
memcpy(&randomNumber, buffer, sizeof(randomNumber));
free(buffer);
totalWeight = randomNumber % totalWeight;
for (const Endpoint& endpoint : aGroup.mEndpoints) {
if (minPriority == endpoint.mPriority && totalWeight < endpoint.mWeight) {
Unused << NS_WARN_IF(NS_FAILED(endpoint.mUrl->GetSpec(aEndpointURI)));
break;
}
}
}
NS_INTERFACE_MAP_BEGIN(ReportingHeader)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsIObserver)

Просмотреть файл

@ -17,6 +17,11 @@ class nsIPrincipal;
class nsIURI;
namespace mozilla {
namespace ipc {
class PrincipalInfo;
}
namespace dom {
class ReportingHeader final : public nsIObserver {
@ -49,6 +54,11 @@ class ReportingHeader final : public nsIObserver {
static UniquePtr<Client> ParseHeader(nsIHttpChannel* aChannel, nsIURI* aURI,
const nsACString& aHeaderValue);
static void GetEndpointForReport(
const nsAString& aGroupName,
const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
nsACString& aEndpointURI);
private:
ReportingHeader();
~ReportingHeader();
@ -86,6 +96,9 @@ class ReportingHeader final : public nsIObserver {
const char* aMsg,
const nsTArray<nsString>& aParams);
static void GetEndpointForReportInternal(const ReportingHeader::Group& aGrup,
nsACString& aEndpointURI);
nsClassHashtable<nsCStringHashKey, Client> mOrigins;
};

Просмотреть файл

@ -6,7 +6,11 @@
#include "mozilla/dom/ReportingUtils.h"
#include "mozilla/dom/ReportBody.h"
#include "mozilla/dom/ReportDeliver.h"
#include "mozilla/dom/Report.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "nsAtom.h"
#include "nsPIDOMWindow.h"
@ -14,15 +18,22 @@ namespace mozilla {
namespace dom {
/* static */ void ReportingUtils::Report(nsPIDOMWindowInner* aWindow,
nsAtom* aType, const nsAString& aURL,
nsAtom* aType,
const nsAString& aGroupName,
const nsAString& aURL,
ReportBody* aBody) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aBody);
RefPtr<mozilla::dom::Report> report = new mozilla::dom::Report(
aWindow, nsDependentAtomString(aType), aURL, aBody);
nsDependentAtomString type(aType);
RefPtr<mozilla::dom::Report> report =
new mozilla::dom::Report(aWindow, type, aURL, aBody);
aWindow->BroadcastReport(report);
// Send the report to the server.
ReportDeliver::Record(aWindow, type, aGroupName, aURL, aBody);
}
} // namespace dom

Просмотреть файл

@ -19,7 +19,8 @@ class ReportBody;
class ReportingUtils final {
public:
static void Report(nsPIDOMWindowInner* aWindow, nsAtom* aType,
const nsAString& aURL, ReportBody* aBody);
const nsAString& aGroupName, const nsAString& aURL,
ReportBody* aBody);
};
} // namespace dom

Просмотреть файл

@ -6,9 +6,12 @@
EXPORTS.mozilla.dom = [
'DeprecationReportBody.h',
'EndpointForReportChild.h',
'EndpointForReportParent.h',
'FeaturePolicyViolationReportBody.h',
'Report.h',
'ReportBody.h',
'ReportDeliver.h',
'ReportingHeader.h',
'ReportingObserver.h',
'ReportingUtils.h',
@ -17,15 +20,22 @@ EXPORTS.mozilla.dom = [
UNIFIED_SOURCES += [
'DeprecationReportBody.cpp',
'EndpointForReportChild.cpp',
'EndpointForReportParent.cpp',
'FeaturePolicyViolationReportBody.cpp',
'Report.cpp',
'ReportBody.cpp',
'ReportDeliver.cpp',
'ReportingHeader.cpp',
'ReportingObserver.cpp',
'ReportingUtils.cpp',
'TestingDeprecatedInterface.cpp',
]
IPDL_SOURCES += [
'PEndpointForReport.ipdl',
]
include('/ipc/chromium/chromium-config.mozbuild')
with Files('**'):

Просмотреть файл

@ -149,6 +149,7 @@ FeaturePolicyUtils::DefaultAllowListFeature(const nsAString& aFeatureName) {
columnNumber, NS_LITERAL_STRING("enforce"));
ReportingUtils::Report(window, nsGkAtoms::featurePolicyViolation,
NS_LITERAL_STRING("default"),
NS_ConvertUTF8toUTF16(spec), body);
}

Просмотреть файл

@ -22,6 +22,7 @@
#include "mozilla/dom/PBackgroundLSSimpleRequestChild.h"
#include "mozilla/dom/PBackgroundSDBConnectionChild.h"
#include "mozilla/dom/PFileSystemRequestChild.h"
#include "mozilla/dom/EndpointForReportChild.h"
#include "mozilla/dom/FileSystemTaskBase.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h"
#include "mozilla/dom/cache/ActorUtils.h"
@ -772,6 +773,18 @@ bool BackgroundChildImpl::GetMessageSchedulerGroups(
return false;
}
dom::PEndpointForReportChild* BackgroundChildImpl::AllocPEndpointForReportChild(
const nsString& aGroupName, const PrincipalInfo& aPrincipalInfo) {
return new dom::EndpointForReportChild();
}
bool BackgroundChildImpl::DeallocPEndpointForReportChild(
PEndpointForReportChild* aActor) {
MOZ_ASSERT(aActor);
delete static_cast<dom::EndpointForReportChild*>(aActor);
return true;
}
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -287,6 +287,12 @@ class BackgroundChildImpl : public PBackgroundChild {
virtual bool DeallocPServiceWorkerRegistrationChild(
PServiceWorkerRegistrationChild*) override;
virtual PEndpointForReportChild* AllocPEndpointForReportChild(
const nsString& aGroupName, const PrincipalInfo& aPrincipalInfo) override;
virtual bool DeallocPEndpointForReportChild(
PEndpointForReportChild* aActor) override;
};
class BackgroundChildImpl::ThreadLocal final {

Просмотреть файл

@ -16,6 +16,7 @@
#include "mozilla/dom/ClientManagerActors.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/DOMTypes.h"
#include "mozilla/dom/EndpointForReportParent.h"
#include "mozilla/dom/FileSystemBase.h"
#include "mozilla/dom/FileSystemRequestParent.h"
#include "mozilla/dom/GamepadEventChannelParent.h"
@ -1203,6 +1204,29 @@ BackgroundParentImpl::RecvPServiceWorkerRegistrationConstructor(
return IPC_OK();
}
dom::PEndpointForReportParent*
BackgroundParentImpl::AllocPEndpointForReportParent(
const nsString& aGroupName, const PrincipalInfo& aPrincipalInfo) {
RefPtr<dom::EndpointForReportParent> actor =
new dom::EndpointForReportParent();
return actor.forget().take();
}
mozilla::ipc::IPCResult BackgroundParentImpl::RecvPEndpointForReportConstructor(
PEndpointForReportParent* aActor, const nsString& aGroupName,
const PrincipalInfo& aPrincipalInfo) {
static_cast<dom::EndpointForReportParent*>(aActor)->Run(aGroupName,
aPrincipalInfo);
return IPC_OK();
}
bool BackgroundParentImpl::DeallocPEndpointForReportParent(
PEndpointForReportParent* aActor) {
RefPtr<dom::EndpointForReportParent> actor =
dont_AddRef(static_cast<dom::EndpointForReportParent*>(aActor));
return true;
}
} // namespace ipc
} // namespace mozilla

Просмотреть файл

@ -357,6 +357,16 @@ class BackgroundParentImpl : public PBackgroundParent {
virtual mozilla::ipc::IPCResult RecvPServiceWorkerRegistrationConstructor(
PServiceWorkerRegistrationParent* aActor,
const IPCServiceWorkerRegistrationDescriptor& aDescriptor) override;
virtual PEndpointForReportParent* AllocPEndpointForReportParent(
const nsString& aGroupName, const PrincipalInfo& aPrincipalInfo) override;
virtual mozilla::ipc::IPCResult RecvPEndpointForReportConstructor(
PEndpointForReportParent* actor, const nsString& aGroupName,
const PrincipalInfo& aPrincipalInfo) override;
virtual bool DeallocPEndpointForReportParent(
PEndpointForReportParent* aActor) override;
};
} // namespace ipc

Просмотреть файл

@ -18,6 +18,7 @@ include protocol PCache;
include protocol PCacheStorage;
include protocol PCacheStreamControl;
include protocol PClientManager;
include protocol PEndpointForReport;
include protocol PFileDescriptorSet;
include protocol PFileSystemRequest;
include protocol PGamepadEventChannel;
@ -89,6 +90,7 @@ sync protocol PBackground
manages PCacheStorage;
manages PCacheStreamControl;
manages PClientManager;
manages PEndpointForReport;
manages PFileDescriptorSet;
manages PFileSystemRequest;
manages PGamepadEventChannel;
@ -213,6 +215,8 @@ parent:
async PServiceWorkerRegistration(IPCServiceWorkerRegistrationDescriptor aDescriptor);
async PEndpointForReport(nsString aGroupName, PrincipalInfo aPrincipalInfo);
child:
async PCache();
async PCacheStreamControl();