Bug 1449631 part 10. Devirtualize AddEventListener. r=smaug

The CanCallerAccess check in the "webidl" version of
nsGlobalWindowOuter::AddEventListener was pointless, because bindings never
call things on outer windows.

MozReview-Commit-ID: 1CGMJ277bPu
This commit is contained in:
Boris Zbarsky 2018-04-05 13:42:42 -04:00
parent 88937275cc
commit 2cdc7450c3
16 changed files with 112 additions and 305 deletions

View File

@ -4498,47 +4498,11 @@ nsGlobalWindowInner::DispatchEvent(Event& aEvent,
}
bool
nsGlobalWindowInner::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted)
nsGlobalWindowInner::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
{
if (!aWantsUntrusted.IsNull()) {
return aWantsUntrusted.Value();
}
return !nsContentUtils::IsChromeDoc(mDoc);
}
nsresult
nsGlobalWindowInner::AddEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
EventListenerManager* manager = GetOrCreateListenerManager();
NS_ENSURE_STATE(manager);
manager->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
return NS_OK;
}
void
nsGlobalWindowInner::AddEventListener(const nsAString& aType,
EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
EventListenerManager* manager = GetOrCreateListenerManager();
if (!manager) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
manager->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
}
NS_IMETHODIMP
nsGlobalWindowInner::AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,

View File

@ -324,20 +324,8 @@ public:
virtual mozilla::EventListenerManager*
GetOrCreateListenerManager() override;
using mozilla::dom::EventTarget::AddEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;
virtual nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) override;
/**
* A helper to determine the wantsUntrusted value from the given Nullable<bool>.
*/
bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted);
bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
virtual nsIGlobalObject* GetOwnerGlobal() const override;

View File

@ -6466,31 +6466,13 @@ nsGlobalWindowOuter::DispatchEvent(Event& aEvent,
FORWARD_TO_INNER(DispatchEvent, (aEvent, aCallerType, aRv), false);
}
nsresult
nsGlobalWindowOuter::AddEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
bool
nsGlobalWindowOuter::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
{
FORWARD_TO_INNER_CREATE(AddEventListener,
(aType, aListener, aUseCapture, aWantsUntrusted),
NS_ERROR_UNEXPECTED);
}
void
nsGlobalWindowOuter::AddEventListener(const nsAString& aType,
EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
if (mInnerWindow && !nsContentUtils::CanCallerAccess(mInnerWindow)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
FORWARD_TO_INNER_CREATE(AddEventListener,
(aType, aListener, aOptions, aWantsUntrusted, aRv),);
// It's OK that we just return false here on failure to create an
// inner. GetOrCreateListenerManager() will likewise fail, and then
// we won't be adding any listeners anyway.
FORWARD_TO_INNER_CREATE(ComputeDefaultWantsUntrusted, (aRv), false);
}
NS_IMETHODIMP

View File

@ -281,16 +281,8 @@ public:
virtual mozilla::EventListenerManager*
GetOrCreateListenerManager() override;
using mozilla::dom::EventTarget::AddEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;
virtual nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) override;
bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
virtual nsPIDOMWindowOuter* GetOwnerGlobalForBindings() override;
virtual nsIGlobalObject* GetOwnerGlobal() const override;

View File

@ -1017,49 +1017,11 @@ nsINode::LookupNamespaceURI(const nsAString& aNamespacePrefix,
}
bool
nsINode::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted)
nsINode::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
{
if (!aWantsUntrusted.IsNull()) {
return aWantsUntrusted.Value();
}
return !nsContentUtils::IsChromeDoc(OwnerDoc());
}
nsresult
nsINode::AddEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
EventListenerManager* listener_manager = GetOrCreateListenerManager();
NS_ENSURE_STATE(listener_manager);
listener_manager->AddEventListener(aType, aListener, aUseCapture,
wantsUntrusted);
return NS_OK;
}
void
nsINode::AddEventListener(const nsAString& aType,
EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
EventListenerManager* listener_manager = GetOrCreateListenerManager();
if (!listener_manager) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
listener_manager->AddEventListener(aType, aListener, aOptions,
wantsUntrusted);
}
NS_IMETHODIMP
nsINode::AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,

View File

@ -1029,20 +1029,7 @@ public:
virtual mozilla::EventListenerManager*
GetOrCreateListenerManager() override;
using mozilla::dom::EventTarget::AddEventListener;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;
virtual nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) override;
/**
* A helper to determine the wantsUntrusted value from the given Nullable<bool>.
*/
bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted);
bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
using nsIDOMEventTarget::AddSystemEventListener;
virtual bool IsApzAware() const override;

View File

