1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/dom/events/EventListenerService.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,332 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +#include "EventListenerService.h" 1.10 +#ifdef MOZ_JSDEBUGGER 1.11 +#include "jsdIDebuggerService.h" 1.12 +#endif 1.13 +#include "mozilla/BasicEvents.h" 1.14 +#include "mozilla/EventDispatcher.h" 1.15 +#include "mozilla/EventListenerManager.h" 1.16 +#include "mozilla/JSEventHandler.h" 1.17 +#include "mozilla/Maybe.h" 1.18 +#include "nsCOMArray.h" 1.19 +#include "nsCxPusher.h" 1.20 +#include "nsDOMClassInfoID.h" 1.21 +#include "nsIXPConnect.h" 1.22 +#include "nsJSUtils.h" 1.23 +#include "nsMemory.h" 1.24 +#include "nsServiceManagerUtils.h" 1.25 + 1.26 +namespace mozilla { 1.27 + 1.28 +using namespace dom; 1.29 + 1.30 +/****************************************************************************** 1.31 + * mozilla::EventListenerInfo 1.32 + ******************************************************************************/ 1.33 + 1.34 +NS_IMPL_CYCLE_COLLECTION(EventListenerInfo, mListener) 1.35 + 1.36 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventListenerInfo) 1.37 + NS_INTERFACE_MAP_ENTRY(nsIEventListenerInfo) 1.38 + NS_INTERFACE_MAP_ENTRY(nsISupports) 1.39 +NS_INTERFACE_MAP_END 1.40 + 1.41 +NS_IMPL_CYCLE_COLLECTING_ADDREF(EventListenerInfo) 1.42 +NS_IMPL_CYCLE_COLLECTING_RELEASE(EventListenerInfo) 1.43 + 1.44 +NS_IMETHODIMP 1.45 +EventListenerInfo::GetType(nsAString& aType) 1.46 +{ 1.47 + aType = mType; 1.48 + return NS_OK; 1.49 +} 1.50 + 1.51 +NS_IMETHODIMP 1.52 +EventListenerInfo::GetCapturing(bool* aCapturing) 1.53 +{ 1.54 + *aCapturing = mCapturing; 1.55 + return NS_OK; 1.56 +} 1.57 + 1.58 +NS_IMETHODIMP 1.59 +EventListenerInfo::GetAllowsUntrusted(bool* aAllowsUntrusted) 1.60 +{ 1.61 + *aAllowsUntrusted = mAllowsUntrusted; 1.62 + return NS_OK; 1.63 +} 1.64 + 1.65 +NS_IMETHODIMP 1.66 +EventListenerInfo::GetInSystemEventGroup(bool* aInSystemEventGroup) 1.67 +{ 1.68 + *aInSystemEventGroup = mInSystemEventGroup; 1.69 + return NS_OK; 1.70 +} 1.71 + 1.72 +NS_IMETHODIMP 1.73 +EventListenerInfo::GetListenerObject(JSContext* aCx, 1.74 + JS::MutableHandle<JS::Value> aObject) 1.75 +{ 1.76 + Maybe<JSAutoCompartment> ac; 1.77 + GetJSVal(aCx, ac, aObject); 1.78 + return NS_OK; 1.79 +} 1.80 + 1.81 +/****************************************************************************** 1.82 + * mozilla::EventListenerService 1.83 + ******************************************************************************/ 1.84 + 1.85 +NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService) 1.86 + 1.87 +bool 1.88 +EventListenerInfo::GetJSVal(JSContext* aCx, 1.89 + Maybe<JSAutoCompartment>& aAc, 1.90 + JS::MutableHandle<JS::Value> aJSVal) 1.91 +{ 1.92 + aJSVal.setNull(); 1.93 + nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener); 1.94 + if (wrappedJS) { 1.95 + JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject()); 1.96 + if (!object) { 1.97 + return false; 1.98 + } 1.99 + aAc.construct(aCx, object); 1.100 + aJSVal.setObject(*object); 1.101 + return true; 1.102 + } 1.103 + 1.104 + nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener); 1.105 + if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) { 1.106 + JS::Handle<JSObject*> handler = 1.107 + jsHandler->GetTypedEventHandler().Ptr()->Callable(); 1.108 + if (handler) { 1.109 + aAc.construct(aCx, handler); 1.110 + aJSVal.setObject(*handler); 1.111 + return true; 1.112 + } 1.113 + } 1.114 + return false; 1.115 +} 1.116 + 1.117 +NS_IMETHODIMP 1.118 +EventListenerInfo::ToSource(nsAString& aResult) 1.119 +{ 1.120 + aResult.SetIsVoid(true); 1.121 + 1.122 + AutoSafeJSContext cx; 1.123 + Maybe<JSAutoCompartment> ac; 1.124 + JS::Rooted<JS::Value> v(cx); 1.125 + if (GetJSVal(cx, ac, &v)) { 1.126 + JSString* str = JS_ValueToSource(cx, v); 1.127 + if (str) { 1.128 + nsDependentJSString depStr; 1.129 + if (depStr.init(cx, str)) { 1.130 + aResult.Assign(depStr); 1.131 + } 1.132 + } 1.133 + } 1.134 + return NS_OK; 1.135 +} 1.136 + 1.137 +NS_IMETHODIMP 1.138 +EventListenerInfo::GetDebugObject(nsISupports** aRetVal) 1.139 +{ 1.140 + *aRetVal = nullptr; 1.141 + 1.142 +#ifdef MOZ_JSDEBUGGER 1.143 + nsresult rv = NS_OK; 1.144 + nsCOMPtr<jsdIDebuggerService> jsd = 1.145 + do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv); 1.146 + NS_ENSURE_SUCCESS(rv, NS_OK); 1.147 + 1.148 + bool isOn = false; 1.149 + jsd->GetIsOn(&isOn); 1.150 + NS_ENSURE_TRUE(isOn, NS_OK); 1.151 + 1.152 + AutoSafeJSContext cx; 1.153 + Maybe<JSAutoCompartment> ac; 1.154 + JS::Rooted<JS::Value> v(cx); 1.155 + if (GetJSVal(cx, ac, &v)) { 1.156 + nsCOMPtr<jsdIValue> jsdValue; 1.157 + rv = jsd->WrapValue(v, getter_AddRefs(jsdValue)); 1.158 + NS_ENSURE_SUCCESS(rv, rv); 1.159 + jsdValue.forget(aRetVal); 1.160 + } 1.161 +#endif 1.162 + 1.163 + return NS_OK; 1.164 +} 1.165 + 1.166 +NS_IMETHODIMP 1.167 +EventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget, 1.168 + uint32_t* aCount, 1.169 + nsIEventListenerInfo*** aOutArray) 1.170 +{ 1.171 + NS_ENSURE_ARG_POINTER(aEventTarget); 1.172 + *aCount = 0; 1.173 + *aOutArray = nullptr; 1.174 + nsCOMArray<nsIEventListenerInfo> listenerInfos; 1.175 + 1.176 + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget); 1.177 + NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE); 1.178 + 1.179 + EventListenerManager* elm = eventTarget->GetExistingListenerManager(); 1.180 + if (elm) { 1.181 + elm->GetListenerInfo(&listenerInfos); 1.182 + } 1.183 + 1.184 + int32_t count = listenerInfos.Count(); 1.185 + if (count == 0) { 1.186 + return NS_OK; 1.187 + } 1.188 + 1.189 + *aOutArray = 1.190 + static_cast<nsIEventListenerInfo**>( 1.191 + nsMemory::Alloc(sizeof(nsIEventListenerInfo*) * count)); 1.192 + NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY); 1.193 + 1.194 + for (int32_t i = 0; i < count; ++i) { 1.195 + NS_ADDREF((*aOutArray)[i] = listenerInfos[i]); 1.196 + } 1.197 + *aCount = count; 1.198 + return NS_OK; 1.199 +} 1.200 + 1.201 +NS_IMETHODIMP 1.202 +EventListenerService::GetEventTargetChainFor(nsIDOMEventTarget* aEventTarget, 1.203 + uint32_t* aCount, 1.204 + nsIDOMEventTarget*** aOutArray) 1.205 +{ 1.206 + *aCount = 0; 1.207 + *aOutArray = nullptr; 1.208 + NS_ENSURE_ARG(aEventTarget); 1.209 + WidgetEvent event(true, NS_EVENT_NULL); 1.210 + nsCOMArray<EventTarget> targets; 1.211 + nsresult rv = EventDispatcher::Dispatch(aEventTarget, nullptr, &event, 1.212 + nullptr, nullptr, nullptr, &targets); 1.213 + NS_ENSURE_SUCCESS(rv, rv); 1.214 + int32_t count = targets.Count(); 1.215 + if (count == 0) { 1.216 + return NS_OK; 1.217 + } 1.218 + 1.219 + *aOutArray = 1.220 + static_cast<nsIDOMEventTarget**>( 1.221 + nsMemory::Alloc(sizeof(nsIDOMEventTarget*) * count)); 1.222 + NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY); 1.223 + 1.224 + for (int32_t i = 0; i < count; ++i) { 1.225 + NS_ADDREF((*aOutArray)[i] = targets[i]); 1.226 + } 1.227 + *aCount = count; 1.228 + 1.229 + return NS_OK; 1.230 +} 1.231 + 1.232 +NS_IMETHODIMP 1.233 +EventListenerService::HasListenersFor(nsIDOMEventTarget* aEventTarget, 1.234 + const nsAString& aType, 1.235 + bool* aRetVal) 1.236 +{ 1.237 + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget); 1.238 + NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE); 1.239 + 1.240 + EventListenerManager* elm = eventTarget->GetExistingListenerManager(); 1.241 + *aRetVal = elm && elm->HasListenersFor(aType); 1.242 + return NS_OK; 1.243 +} 1.244 + 1.245 +NS_IMETHODIMP 1.246 +EventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget, 1.247 + const nsAString& aType, 1.248 + nsIDOMEventListener* aListener, 1.249 + bool aUseCapture) 1.250 +{ 1.251 + NS_PRECONDITION(aTarget, "Missing target"); 1.252 + NS_PRECONDITION(aListener, "Missing listener"); 1.253 + 1.254 + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget); 1.255 + NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE); 1.256 + 1.257 + EventListenerManager* manager = eventTarget->GetOrCreateListenerManager(); 1.258 + NS_ENSURE_STATE(manager); 1.259 + 1.260 + EventListenerFlags flags = 1.261 + aUseCapture ? TrustedEventsAtSystemGroupCapture() : 1.262 + TrustedEventsAtSystemGroupBubble(); 1.263 + manager->AddEventListenerByType(aListener, aType, flags); 1.264 + return NS_OK; 1.265 +} 1.266 + 1.267 +NS_IMETHODIMP 1.268 +EventListenerService::RemoveSystemEventListener(nsIDOMEventTarget *aTarget, 1.269 + const nsAString& aType, 1.270 + nsIDOMEventListener* aListener, 1.271 + bool aUseCapture) 1.272 +{ 1.273 + NS_PRECONDITION(aTarget, "Missing target"); 1.274 + NS_PRECONDITION(aListener, "Missing listener"); 1.275 + 1.276 + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget); 1.277 + NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE); 1.278 + 1.279 + EventListenerManager* manager = eventTarget->GetExistingListenerManager(); 1.280 + if (manager) { 1.281 + EventListenerFlags flags = 1.282 + aUseCapture ? TrustedEventsAtSystemGroupCapture() : 1.283 + TrustedEventsAtSystemGroupBubble(); 1.284 + manager->RemoveEventListenerByType(aListener, aType, flags); 1.285 + } 1.286 + 1.287 + return NS_OK; 1.288 +} 1.289 + 1.290 +NS_IMETHODIMP 1.291 +EventListenerService::AddListenerForAllEvents(nsIDOMEventTarget* aTarget, 1.292 + nsIDOMEventListener* aListener, 1.293 + bool aUseCapture, 1.294 + bool aWantsUntrusted, 1.295 + bool aSystemEventGroup) 1.296 +{ 1.297 + NS_ENSURE_STATE(aTarget && aListener); 1.298 + 1.299 + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget); 1.300 + NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE); 1.301 + 1.302 + EventListenerManager* manager = eventTarget->GetOrCreateListenerManager(); 1.303 + NS_ENSURE_STATE(manager); 1.304 + manager->AddListenerForAllEvents(aListener, aUseCapture, aWantsUntrusted, 1.305 + aSystemEventGroup); 1.306 + return NS_OK; 1.307 +} 1.308 + 1.309 +NS_IMETHODIMP 1.310 +EventListenerService::RemoveListenerForAllEvents(nsIDOMEventTarget* aTarget, 1.311 + nsIDOMEventListener* aListener, 1.312 + bool aUseCapture, 1.313 + bool aSystemEventGroup) 1.314 +{ 1.315 + NS_ENSURE_STATE(aTarget && aListener); 1.316 + 1.317 + nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget); 1.318 + NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE); 1.319 + 1.320 + EventListenerManager* manager = eventTarget->GetExistingListenerManager(); 1.321 + if (manager) { 1.322 + manager->RemoveListenerForAllEvents(aListener, aUseCapture, aSystemEventGroup); 1.323 + } 1.324 + return NS_OK; 1.325 +} 1.326 + 1.327 +} // namespace mozilla 1.328 + 1.329 +nsresult 1.330 +NS_NewEventListenerService(nsIEventListenerService** aResult) 1.331 +{ 1.332 + *aResult = new mozilla::EventListenerService(); 1.333 + NS_ADDREF(*aResult); 1.334 + return NS_OK; 1.335 +}