2009-06-15 08:27:29 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
2012-05-21 11:12:37 +00:00
|
|
|
/* 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/. */
|
2009-06-15 08:27:29 +00:00
|
|
|
|
|
|
|
#include "nsDOMEventTargetHelper.h"
|
|
|
|
#include "nsContentUtils.h"
|
|
|
|
#include "nsEventDispatcher.h"
|
|
|
|
#include "nsGUIEvent.h"
|
|
|
|
#include "nsIDocument.h"
|
2012-02-08 02:53:33 +00:00
|
|
|
#include "nsIJSContextStack.h"
|
|
|
|
#include "nsDOMJSUtils.h"
|
2012-02-12 13:33:51 +00:00
|
|
|
#include "prprf.h"
|
2012-03-13 00:56:07 +00:00
|
|
|
#include "nsGlobalWindow.h"
|
2009-06-15 08:27:29 +00:00
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventListenerWrapper)
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventListenerWrapper)
|
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
|
|
|
NS_INTERFACE_MAP_END_AGGREGATED(mListener)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventListenerWrapper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventListenerWrapper)
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventListenerWrapper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListener)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsDOMEventListenerWrapper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListener)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMEventListenerWrapper::HandleEvent(nsIDOMEvent* aEvent)
|
|
|
|
{
|
|
|
|
return mListener->HandleEvent(aEvent);
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_CLASS(nsDOMEventTargetHelper)
|
|
|
|
|
2012-02-08 02:53:33 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsDOMEventTargetHelper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRACE_END
|
|
|
|
|
2012-02-12 13:09:18 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INTERNAL(nsDOMEventTargetHelper)
|
|
|
|
if (NS_UNLIKELY(cb.WantDebugInfo())) {
|
|
|
|
char name[512];
|
|
|
|
nsAutoString uri;
|
|
|
|
if (tmp->mOwner && tmp->mOwner->GetExtantDocument()) {
|
|
|
|
tmp->mOwner->GetExtantDocument()->GetDocumentURI(uri);
|
|
|
|
}
|
|
|
|
PR_snprintf(name, sizeof(name), "nsDOMEventTargetHelper %s",
|
|
|
|
NS_ConvertUTF16toUTF8(uri).get());
|
|
|
|
cb.DescribeRefCountedNode(tmp->mRefCnt.get(), sizeof(nsDOMEventTargetHelper),
|
|
|
|
name);
|
|
|
|
} else {
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_DESCRIBE(nsDOMEventTargetHelper, tmp->mRefCnt.get())
|
|
|
|
}
|
|
|
|
|
2012-02-08 02:53:33 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_SCRIPT_OBJECTS
|
2011-06-24 02:18:01 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
|
|
|
|
nsEventListenerManager)
|
2009-06-15 08:27:29 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
|
|
|
|
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsDOMEventTargetHelper)
|
2012-02-08 02:53:33 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
|
2009-06-15 08:27:29 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
|
|
|
|
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
|
|
|
|
|
|
|
|
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMEventTargetHelper)
|
2012-02-08 02:53:33 +00:00
|
|
|
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
2011-06-24 02:18:01 +00:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
2009-06-15 08:27:29 +00:00
|
|
|
NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
|
|
|
|
NS_INTERFACE_MAP_END
|
|
|
|
|
2011-03-06 11:11:31 +00:00
|
|
|
NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMEventTargetHelper)
|
|
|
|
NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMEventTargetHelper)
|
2009-06-15 08:27:29 +00:00
|
|
|
|
2011-06-24 02:17:58 +00:00
|
|
|
NS_IMPL_DOMTARGET_DEFAULTS(nsDOMEventTargetHelper);
|
2009-06-15 08:27:29 +00:00
|
|
|
|
2011-12-08 08:31:14 +00:00
|
|
|
nsDOMEventTargetHelper::~nsDOMEventTargetHelper()
|
|
|
|
{
|
2012-03-13 00:56:07 +00:00
|
|
|
if (mOwner) {
|
|
|
|
static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
|
|
|
|
}
|
2011-12-08 08:31:14 +00:00
|
|
|
if (mListenerManager) {
|
|
|
|
mListenerManager->Disconnect();
|
|
|
|
}
|
2012-02-08 02:53:33 +00:00
|
|
|
nsContentUtils::ReleaseWrapper(this, this);
|
2011-12-08 08:31:14 +00:00
|
|
|
}
|
|
|
|
|
2012-03-13 00:56:07 +00:00
|
|
|
void
|
|
|
|
nsDOMEventTargetHelper::BindToOwner(nsPIDOMWindow* aOwner)
|
|
|
|
{
|
|
|
|
if (mOwner) {
|
|
|
|
static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
|
2012-07-30 14:20:58 +00:00
|
|
|
mOwner = nullptr;
|
2012-03-13 00:56:07 +00:00
|
|
|
mHasOrHasHadOwner = false;
|
|
|
|
}
|
|
|
|
if (aOwner) {
|
|
|
|
mOwner = aOwner;
|
|
|
|
mHasOrHasHadOwner = true;
|
|
|
|
static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDOMEventTargetHelper::BindToOwner(nsDOMEventTargetHelper* aOther)
|
|
|
|
{
|
|
|
|
if (mOwner) {
|
|
|
|
static_cast<nsGlobalWindow*>(mOwner)->RemoveEventTargetObject(this);
|
2012-07-30 14:20:58 +00:00
|
|
|
mOwner = nullptr;
|
2012-03-13 00:56:07 +00:00
|
|
|
mHasOrHasHadOwner = false;
|
|
|
|
}
|
|
|
|
if (aOther) {
|
|
|
|
mHasOrHasHadOwner = aOther->HasOrHasHadOwner();
|
|
|
|
if (aOther->GetOwner()) {
|
|
|
|
mOwner = aOther->GetOwner();
|
|
|
|
mHasOrHasHadOwner = true;
|
|
|
|
static_cast<nsGlobalWindow*>(mOwner)->AddEventTargetObject(this);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsDOMEventTargetHelper::DisconnectFromOwner()
|
|
|
|
{
|
2012-07-30 14:20:58 +00:00
|
|
|
mOwner = nullptr;
|
2012-03-13 00:56:07 +00:00
|
|
|
// Event listeners can't be handled anymore, so we can release them here.
|
|
|
|
if (mListenerManager) {
|
|
|
|
mListenerManager->Disconnect();
|
2012-07-30 14:20:58 +00:00
|
|
|
mListenerManager = nullptr;
|
2012-03-13 00:56:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-06-15 08:27:29 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMEventTargetHelper::RemoveEventListener(const nsAString& aType,
|
|
|
|
nsIDOMEventListener* aListener,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool aUseCapture)
|
2009-06-15 08:27:29 +00:00
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
nsEventListenerManager* elm = GetListenerManager(false);
|
2009-06-15 08:27:29 +00:00
|
|
|
if (elm) {
|
2011-06-24 02:18:02 +00:00
|
|
|
elm->RemoveEventListener(aType, aListener, aUseCapture);
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2011-11-25 01:09:58 +00:00
|
|
|
NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsDOMEventTargetHelper)
|
|
|
|
|
2009-06-15 08:27:29 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMEventTargetHelper::AddEventListener(const nsAString& aType,
|
|
|
|
nsIDOMEventListener *aListener,
|
2011-09-29 06:19:26 +00:00
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted,
|
2012-08-22 15:56:38 +00:00
|
|
|
uint8_t aOptionalArgc)
|
2009-06-15 08:27:29 +00:00
|
|
|
{
|
2011-06-24 02:17:59 +00:00
|
|
|
NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
|
2010-01-13 13:50:01 +00:00
|
|
|
"Won't check if this is chrome, you want to set "
|
2011-10-17 14:59:28 +00:00
|
|
|
"aWantsUntrusted to false or make the aWantsUntrusted "
|
2011-06-24 02:17:59 +00:00
|
|
|
"explicit by making aOptionalArgc non-zero.");
|
2010-01-13 13:50:01 +00:00
|
|
|
|
2011-06-24 02:17:59 +00:00
|
|
|
if (aOptionalArgc < 2) {
|
2010-01-13 13:50:01 +00:00
|
|
|
nsresult rv;
|
|
|
|
nsIScriptContext* context = GetContextForEventHandlers(&rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDocument> doc =
|
|
|
|
nsContentUtils::GetDocumentFromScriptContext(context);
|
|
|
|
aWantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
|
|
|
|
}
|
|
|
|
|
2011-10-17 14:59:28 +00:00
|
|
|
nsEventListenerManager* elm = GetListenerManager(true);
|
2011-06-24 02:18:02 +00:00
|
|
|
NS_ENSURE_STATE(elm);
|
2011-08-18 09:45:00 +00:00
|
|
|
elm->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
|
|
|
|
return NS_OK;
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
|
2011-11-25 01:09:58 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsDOMEventTargetHelper::AddSystemEventListener(const nsAString& aType,
|
|
|
|
nsIDOMEventListener *aListener,
|
|
|
|
bool aUseCapture,
|
|
|
|
bool aWantsUntrusted,
|
2012-08-22 15:56:38 +00:00
|
|
|
uint8_t aOptionalArgc)
|
2011-11-25 01:09:58 +00:00
|
|
|
{
|
|
|
|
NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
|
|
|
|
"Won't check if this is chrome, you want to set "
|
|
|
|
"aWantsUntrusted to false or make the aWantsUntrusted "
|
|
|
|
"explicit by making aOptionalArgc non-zero.");
|
|
|
|
|
|
|
|
if (aOptionalArgc < 2) {
|
|
|
|
nsresult rv;
|
|
|
|
nsIScriptContext* context = GetContextForEventHandlers(&rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
nsCOMPtr<nsIDocument> doc =
|
|
|
|
nsContentUtils::GetDocumentFromScriptContext(context);
|
|
|
|
aWantsUntrusted = doc && !nsContentUtils::IsChromeDoc(doc);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
|
|
|
|
aWantsUntrusted);
|
|
|
|
}
|
|
|
|
|
2009-06-15 08:27:29 +00:00
|
|
|
NS_IMETHODIMP
|
2011-09-29 06:19:26 +00:00
|
|
|
nsDOMEventTargetHelper::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
|
2009-06-15 08:27:29 +00:00
|
|
|
{
|
|
|
|
nsEventStatus status = nsEventStatus_eIgnore;
|
|
|
|
nsresult rv =
|
2012-07-30 14:20:58 +00:00
|
|
|
nsEventDispatcher::DispatchDOMEvent(this, nullptr, aEvent, nullptr, &status);
|
2009-06-15 08:27:29 +00:00
|
|
|
|
|
|
|
*aRetVal = (status != nsEventStatus_eConsumeNoDefault);
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMEventTargetHelper::RemoveAddEventListener(const nsAString& aType,
|
|
|
|
nsRefPtr<nsDOMEventListenerWrapper>& aCurrent,
|
|
|
|
nsIDOMEventListener* aNew)
|
|
|
|
{
|
|
|
|
if (aCurrent) {
|
2011-10-17 14:59:28 +00:00
|
|
|
RemoveEventListener(aType, aCurrent, false);
|
2012-07-30 14:20:58 +00:00
|
|
|
aCurrent = nullptr;
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
if (aNew) {
|
|
|
|
aCurrent = new nsDOMEventListenerWrapper(aNew);
|
|
|
|
NS_ENSURE_TRUE(aCurrent, NS_ERROR_OUT_OF_MEMORY);
|
2011-10-17 14:59:28 +00:00
|
|
|
nsIDOMEventTarget::AddEventListener(aType, aCurrent, false);
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMEventTargetHelper::GetInnerEventListener(nsRefPtr<nsDOMEventListenerWrapper>& aWrapper,
|
|
|
|
nsIDOMEventListener** aListener)
|
|
|
|
{
|
|
|
|
NS_ENSURE_ARG_POINTER(aListener);
|
|
|
|
if (aWrapper) {
|
2012-03-13 01:53:25 +00:00
|
|
|
NS_IF_ADDREF(*aListener = aWrapper->GetInner());
|
2009-06-15 08:27:29 +00:00
|
|
|
} else {
|
2012-07-30 14:20:58 +00:00
|
|
|
*aListener = nullptr;
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMEventTargetHelper::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
|
|
|
|
{
|
2011-10-17 14:59:28 +00:00
|
|
|
aVisitor.mCanHandle = true;
|
2012-07-30 14:20:58 +00:00
|
|
|
aVisitor.mParentTarget = nullptr;
|
2009-06-15 08:27:29 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMEventTargetHelper::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
|
|
|
|
{
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsDOMEventTargetHelper::DispatchDOMEvent(nsEvent* aEvent,
|
|
|
|
nsIDOMEvent* aDOMEvent,
|
|
|
|
nsPresContext* aPresContext,
|
|
|
|
nsEventStatus* aEventStatus)
|
|
|
|
{
|
|
|
|
return
|
2011-06-24 02:18:01 +00:00
|
|
|
nsEventDispatcher::DispatchDOMEvent(this, aEvent, aDOMEvent, aPresContext,
|
2009-06-15 08:27:29 +00:00
|
|
|
aEventStatus);
|
|
|
|
}
|
|
|
|
|
2011-06-24 02:18:01 +00:00
|
|
|
nsEventListenerManager*
|
2011-09-29 06:19:26 +00:00
|
|
|
nsDOMEventTargetHelper::GetListenerManager(bool aCreateIfNotFound)
|
2009-06-15 08:27:29 +00:00
|
|
|
{
|
2011-06-24 02:18:01 +00:00
|
|
|
if (!mListenerManager && aCreateIfNotFound) {
|
|
|
|
mListenerManager = new nsEventListenerManager(this);
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
|
2009-06-23 11:23:52 +00:00
|
|
|
return mListenerManager;
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsIScriptContext*
|
|
|
|
nsDOMEventTargetHelper::GetContextForEventHandlers(nsresult* aRv)
|
|
|
|
{
|
|
|
|
*aRv = CheckInnerWindowCorrectness();
|
|
|
|
if (NS_FAILED(*aRv)) {
|
2012-07-30 14:20:58 +00:00
|
|
|
return nullptr;
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
2012-03-13 00:56:07 +00:00
|
|
|
return mOwner ? static_cast<nsGlobalWindow*>(mOwner)->GetContextInternal()
|
2012-07-30 14:20:58 +00:00
|
|
|
: nullptr;
|
2009-06-15 08:27:29 +00:00
|
|
|
}
|
|
|
|
|
2012-02-08 02:53:33 +00:00
|
|
|
void
|
|
|
|
nsDOMEventTargetHelper::Init(JSContext* aCx)
|
|
|
|
{
|
|
|
|
JSContext* cx = aCx;
|
|
|
|
if (!cx) {
|
|
|
|
nsIJSContextStack* stack = nsContentUtils::ThreadJSContextStack();
|
|
|
|
|
|
|
|
if (!stack)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (NS_FAILED(stack->Peek(&cx)) || !cx)
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ASSERTION(cx, "Should have returned earlier ...");
|
|
|
|
nsIScriptContext* context = GetScriptContextFromJSContext(cx);
|
|
|
|
if (context) {
|
|
|
|
nsCOMPtr<nsPIDOMWindow> window =
|
|
|
|
do_QueryInterface(context->GetGlobalObject());
|
2012-03-13 00:56:07 +00:00
|
|
|
if (window) {
|
|
|
|
BindToOwner(window->GetCurrentInnerWindow());
|
|
|
|
}
|
2012-02-08 02:53:33 +00:00
|
|
|
}
|
|
|
|
}
|