@ -85,42 +85,11 @@ nsWindowRoot::DispatchEvent(Event& aEvent, CallerType aCallerType,
}
bool
nsWindowRoot::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted)
nsWindowRoot::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
{
return !aWantsUntrusted.IsNull() && aWantsUntrusted.Value();
return false;
}
nsresult
nsWindowRoot::AddEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
EventListenerManager* elm = GetOrCreateListenerManager();
NS_ENSURE_STATE(elm);
elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
return NS_OK;
}
void
nsWindowRoot::AddEventListener(const nsAString& aType,
EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted);
EventListenerManager* elm = GetOrCreateListenerManager();
if (!elm) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
}
NS_IMETHODIMP
nsWindowRoot::AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener *aListener,

View File

@ -32,19 +32,7 @@ public:
virtual mozilla::EventListenerManager*
GetOrCreateListenerManager() override;
virtual void AddEventListener(const nsAString& aType,
mozilla::dom::EventListener* aListener,
const mozilla::dom::AddEventListenerOptionsOrBoolean& aOptions,
const mozilla::dom::Nullable<bool>& aWantsUntrusted,
mozilla::ErrorResult& aRv) override;
virtual nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) override;
/**
* A helper to determine the wantsUntrusted value from the given Nullable<bool>.
*/
bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted);
bool ComputeDefaultWantsUntrusted(mozilla::ErrorResult& aRv) final;
bool DispatchEvent(mozilla::dom::Event& aEvent,
mozilla::dom::CallerType aCallerType,

View File

@ -174,13 +174,8 @@ DOMEventTargetHelper::GetDocumentIfCurrent() const
}
bool
DOMEventTargetHelper::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
DOMEventTargetHelper::ComputeDefaultWantsUntrusted(ErrorResult& aRv)
{
if (!aWantsUntrusted.IsNull()) {
return aWantsUntrusted.Value();
}
bool wantsUntrusted;
nsresult rv = WantsUntrusted(&wantsUntrusted);
if (NS_FAILED(rv)) {
@ -190,45 +185,6 @@ DOMEventTargetHelper::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntruste
return wantsUntrusted;
}
nsresult
DOMEventTargetHelper::AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
{
ErrorResult rv;
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, rv);
if (rv.Failed()) {
return rv.StealNSResult();
}
EventListenerManager* elm = GetOrCreateListenerManager();
NS_ENSURE_STATE(elm);
elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
return NS_OK;
}
void
DOMEventTargetHelper::AddEventListener(const nsAString& aType,
EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, aRv);
if (aRv.Failed()) {
return;
}
EventListenerManager* elm = GetOrCreateListenerManager();
if (!elm) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
elm->AddEventListener(aType, aListener, aOptions, wantsUntrusted);
}
NS_IMETHODIMP
DOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,

View File

@ -73,21 +73,7 @@ public:
virtual EventListenerManager* GetExistingListenerManager() const override;
virtual EventListenerManager* GetOrCreateListenerManager() override;
using EventTarget::AddEventListener;
virtual void AddEventListener(const nsAString& aType,
dom::EventListener* aListener,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
const dom::Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) override;
virtual nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) override;
/**
* A helper to determine the wantsUntrusted value from the given Nullable<bool>.
*/
bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv);
bool ComputeDefaultWantsUntrusted(ErrorResult& aRv) override;
using EventTarget::DispatchEvent;
bool DispatchEvent(dom::Event& aEvent, dom::CallerType aCallerType,

View File

@ -27,6 +27,61 @@ EventTarget::Constructor(const GlobalObject& aGlobal, ErrorResult& aRv)
return target.forget();
}
bool
EventTarget::ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
if (!aWantsUntrusted.IsNull()) {
return aWantsUntrusted.Value();
}
bool defaultWantsUntrusted = ComputeDefaultWantsUntrusted(aRv);
if (aRv.Failed()) {
return false;
}
return defaultWantsUntrusted;
}
void
EventTarget::AddEventListener(const nsAString& aType,
EventListener* aCallback,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
{
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, aRv);
if (aRv.Failed()) {
return;
}
EventListenerManager* elm = GetOrCreateListenerManager();
if (!elm) {
aRv.Throw(NS_ERROR_UNEXPECTED);
return;
}
elm->AddEventListener(aType, aCallback, aOptions, wantsUntrusted);
}
nsresult
EventTarget::AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
{
ErrorResult rv;
bool wantsUntrusted = ComputeWantsUntrusted(aWantsUntrusted, rv);
if (rv.Failed()) {
return rv.StealNSResult();
}
EventListenerManager* elm = GetOrCreateListenerManager();
NS_ENSURE_STATE(elm);
elm->AddEventListener(aType, aListener, aUseCapture, wantsUntrusted);
return NS_OK;
}
void
EventTarget::RemoveEventListener(const nsAString& aType,
EventListener* aListener,

View File

@ -54,11 +54,11 @@ public:
// WebIDL API
static already_AddRefed<EventTarget> Constructor(const GlobalObject& aGlobal,
ErrorResult& aRv);
virtual void AddEventListener(const nsAString& aType,
EventListener* aCallback,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) = 0;
void AddEventListener(const nsAString& aType,
EventListener* aCallback,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv);
void RemoveEventListener(const nsAString& aType,
EventListener* aCallback,
const EventListenerOptionsOrBoolean& aOptions,
@ -71,10 +71,10 @@ protected:
* standard AddEventListener. The one difference is that it just
* has a "use capture" boolean, not an EventListenerOptions.
*/
virtual nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) = 0;
nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted);
public:
/**
@ -268,6 +268,25 @@ protected:
const nsAString& aTypeString);
void SetEventHandler(nsAtom* aType, const nsAString& aTypeString,
EventHandlerNonNull* aHandler);
/**
* Hook for AddEventListener that allows it to compute the right
* wantsUntrusted boolean when one is not provided. If this returns failure,
* the listener will not be added.
*
* This hook will NOT be called unless aWantsUntrusted is null in
* AddEventListener. If you need to take action when event listeners are
* added, use EventListenerAdded. Especially because not all event listener
* additions go through AddEventListener!
*/
virtual bool ComputeDefaultWantsUntrusted(ErrorResult& aRv) = 0;
/**
* A method to compute the right wantsUntrusted value for AddEventListener.
* This will call the above hook as needed.
*/
bool ComputeWantsUntrusted(const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv);
};
NS_DEFINE_STATIC_IID_ACCESSOR(EventTarget, NS_EVENTTARGET_IID)

