Bug 1492036 - Reporting API - part 4 - Reporting, r=smaug

This commit is contained in:
Andrea Marchesini 2018-11-14 20:02:33 +01:00
parent db43f2464c
commit d9e70a0be6
8 changed files with 204 additions and 5 deletions

View File

@ -237,6 +237,8 @@
#include "mozilla/dom/ImageBitmap.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/InstallTriggerBinding.h"
#include "mozilla/dom/Report.h"
#include "mozilla/dom/ReportingObserver.h"
#include "mozilla/dom/ServiceWorker.h"
#include "mozilla/dom/ServiceWorkerRegistration.h"
#include "mozilla/dom/ServiceWorkerRegistrationDescriptor.h"
@ -337,6 +339,9 @@ using mozilla::dom::cache::CacheStorage;
// Min idle notification time in seconds.
#define MIN_IDLE_NOTIFICATION_TIME_S 1
// Max number of Report objects
#define MAX_REPORT_RECORDS 100
static LazyLogModule gDOMLeakPRLogInner("DOMLeakInner");
static bool gIdleObserversAPIFuzzTimeDisabled = false;
@ -1469,6 +1474,8 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsGlobalWindowInner)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mExternal)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mInstallTrigger)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mIntlUtils)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReportRecords)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReportingObservers)
tmp->TraverseHostObjectURIs(cb);
@ -1558,6 +1565,8 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindowInner)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mExternal)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mInstallTrigger)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mIntlUtils)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReportRecords)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReportingObservers)
tmp->UnlinkHostObjectURIs();
@ -8079,6 +8088,62 @@ nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter *aOuterWindow)
MOZ_ASSERT(aOuterWindow);
}
void
nsPIDOMWindowInner::RegisterReportingObserver(ReportingObserver* aObserver,
bool aBuffered)
{
MOZ_ASSERT(aObserver);
if (mReportingObservers.Contains(aObserver)) {
return;
}
if (NS_WARN_IF(!mReportingObservers.AppendElement(aObserver, fallible))) {
return;
}
if (!aBuffered) {
return;
}
for (Report* report : mReportRecords) {
aObserver->MaybeReport(report);
}
}
void
nsPIDOMWindowInner::UnregisterReportingObserver(ReportingObserver* aObserver)
{
MOZ_ASSERT(aObserver);
mReportingObservers.RemoveElement(aObserver);
}
void
nsPIDOMWindowInner::BroadcastReport(Report* aReport)
{
MOZ_ASSERT(aReport);
for (ReportingObserver* observer : mReportingObservers) {
observer->MaybeReport(aReport);
}
if (NS_WARN_IF(!mReportRecords.AppendElement(aReport, fallible))) {
return;
}
while (mReportRecords.Length() > MAX_REPORT_RECORDS) {
mReportRecords.RemoveElementAt(0);
}
}
void
nsPIDOMWindowInner::NotifyReportingObservers()
{
for (ReportingObserver* observer : mReportingObservers) {
observer->MaybeNotify();
}
}
nsPIDOMWindowInner::~nsPIDOMWindowInner() {}
#undef FORWARD_TO_OUTER

View File

@ -58,6 +58,9 @@ class Element;
class MozIdleObserver;
class Navigator;
class Performance;
class Report;
class ReportBody;
class ReportingObserver;
class Selection;
class ServiceWorker;
class ServiceWorkerDescriptor;
@ -618,6 +621,19 @@ public:
already_AddRefed<mozilla::AutoplayPermissionManager>
GetAutoplayPermissionManager();
void
RegisterReportingObserver(mozilla::dom::ReportingObserver* aObserver,
bool aBuffered);
void
UnregisterReportingObserver(mozilla::dom::ReportingObserver* aObserver);
void
BroadcastReport(mozilla::dom::Report* aReport);
void
NotifyReportingObservers();
protected:
void CreatePerformanceObjectIfNeeded();
@ -709,6 +725,10 @@ protected:
// The event dispatch code sets and unsets this while keeping
// the event object alive.
mozilla::dom::Event* mEvent;
// List of Report objects for ReportingObservers.
nsTArray<RefPtr<mozilla::dom::ReportingObserver>> mReportingObservers;
nsTArray<RefPtr<mozilla::dom::Report>> mReportRecords;
};
NS_DEFINE_STATIC_IID_ACCESSOR(nsPIDOMWindowInner, NS_PIDOMWINDOWINNER_IID)

View File

