author | Boris Zbarsky <bzbarsky@mit.edu> |
Thu, 12 Apr 2018 00:05:38 -0400 | |
changeset 412925 | a5d3181f3b27516389832323e67b600c91999839 |
parent 412924 | 1c2716f85b46caf57f1a096d729508d4b289c15e |
child 412926 | 2a9b18f3f4ace72abfcb323612eb7cf9bd147076 |
push id | 33824 |
push user | ebalazs@mozilla.com |
push date | Thu, 12 Apr 2018 09:39:57 +0000 |
treeherder | mozilla-central@246c614e1605 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | smaug |
bugs | 1453487 |
milestone | 61.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/components/sessionstore/content/content-sessionStore.js +++ b/browser/components/sessionstore/content/content-sessionStore.js @@ -46,16 +46,19 @@ const DOM_STORAGE_LIMIT_PREF = "browser. // or not, and should only be used for tests or debugging. const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates"; const PREF_INTERVAL = "browser.sessionstore.interval"; const kNoIndex = Number.MAX_SAFE_INTEGER; const kLastIndex = Number.MAX_SAFE_INTEGER - 1; +// Grab our global so we can access it in functions below. +const global = this; + /** * A function that will recursively call |cb| to collected data for all * non-dynamic frames in the current frame/docShell tree. */ function mapFrameTree(callback) { return (function map(frame, cb) { // Collect data for the current frame. let obj = cb(frame) || {}; @@ -145,17 +148,17 @@ var StateChangeNotifier = { /** * Listens for and handles content events that we need for the * session store service to be notified of state changes in content. */ var EventListener = { init() { - addEventListener("load", ssu.createDynamicFrameEventFilter(this), true); + ssu.addDynamicFrameFilteredListener(global, "load", this, true); }, handleEvent(event) { // Ignore load events from subframes. if (event.target != content.document) { return; } @@ -459,17 +462,17 @@ var SessionHistoryListener = { * is scrolled this will return null so that we don't tack a property onto * the tabData object in the parent process. * * Example: * {scroll: "100,100", children: [null, null, {scroll: "200,200"}]} */ var ScrollPositionListener = { init() { - addEventListener("scroll", ssu.createDynamicFrameEventFilter(this)); + ssu.addDynamicFrameFilteredListener(global, "scroll", this, false); StateChangeNotifier.addObserver(this); }, handleEvent() { MessageQueue.push("scroll", () => this.collect()); }, onPageLoadCompleted() { @@ -499,17 +502,17 @@ var ScrollPositionListener = { * children: [ * null, * {url: "http://sub.mozilla.org/", id: {input_id: "input value 2"}} * ] * } */ var FormDataListener = { init() { - addEventListener("input", ssu.createDynamicFrameEventFilter(this), true); + ssu.addDynamicFrameFilteredListener(global, "input", this, true); StateChangeNotifier.addObserver(this); }, handleEvent() { MessageQueue.push("formdata", () => this.collect()); }, onPageLoadStarted() { @@ -591,23 +594,25 @@ var SessionStorageListener = { this._changes = undefined; }, // The event listener waiting for MozSessionStorageChanged events. _listener: null, resetEventListener() { if (!this._listener) { - this._listener = ssu.createDynamicFrameEventFilter(this); - addEventListener("MozSessionStorageChanged", this._listener, true); + this._listener = + ssu.addDynamicFrameFilteredListener(global, "MozSessionStorageChanged", + this, true); } }, removeEventListener() { - removeEventListener("MozSessionStorageChanged", this._listener, true); + ssu.removeDynamicFrameFilteredListener(global, "MozSessionStorageChanged", + this._listener, true); this._listener = null; }, handleEvent(event) { if (!docShell) { return; }
--- a/browser/components/sessionstore/nsISessionStoreUtils.idl +++ b/browser/components/sessionstore/nsISessionStoreUtils.idl @@ -1,16 +1,16 @@ /* 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/. */ #include "nsISupports.idl" interface mozIDOMWindowProxy; -interface nsIDOMEventListener; +interface nsIDOMEventTarget; /** * A callback passed to nsISessionStoreUtils.forEachNonDynamicChildFrame(). */ [function, scriptable, uuid(8199ebf7-76c0-43d6-bcbe-913dd3de3ebf)] interface nsISessionStoreUtilsFrameCallback : nsISupports { /** @@ -30,18 +30,40 @@ interface nsISessionStoreUtils : nsISupp /** * Calls the given |callback| once for each non-dynamic child frame of the * given |window|. */ void forEachNonDynamicChildFrame(in mozIDOMWindowProxy window, in nsISessionStoreUtilsFrameCallback callback); /** - * Creates and returns an event listener that filters events from dynamic - * docShells. It forwards those from non-dynamic docShells to the given - * |listener|. + * Takes the given listener, wraps it in a filter that filters out events from + * dynamic docShells, and adds that filter as a listener for the given event + * type on the given event target. The listener that was added is returned + * (as nsISupports) so that it can later be removed via + * removeDynamicFrameFilteredListener. * * This is implemented as a native filter, rather than a JS-based one, for * performance reasons. + * + * Once bug 1444991 is fixed, this should start taking an EventTarget. */ [implicit_jscontext] - nsIDOMEventListener createDynamicFrameEventFilter(in jsval listener); + nsISupports addDynamicFrameFilteredListener(in nsIDOMEventTarget target, + in AString type, + in jsval listener, + in boolean useCapture); + + /** + * Remove the passed-in filtered listener from the given event target, if it's + * currently a listener for the given event type there. The 'listener' + * argument must be something that was returned by + * addDynamicFrameFilteredListener. + * + * This is needed, instead of the normal removeEventListener, because the + * caller doesn't actually have something that WebIDL considers an + * EventListener. + */ + void removeDynamicFrameFilteredListener(in nsIDOMEventTarget target, + in AString type, + in nsISupports listener, + in boolean useCapture); };
--- a/browser/components/sessionstore/nsSessionStoreUtils.cpp +++ b/browser/components/sessionstore/nsSessionStoreUtils.cpp @@ -1,16 +1,17 @@ /* 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/. */ #include "nsSessionStoreUtils.h" #include "mozilla/dom/Event.h" #include "mozilla/dom/EventListenerBinding.h" +#include "mozilla/dom/EventTarget.h" #include "mozilla/dom/ScriptSettings.h" #include "nsPIDOMWindow.h" #include "nsIDocShell.h" using namespace mozilla::dom; namespace { @@ -111,25 +112,50 @@ nsSessionStoreUtils::ForEachNonDynamicCh aCallback->HandleFrame(item->GetWindow(), childOffset); } return NS_OK; } NS_IMETHODIMP -nsSessionStoreUtils::CreateDynamicFrameEventFilter(JS::Handle<JS::Value> aListener, - JSContext* aCx, - nsIDOMEventListener** aResult) +nsSessionStoreUtils::AddDynamicFrameFilteredListener(nsIDOMEventTarget* aTarget, + const nsAString& aType, + JS::Handle<JS::Value> aListener, + bool aUseCapture, + JSContext* aCx, + nsISupports** aResult) { if (NS_WARN_IF(!aListener.isObject())) { return NS_ERROR_INVALID_ARG; } + nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget); + NS_ENSURE_TRUE(target, NS_ERROR_NO_INTERFACE); + JS::Rooted<JSObject*> obj(aCx, &aListener.toObject()); RefPtr<EventListener> listener = new EventListener(aCx, obj, GetIncumbentGlobal()); nsCOMPtr<nsIDOMEventListener> filter(new DynamicFrameEventFilter(listener)); + + nsresult rv = target->AddEventListener(aType, filter, aUseCapture); + NS_ENSURE_SUCCESS(rv, rv); + filter.forget(aResult); - return NS_OK; } + +NS_IMETHODIMP +nsSessionStoreUtils::RemoveDynamicFrameFilteredListener(nsIDOMEventTarget* aTarget, + const nsAString& aType, + nsISupports* aListener, + bool aUseCapture) +{ + nsCOMPtr<EventTarget> target = do_QueryInterface(aTarget); + NS_ENSURE_TRUE(target, NS_ERROR_NO_INTERFACE); + + nsCOMPtr<nsIDOMEventListener> listener = do_QueryInterface(aListener); + NS_ENSURE_TRUE(listener, NS_ERROR_NO_INTERFACE); + + target->RemoveEventListener(aType, listener, aUseCapture); + return NS_OK; +}