dom/events/EventListenerService.cpp

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 3 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 5
michael@0 6 #include "EventListenerService.h"
michael@0 7 #ifdef MOZ_JSDEBUGGER
michael@0 8 #include "jsdIDebuggerService.h"
michael@0 9 #endif
michael@0 10 #include "mozilla/BasicEvents.h"
michael@0 11 #include "mozilla/EventDispatcher.h"
michael@0 12 #include "mozilla/EventListenerManager.h"
michael@0 13 #include "mozilla/JSEventHandler.h"
michael@0 14 #include "mozilla/Maybe.h"
michael@0 15 #include "nsCOMArray.h"
michael@0 16 #include "nsCxPusher.h"
michael@0 17 #include "nsDOMClassInfoID.h"
michael@0 18 #include "nsIXPConnect.h"
michael@0 19 #include "nsJSUtils.h"
michael@0 20 #include "nsMemory.h"
michael@0 21 #include "nsServiceManagerUtils.h"
michael@0 22
michael@0 23 namespace mozilla {
michael@0 24
michael@0 25 using namespace dom;
michael@0 26
michael@0 27 /******************************************************************************
michael@0 28 * mozilla::EventListenerInfo
michael@0 29 ******************************************************************************/
michael@0 30
michael@0 31 NS_IMPL_CYCLE_COLLECTION(EventListenerInfo, mListener)
michael@0 32
michael@0 33 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(EventListenerInfo)
michael@0 34 NS_INTERFACE_MAP_ENTRY(nsIEventListenerInfo)
michael@0 35 NS_INTERFACE_MAP_ENTRY(nsISupports)
michael@0 36 NS_INTERFACE_MAP_END
michael@0 37
michael@0 38 NS_IMPL_CYCLE_COLLECTING_ADDREF(EventListenerInfo)
michael@0 39 NS_IMPL_CYCLE_COLLECTING_RELEASE(EventListenerInfo)
michael@0 40
michael@0 41 NS_IMETHODIMP
michael@0 42 EventListenerInfo::GetType(nsAString& aType)
michael@0 43 {
michael@0 44 aType = mType;
michael@0 45 return NS_OK;
michael@0 46 }
michael@0 47
michael@0 48 NS_IMETHODIMP
michael@0 49 EventListenerInfo::GetCapturing(bool* aCapturing)
michael@0 50 {
michael@0 51 *aCapturing = mCapturing;
michael@0 52 return NS_OK;
michael@0 53 }
michael@0 54
michael@0 55 NS_IMETHODIMP
michael@0 56 EventListenerInfo::GetAllowsUntrusted(bool* aAllowsUntrusted)
michael@0 57 {
michael@0 58 *aAllowsUntrusted = mAllowsUntrusted;
michael@0 59 return NS_OK;
michael@0 60 }
michael@0 61
michael@0 62 NS_IMETHODIMP
michael@0 63 EventListenerInfo::GetInSystemEventGroup(bool* aInSystemEventGroup)
michael@0 64 {
michael@0 65 *aInSystemEventGroup = mInSystemEventGroup;
michael@0 66 return NS_OK;
michael@0 67 }
michael@0 68
michael@0 69 NS_IMETHODIMP
michael@0 70 EventListenerInfo::GetListenerObject(JSContext* aCx,
michael@0 71 JS::MutableHandle<JS::Value> aObject)
michael@0 72 {
michael@0 73 Maybe<JSAutoCompartment> ac;
michael@0 74 GetJSVal(aCx, ac, aObject);
michael@0 75 return NS_OK;
michael@0 76 }
michael@0 77
michael@0 78 /******************************************************************************
michael@0 79 * mozilla::EventListenerService
michael@0 80 ******************************************************************************/
michael@0 81
michael@0 82 NS_IMPL_ISUPPORTS(EventListenerService, nsIEventListenerService)
michael@0 83
michael@0 84 bool
michael@0 85 EventListenerInfo::GetJSVal(JSContext* aCx,
michael@0 86 Maybe<JSAutoCompartment>& aAc,
michael@0 87 JS::MutableHandle<JS::Value> aJSVal)
michael@0 88 {
michael@0 89 aJSVal.setNull();
michael@0 90 nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(mListener);
michael@0 91 if (wrappedJS) {
michael@0 92 JS::Rooted<JSObject*> object(aCx, wrappedJS->GetJSObject());
michael@0 93 if (!object) {
michael@0 94 return false;
michael@0 95 }
michael@0 96 aAc.construct(aCx, object);
michael@0 97 aJSVal.setObject(*object);
michael@0 98 return true;
michael@0 99 }
michael@0 100
michael@0 101 nsCOMPtr<JSEventHandler> jsHandler = do_QueryInterface(mListener);
michael@0 102 if (jsHandler && jsHandler->GetTypedEventHandler().HasEventHandler()) {
michael@0 103 JS::Handle<JSObject*> handler =
michael@0 104 jsHandler->GetTypedEventHandler().Ptr()->Callable();
michael@0 105 if (handler) {
michael@0 106 aAc.construct(aCx, handler);
michael@0 107 aJSVal.setObject(*handler);
michael@0 108 return true;
michael@0 109 }
michael@0 110 }
michael@0 111 return false;
michael@0 112 }
michael@0 113
michael@0 114 NS_IMETHODIMP
michael@0 115 EventListenerInfo::ToSource(nsAString& aResult)
michael@0 116 {
michael@0 117 aResult.SetIsVoid(true);
michael@0 118
michael@0 119 AutoSafeJSContext cx;
michael@0 120 Maybe<JSAutoCompartment> ac;
michael@0 121 JS::Rooted<JS::Value> v(cx);
michael@0 122 if (GetJSVal(cx, ac, &v)) {
michael@0 123 JSString* str = JS_ValueToSource(cx, v);
michael@0 124 if (str) {
michael@0 125 nsDependentJSString depStr;
michael@0 126 if (depStr.init(cx, str)) {
michael@0 127 aResult.Assign(depStr);
michael@0 128 }
michael@0 129 }
michael@0 130 }
michael@0 131 return NS_OK;
michael@0 132 }
michael@0 133
michael@0 134 NS_IMETHODIMP
michael@0 135 EventListenerInfo::GetDebugObject(nsISupports** aRetVal)
michael@0 136 {
michael@0 137 *aRetVal = nullptr;
michael@0 138
michael@0 139 #ifdef MOZ_JSDEBUGGER
michael@0 140 nsresult rv = NS_OK;
michael@0 141 nsCOMPtr<jsdIDebuggerService> jsd =
michael@0 142 do_GetService("@mozilla.org/js/jsd/debugger-service;1", &rv);
michael@0 143 NS_ENSURE_SUCCESS(rv, NS_OK);
michael@0 144
michael@0 145 bool isOn = false;
michael@0 146 jsd->GetIsOn(&isOn);
michael@0 147 NS_ENSURE_TRUE(isOn, NS_OK);
michael@0 148
michael@0 149 AutoSafeJSContext cx;
michael@0 150 Maybe<JSAutoCompartment> ac;
michael@0 151 JS::Rooted<JS::Value> v(cx);
michael@0 152 if (GetJSVal(cx, ac, &v)) {
michael@0 153 nsCOMPtr<jsdIValue> jsdValue;
michael@0 154 rv = jsd->WrapValue(v, getter_AddRefs(jsdValue));
michael@0 155 NS_ENSURE_SUCCESS(rv, rv);
michael@0 156 jsdValue.forget(aRetVal);
michael@0 157 }
michael@0 158 #endif
michael@0 159
michael@0 160 return NS_OK;
michael@0 161 }
michael@0 162
michael@0 163 NS_IMETHODIMP
michael@0 164 EventListenerService::GetListenerInfoFor(nsIDOMEventTarget* aEventTarget,
michael@0 165 uint32_t* aCount,
michael@0 166 nsIEventListenerInfo*** aOutArray)
michael@0 167 {
michael@0 168 NS_ENSURE_ARG_POINTER(aEventTarget);
michael@0 169 *aCount = 0;
michael@0 170 *aOutArray = nullptr;
michael@0 171 nsCOMArray<nsIEventListenerInfo> listenerInfos;
michael@0 172
michael@0 173 nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
michael@0 174 NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
michael@0 175
michael@0 176 EventListenerManager* elm = eventTarget->GetExistingListenerManager();
michael@0 177 if (elm) {
michael@0 178 elm->GetListenerInfo(&listenerInfos);
michael@0 179 }
michael@0 180
michael@0 181 int32_t count = listenerInfos.Count();
michael@0 182 if (count == 0) {
michael@0 183 return NS_OK;
michael@0 184 }
michael@0 185
michael@0 186 *aOutArray =
michael@0 187 static_cast<nsIEventListenerInfo**>(
michael@0 188 nsMemory::Alloc(sizeof(nsIEventListenerInfo*) * count));
michael@0 189 NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY);
michael@0 190
michael@0 191 for (int32_t i = 0; i < count; ++i) {
michael@0 192 NS_ADDREF((*aOutArray)[i] = listenerInfos[i]);
michael@0 193 }
michael@0 194 *aCount = count;
michael@0 195 return NS_OK;
michael@0 196 }
michael@0 197
michael@0 198 NS_IMETHODIMP
michael@0 199 EventListenerService::GetEventTargetChainFor(nsIDOMEventTarget* aEventTarget,
michael@0 200 uint32_t* aCount,
michael@0 201 nsIDOMEventTarget*** aOutArray)
michael@0 202 {
michael@0 203 *aCount = 0;
michael@0 204 *aOutArray = nullptr;
michael@0 205 NS_ENSURE_ARG(aEventTarget);
michael@0 206 WidgetEvent event(true, NS_EVENT_NULL);
michael@0 207 nsCOMArray<EventTarget> targets;
michael@0 208 nsresult rv = EventDispatcher::Dispatch(aEventTarget, nullptr, &event,
michael@0 209 nullptr, nullptr, nullptr, &targets);
michael@0 210 NS_ENSURE_SUCCESS(rv, rv);
michael@0 211 int32_t count = targets.Count();
michael@0 212 if (count == 0) {
michael@0 213 return NS_OK;
michael@0 214 }
michael@0 215
michael@0 216 *aOutArray =
michael@0 217 static_cast<nsIDOMEventTarget**>(
michael@0 218 nsMemory::Alloc(sizeof(nsIDOMEventTarget*) * count));
michael@0 219 NS_ENSURE_TRUE(*aOutArray, NS_ERROR_OUT_OF_MEMORY);
michael@0 220
michael@0 221 for (int32_t i = 0; i < count; ++i) {
michael@0 222 NS_ADDREF((*aOutArray)[i] = targets[i]);
michael@0 223 }
michael@0 224 *aCount = count;
michael@0 225
michael@0 226 return NS_OK;
michael@0 227 }
michael@0 228
michael@0 229 NS_IMETHODIMP
michael@0 230 EventListenerService::HasListenersFor(nsIDOMEventTarget* aEventTarget,
michael@0 231 const nsAString& aType,
michael@0 232 bool* aRetVal)
michael@0 233 {
michael@0 234 nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aEventTarget);
michael@0 235 NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
michael@0 236
michael@0 237 EventListenerManager* elm = eventTarget->GetExistingListenerManager();
michael@0 238 *aRetVal = elm && elm->HasListenersFor(aType);
michael@0 239 return NS_OK;
michael@0 240 }
michael@0 241
michael@0 242 NS_IMETHODIMP
michael@0 243 EventListenerService::AddSystemEventListener(nsIDOMEventTarget *aTarget,
michael@0 244 const nsAString& aType,
michael@0 245 nsIDOMEventListener* aListener,
michael@0 246 bool aUseCapture)
michael@0 247 {
michael@0 248 NS_PRECONDITION(aTarget, "Missing target");
michael@0 249 NS_PRECONDITION(aListener, "Missing listener");
michael@0 250
michael@0 251 nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
michael@0 252 NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
michael@0 253
michael@0 254 EventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
michael@0 255 NS_ENSURE_STATE(manager);
michael@0 256
michael@0 257 EventListenerFlags flags =
michael@0 258 aUseCapture ? TrustedEventsAtSystemGroupCapture() :
michael@0 259 TrustedEventsAtSystemGroupBubble();
michael@0 260 manager->AddEventListenerByType(aListener, aType, flags);
michael@0 261 return NS_OK;
michael@0 262 }
michael@0 263
michael@0 264 NS_IMETHODIMP
michael@0 265 EventListenerService::RemoveSystemEventListener(nsIDOMEventTarget *aTarget,
michael@0 266 const nsAString& aType,
michael@0 267 nsIDOMEventListener* aListener,
michael@0 268 bool aUseCapture)
michael@0 269 {
michael@0 270 NS_PRECONDITION(aTarget, "Missing target");
michael@0 271 NS_PRECONDITION(aListener, "Missing listener");
michael@0 272
michael@0 273 nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
michael@0 274 NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
michael@0 275
michael@0 276 EventListenerManager* manager = eventTarget->GetExistingListenerManager();
michael@0 277 if (manager) {
michael@0 278 EventListenerFlags flags =
michael@0 279 aUseCapture ? TrustedEventsAtSystemGroupCapture() :
michael@0 280 TrustedEventsAtSystemGroupBubble();
michael@0 281 manager->RemoveEventListenerByType(aListener, aType, flags);
michael@0 282 }
michael@0 283
michael@0 284 return NS_OK;
michael@0 285 }
michael@0 286
michael@0 287 NS_IMETHODIMP
michael@0 288 EventListenerService::AddListenerForAllEvents(nsIDOMEventTarget* aTarget,
michael@0 289 nsIDOMEventListener* aListener,
michael@0 290 bool aUseCapture,
michael@0 291 bool aWantsUntrusted,
michael@0 292 bool aSystemEventGroup)
michael@0 293 {
michael@0 294 NS_ENSURE_STATE(aTarget && aListener);
michael@0 295
michael@0 296 nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
michael@0 297 NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
michael@0 298
michael@0 299 EventListenerManager* manager = eventTarget->GetOrCreateListenerManager();
michael@0 300 NS_ENSURE_STATE(manager);
michael@0 301 manager->AddListenerForAllEvents(aListener, aUseCapture, aWantsUntrusted,
michael@0 302 aSystemEventGroup);
michael@0 303 return NS_OK;
michael@0 304 }
michael@0 305
michael@0 306 NS_IMETHODIMP
michael@0 307 EventListenerService::RemoveListenerForAllEvents(nsIDOMEventTarget* aTarget,
michael@0 308 nsIDOMEventListener* aListener,
michael@0 309 bool aUseCapture,
michael@0 310 bool aSystemEventGroup)
michael@0 311 {
michael@0 312 NS_ENSURE_STATE(aTarget && aListener);
michael@0 313
michael@0 314 nsCOMPtr<EventTarget> eventTarget = do_QueryInterface(aTarget);
michael@0 315 NS_ENSURE_TRUE(eventTarget, NS_ERROR_NO_INTERFACE);
michael@0 316
michael@0 317 EventListenerManager* manager = eventTarget->GetExistingListenerManager();
michael@0 318 if (manager) {
michael@0 319 manager->RemoveListenerForAllEvents(aListener, aUseCapture, aSystemEventGroup);
michael@0 320 }
michael@0 321 return NS_OK;
michael@0 322 }
michael@0 323
michael@0 324 } // namespace mozilla
michael@0 325
michael@0 326 nsresult
michael@0 327 NS_NewEventListenerService(nsIEventListenerService** aResult)
michael@0 328 {
michael@0 329 *aResult = new mozilla::EventListenerService();
michael@0 330 NS_ADDREF(*aResult);
michael@0 331 return NS_OK;
michael@0 332 }

mercurial