View File

@ -271,32 +271,11 @@ MediaDevices::SetOndevicechange(mozilla::dom::EventHandlerNonNull* aCallback)
MediaManager::Get()->AddDeviceChangeCallback(this);
}
nsresult
MediaDevices::AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted)
{
MediaManager::Get()->AddDeviceChangeCallback(this);
return DOMEventTargetHelper::AddEventListener(aType, aListener,
aUseCapture,
aWantsUntrusted);
}
void
MediaDevices::AddEventListener(const nsAString& aType,
EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
MediaDevices::EventListenerAdded(nsAtom* aType)
{
MediaManager::Get()->AddDeviceChangeCallback(this);
return DOMEventTargetHelper::AddEventListener(aType, aListener,
aOptions,
aWantsUntrusted,
aRv);
DOMEventTargetHelper::EventListenerAdded(aType);
}
JSObject*

View File

@ -51,16 +51,8 @@ public:
void SetOndevicechange(mozilla::dom::EventHandlerNonNull* aCallback);
nsresult AddEventListener(const nsAString& aType,
nsIDOMEventListener* aListener,
bool aUseCapture,
const Nullable<bool>& aWantsUntrusted) override;
virtual void AddEventListener(const nsAString& aType,
dom::EventListener* aListener,
const AddEventListenerOptionsOrBoolean& aOptions,
const Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) override;
void EventListenerAdded(nsAtom* aType) override;
using DOMEventTargetHelper::EventListenerAdded;
private:
class GumResolver;

View File

@ -788,19 +788,11 @@ ServiceWorkerGlobalScope::SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallbac
}
void
ServiceWorkerGlobalScope::AddEventListener(
const nsAString& aType,
dom::EventListener* aListener,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
const dom::Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv)
ServiceWorkerGlobalScope::EventListenerAdded(const nsAString& aType)
{
MOZ_ASSERT(mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
DOMEventTargetHelper::AddEventListener(aType, aListener, aOptions,
aWantsUntrusted, aRv);
if (!aType.EqualsLiteral("fetch")) {
return;
}
@ -810,9 +802,7 @@ ServiceWorkerGlobalScope::AddEventListener(
mWorkerPrivate->DispatchToMainThread(r.forget());
}
if (!aRv.Failed()) {
mWorkerPrivate->SetFetchHandlerWasAdded();
}
mWorkerPrivate->SetFetchHandlerWasAdded();
}
namespace {

View File

@ -346,13 +346,11 @@ public:
void
SetOnfetch(mozilla::dom::EventHandlerNonNull* aCallback);
using DOMEventTargetHelper::AddEventListener;
virtual void
AddEventListener(const nsAString& aType,
dom::EventListener* aListener,
const dom::AddEventListenerOptionsOrBoolean& aOptions,
const dom::Nullable<bool>& aWantsUntrusted,
ErrorResult& aRv) override;
// We only need to override the string version of EventListenerAdded, because
// the atom version should never be called on workers. Until bug 1450167 is
// fixed, at least.
using DOMEventTargetHelper::EventListenerAdded;
void EventListenerAdded(const nsAString& aType) override;
};
class WorkerDebuggerGlobalScope final : public DOMEventTargetHelper,