Bug 1668134 - part 2: Make nsPIDOMWindowInner have an API to know whether a node is (was) in the window has been observed by web apps with a mutation observer r=smaug

There is similar API in `Document`, but they indicate whether a node has been
observed by any mutation receiver, not only by `MutationObserver` of JS.
However, I'd like to know the percentage of web apps which use
`MutationObserver`, but not use `beforeinput` events.  Therefore, this patch
adds similar API into `nsPIDOMWindowInner` as same as `beforeinput` and
ignores `MutationObserver`s which are created by chrome script and addons.

Differential Revision: https://phabricator.services.mozilla.com/D92547
This commit is contained in:
Masayuki Nakano 2020-10-08 02:25:35 +00:00
parent 8c5fa85517
commit 0f46ae6a8e
6 changed files with 51 additions and 3 deletions

View File

@ -593,7 +593,7 @@ void nsDOMMutationObserver::RescheduleForRun() {
void nsDOMMutationObserver::Observe(
nsINode& aTarget, const mozilla::dom::MutationObserverInit& aOptions,
mozilla::ErrorResult& aRv) {
nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aRv) {
bool childList = aOptions.mChildList;
bool attributes =
aOptions.mAttributes.WasPassed() && aOptions.mAttributes.Value();
@ -673,6 +673,13 @@ void nsDOMMutationObserver::Observe(
r->SetAnimations(animations);
r->RemoveClones();
if (!aSubjectPrincipal.IsSystemPrincipal() &&
!aSubjectPrincipal.GetIsAddonOrExpandedAddonPrincipal()) {
if (nsPIDOMWindowInner* window = aTarget.OwnerDoc()->GetInnerWindow()) {
window->SetMutationObserverHasObservedNodeForTelemetry();
}
}
#ifdef DEBUG
for (int32_t i = 0; i < mReceivers.Count(); ++i) {
NS_WARNING_ASSERTION(mReceivers[i]->Target(),

View File

@ -29,6 +29,8 @@
#include "nsTArray.h"
#include "nsWrapperCache.h"
class nsIPrincipal;
class nsDOMMutationObserver;
using mozilla::dom::MutationObservingInfo;
@ -461,7 +463,7 @@ class nsDOMMutationObserver final : public nsISupports, public nsWrapperCache {
void Observe(nsINode& aTarget,
const mozilla::dom::MutationObserverInit& aOptions,
mozilla::ErrorResult& aRv);
nsIPrincipal& aSubjectPrincipal, mozilla::ErrorResult& aRv);
void Disconnect();

View File

@ -7480,6 +7480,7 @@ nsPIDOMWindowInner::nsPIDOMWindowInner(nsPIDOMWindowOuter* aOuterWindow,
mMayHaveMouseEnterLeaveEventListener(false),
mMayHavePointerEnterLeaveEventListener(false),
mMayHaveBeforeInputEventListenerForTelemetry(false),
mMutationObserverHasObservedNodeForTelemetry(false),
mOuterWindow(aOuterWindow),
mWindowID(0),
mHasNotifiedGlobalCreated(false),

View File

@ -242,6 +242,26 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
mMayHaveBeforeInputEventListenerForTelemetry = true;
}
/**
* Call this to check whether some node (The document, or content in the
* document) has been observed by web apps with a mutation observer.
* (i.e., `MutationObserver.observe()` called by chrome script and addon's
* script does not make this returns true).
* Returing false may be wrong if some nodes have come from another document
* with `Document.adoptNode`.
*/
bool MutationObserverHasObservedNodeForTelemetry() const {
return mMutationObserverHasObservedNodeForTelemetry;
}
/**
* Call this to indicate that some node (The document, or content in the
* document) is observed by web apps with a mutation observer.
*/
void SetMutationObserverHasObservedNodeForTelemetry() {
mMutationObserverHasObservedNodeForTelemetry = true;
}
// Sets the event for window.event. Does NOT take ownership, so
// the caller is responsible for clearing the event before the
// event gets deallocated. Pass nullptr to set window.event to
@ -609,6 +629,7 @@ class nsPIDOMWindowInner : public mozIDOMWindow {
// Only used for telemetry probes. This may be wrong if some nodes have
// come from another document with `Document.adoptNode`.
bool mMayHaveBeforeInputEventListenerForTelemetry;
bool mMutationObserverHasObservedNodeForTelemetry;
// Our inner window's outer window.
nsCOMPtr<nsPIDOMWindowOuter> mOuterWindow;

View File

@ -43,7 +43,7 @@ interface MutationObserver {
[Throws]
constructor(MutationCallback mutationCallback);
[Throws]
[Throws, NeedsSubjectPrincipal]
void observe(Node target, optional MutationObserverInit options = {});
void disconnect();
sequence<MutationRecord> takeRecords();

View File

@ -246,6 +246,23 @@ class EditorBase : public nsIEditor,
return false;
}
/**
* MutationObserverHasObservedNodeForTelemetry() returns true when a node in
* the window may have been observed by the web apps with a mutation observer
* (i.e., `MutationObserver.observe()` called by chrome script and addon's
* script does not make this returns true).
* Note that this may return false even if there is a node observed by
* a MutationObserver. See
* nsPIDOMWindowInner::MutationObserverHasObservedNodeForTelemetry()'s comment
* for the detail.
*/
bool MutationObserverHasObservedNodeForTelemetry() const {
if (const nsPIDOMWindowInner* window = GetInnerWindow()) {
return window->MutationObserverHasObservedNodeForTelemetry();
}
return false;
}
PresShell* GetPresShell() const {
return mDocument ? mDocument->GetPresShell() : nullptr;
}