@ -30,6 +30,7 @@
#include "nsINode.h"
#include "nsIPermissionManager.h"
#include "nsIPrincipal.h"
#include "nsIURIFixup.h"
#include "nsIXPConnect.h"
#include "nsUTF8Utils.h"
#include "WorkerPrivate.h"
@ -4122,8 +4123,22 @@ ReportDeprecation(nsPIDOMWindowInner* aWindow, nsIURI* aURI,
{
MOZ_ASSERT(aURI);
// Anonymize the URL.
// Strip the URL of any possible username/password and make it ready to be
// presented in the UI.
nsCOMPtr<nsIURIFixup> urifixup = services::GetURIFixup();
if (NS_WARN_IF(!urifixup)) {
return;
}
nsCOMPtr<nsIURI> exposableURI;
nsresult rv = urifixup->CreateExposableURI(aURI, getter_AddRefs(exposableURI));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoCString spec;
nsresult rv = aURI->GetSpec(spec);
rv = exposableURI->GetSpec(spec);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}

View File

@ -34,6 +34,14 @@ Report::Report(nsPIDOMWindowInner* aWindow,
Report::~Report() = default;
already_AddRefed<Report>
Report::Clone()
{
RefPtr<Report> report =
new Report(mWindow, mType, mURL, mBody);
return report.forget();
}
JSObject*
Report::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
{

View File

@ -29,6 +29,9 @@ public:
const nsAString& aURL,
ReportBody* aBody);
already_AddRefed<Report>
Clone();
JSObject*
WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;

View File

@ -15,12 +15,14 @@ namespace dom {
NS_IMPL_CYCLE_COLLECTION_CLASS(ReportingObserver)
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ReportingObserver)
tmp->Disconnect();
NS_IMPL_CYCLE_COLLECTION_UNLINK(mReports)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mCallback)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(ReportingObserver)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mReports)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mCallback)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
@ -79,19 +81,82 @@ ReportingObserver::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
void
ReportingObserver::Observe()
{
// TODO
mWindow->RegisterReportingObserver(this, mBuffered);
}
void
ReportingObserver::Disconnect()
{
// TODO
if (mWindow) {
mWindow->UnregisterReportingObserver(this);
}
}
void
ReportingObserver::TakeRecords(nsTArray<RefPtr<Report>>& aRecords)
{
// TODO
mReports.SwapElements(aRecords);
}
void
ReportingObserver::MaybeReport(Report* aReport)
{
MOZ_ASSERT(aReport);
if (!mTypes.IsEmpty()) {
nsAutoString type;
aReport->GetType(type);
if (!mTypes.Contains(type)) {
return;
}
}
bool wasEmpty = mReports.IsEmpty();
RefPtr<Report> report = aReport->Clone();
MOZ_ASSERT(report);
if (NS_WARN_IF(!mReports.AppendElement(report, fallible))) {
return;
}
if (!wasEmpty) {
return;
}
nsCOMPtr<nsPIDOMWindowInner> window = mWindow;
nsCOMPtr<nsIRunnable> r =
NS_NewRunnableFunction(
"ReportingObserver::MaybeReport",
[window]() {
window->NotifyReportingObservers();
});
NS_DispatchToCurrentThread(r);
}
void
ReportingObserver::MaybeNotify()
{
if (mReports.IsEmpty()) {
return;
}
// Let's take the ownership of the reports.
nsTArray<RefPtr<Report>> list;
list.SwapElements(mReports);
Sequence<OwningNonNull<Report>> reports;
for (Report* report : list) {
if (NS_WARN_IF(!reports.AppendElement(*report, fallible))) {
return;
}
}
// We should report if this throws exception. But where?
mCallback->Call(reports, *this);
}
} // dom namespace

View File

@ -11,12 +11,17 @@
#include "mozilla/dom/BindingUtils.h"
#include "nsCycleCollectionParticipant.h"
#include "nsWrapperCache.h"
#include "nsTArray.h"
class nsPIDOMWindowInner;
namespace mozilla {
namespace dom {
class Report;
class ReportingObserverCallback;
struct ReportingObserverOptions;
class ReportingObserver final : public nsISupports
, public nsWrapperCache
{
@ -53,9 +58,17 @@ public:
void
TakeRecords(nsTArray<RefPtr<Report>>& aRecords);
void
MaybeReport(Report* aReport);
void
MaybeNotify();
private:
~ReportingObserver();
nsTArray<RefPtr<Report>> mReports;
nsCOMPtr<nsPIDOMWindowInner> mWindow;
RefPtr<ReportingObserverCallback> mCallback;
nsTArray<nsString> mTypes;

View File

@ -6,6 +6,9 @@
#include "mozilla/dom/ReportingUtils.h"
#include "mozilla/dom/ReportBody.h"
#include "mozilla/dom/Report.h"
#include "nsAtom.h"
#include "nsPIDOMWindow.h"
namespace mozilla {
namespace dom {
@ -16,7 +19,14 @@ ReportingUtils::Report(nsPIDOMWindowInner* aWindow,
const nsAString& aURL,
ReportBody* aBody)
{
// TODO
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(aWindow);
MOZ_ASSERT(aBody);
RefPtr<mozilla::dom::Report> report =
new mozilla::dom::Report(aWindow, nsDependentAtomString(aType), aURL,
aBody);
aWindow->BroadcastReport(report);
}
} // dom namespace