mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1196975 - part2: shimwaiver applications. r=mossop
This commit is contained in:
parent
01939af4fe
commit
60e444f48f
@ -282,6 +282,7 @@ EXTRA_JS_MODULES.commonjs.sdk.deprecated.events += [
|
||||
]
|
||||
|
||||
EXTRA_JS_MODULES.commonjs.sdk.dom += [
|
||||
'source/lib/sdk/dom/events-shimmed.js',
|
||||
'source/lib/sdk/dom/events.js',
|
||||
]
|
||||
|
||||
@ -408,6 +409,7 @@ EXTRA_JS_MODULES.commonjs.sdk.stylesheet += [
|
||||
EXTRA_JS_MODULES.commonjs.sdk.system += [
|
||||
'source/lib/sdk/system/child_process.js',
|
||||
'source/lib/sdk/system/environment.js',
|
||||
'source/lib/sdk/system/events-shimmed.js',
|
||||
'source/lib/sdk/system/events.js',
|
||||
'source/lib/sdk/system/globals.js',
|
||||
'source/lib/sdk/system/process.js',
|
||||
|
@ -9,14 +9,17 @@ module.metadata = {
|
||||
};
|
||||
|
||||
|
||||
const { Cc, Ci, Cr } = require("chrome");
|
||||
const { Cc, Ci, Cr, Cu } = require("chrome");
|
||||
const { Class } = require("./heritage");
|
||||
const { isWeak } = require("./reference");
|
||||
const method = require("../../method/core");
|
||||
|
||||
const { addObserver, removeObserver } = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
const observerService = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
|
||||
const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
|
||||
|
||||
// This is a method that will be invoked when notification observer
|
||||
// subscribed to occurs.
|
||||
|
18
addon-sdk/source/lib/sdk/dom/events-shimmed.js
Normal file
18
addon-sdk/source/lib/sdk/dom/events-shimmed.js
Normal file
@ -0,0 +1,18 @@
|
||||
/* 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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.metadata = {
|
||||
'stability': 'unstable'
|
||||
};
|
||||
|
||||
const events = require('./events.js');
|
||||
|
||||
exports.emit = (element, type, obj) => events.emit(element, type, obj, true);
|
||||
exports.on = (element, type, listener, capture) => events.on(element, type, listener, capture, true);
|
||||
exports.once = (element, type, listener, capture) => events.once(element, type, listener, capture, true);
|
||||
exports.removeListener = (element, type, listener, capture) => events.removeListener(element, type, listener, capture, true);
|
||||
exports.removed = events.removed;
|
||||
exports.when = (element, eventName, capture) => events.when(element, eventName, capture ? capture : false, true);
|
@ -8,6 +8,9 @@ module.metadata = {
|
||||
"stability": "unstable"
|
||||
};
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
|
||||
// Utility function that returns copy of the given `text` with last character
|
||||
// removed if it is `"s"`.
|
||||
function singularify(text) {
|
||||
@ -44,10 +47,14 @@ function getInitializerName(category) {
|
||||
* See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
|
||||
* for a detailed explanation.
|
||||
*/
|
||||
function on(element, type, listener, capture) {
|
||||
function on(element, type, listener, capture, shimmed = false) {
|
||||
// `capture` defaults to `false`.
|
||||
capture = capture || false;
|
||||
element.addEventListener(type, listener, capture);
|
||||
if (shimmed) {
|
||||
element.addEventListener(type, listener, capture);
|
||||
} else {
|
||||
ShimWaiver.getProperty(element, "addEventListener")(type, listener, capture);
|
||||
}
|
||||
}
|
||||
exports.on = on;
|
||||
|
||||
@ -73,11 +80,11 @@ exports.on = on;
|
||||
* See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
|
||||
* for a detailed explanation.
|
||||
*/
|
||||
function once(element, type, listener, capture) {
|
||||
function once(element, type, listener, capture, shimmed = false) {
|
||||
on(element, type, function selfRemovableListener(event) {
|
||||
removeListener(element, type, selfRemovableListener, capture);
|
||||
removeListener(element, type, selfRemovableListener, capture, shimmed);
|
||||
listener.apply(this, arguments);
|
||||
}, capture);
|
||||
}, capture, shimmed);
|
||||
}
|
||||
exports.once = once;
|
||||
|
||||
@ -103,8 +110,12 @@ exports.once = once;
|
||||
* See [DOM Level 3 Events](http://www.w3.org/TR/DOM-Level-3-Events/#event-flow)
|
||||
* for a detailed explanation.
|
||||
*/
|
||||
function removeListener(element, type, listener, capture) {
|
||||
element.removeEventListener(type, listener, capture);
|
||||
function removeListener(element, type, listener, capture, shimmed = false) {
|
||||
if (shimmed) {
|
||||
element.removeEventListener(type, listener, capture);
|
||||
} else {
|
||||
ShimWaiver.getProperty(element, "removeEventListener")(type, listener, capture);
|
||||
}
|
||||
}
|
||||
exports.removeListener = removeListener;
|
||||
|
||||
@ -128,13 +139,17 @@ exports.removeListener = removeListener;
|
||||
* initializer after firs `type` argument.
|
||||
* @see https://developer.mozilla.org/En/DOM/Document.createEvent
|
||||
*/
|
||||
function emit(element, type, { category, initializer, settings }) {
|
||||
function emit(element, type, { category, initializer, settings }, shimmed = false) {
|
||||
category = category || "UIEvents";
|
||||
initializer = initializer || getInitializerName(category);
|
||||
let document = element.ownerDocument;
|
||||
let event = document.createEvent(category);
|
||||
event[initializer].apply(event, [type].concat(settings));
|
||||
element.dispatchEvent(event);
|
||||
if (shimmed) {
|
||||
element.dispatchEvent(event);
|
||||
} else {
|
||||
ShimWaiver.getProperty(element, "dispatchEvent")(event);
|
||||
}
|
||||
};
|
||||
exports.emit = emit;
|
||||
|
||||
@ -158,12 +173,20 @@ const removed = element => {
|
||||
};
|
||||
exports.removed = removed;
|
||||
|
||||
const when = (element, eventName, capture=false) => new Promise(resolve => {
|
||||
const when = (element, eventName, capture=false, shimmed=false) => new Promise(resolve => {
|
||||
const listener = event => {
|
||||
element.removeEventListener(eventName, listener, capture);
|
||||
if (shimmed) {
|
||||
element.removeEventListener(eventName, listener, capture);
|
||||
} else {
|
||||
ShimWaiver.getProperty(element, "removeEventListener")(eventName, listener, capture);
|
||||
}
|
||||
resolve(event);
|
||||
};
|
||||
|
||||
element.addEventListener(eventName, listener, capture);
|
||||
if (shimmed) {
|
||||
element.addEventListener(eventName, listener, capture);
|
||||
} else {
|
||||
ShimWaiver.getProperty(element, "addEventListener")(eventName, listener, capture);
|
||||
}
|
||||
});
|
||||
exports.when = when;
|
||||
|
@ -8,10 +8,15 @@ module.metadata = {
|
||||
"stability": "unstable"
|
||||
};
|
||||
|
||||
const { Cc, Ci, Cr } = require("chrome");
|
||||
const { Cc, Ci, Cr, Cu } = require("chrome");
|
||||
const { emit, on, off } = require("./core");
|
||||
const { addObserver, removeObserver } = Cc["@mozilla.org/observer-service;1"].
|
||||
getService(Ci.nsIObserverService);
|
||||
var observerService = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
|
||||
const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
|
||||
|
||||
const { when: unload } = require("../system/unload");
|
||||
|
||||
// Simple class that can be used to instantiate event channel that
|
||||
|
@ -14,6 +14,9 @@ var { emit } = require("./core");
|
||||
var { when: unload } = require("../system/unload");
|
||||
var listeners = new Map();
|
||||
|
||||
const { Cu } = require("chrome");
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
|
||||
var getWindowFrom = x =>
|
||||
x instanceof Ci.nsIDOMWindow ? x :
|
||||
x instanceof Ci.nsIDOMDocument ? x.defaultView :
|
||||
@ -21,7 +24,7 @@ var getWindowFrom = x =>
|
||||
null;
|
||||
|
||||
function removeFromListeners() {
|
||||
this.removeEventListener("DOMWindowClose", removeFromListeners);
|
||||
ShimWaiver.getProperty(this, "removeEventListener")("DOMWindowClose", removeFromListeners);
|
||||
for (let cleaner of listeners.get(this))
|
||||
cleaner();
|
||||
|
||||
@ -56,11 +59,11 @@ function open(target, type, options) {
|
||||
|
||||
// We need to remove from our map the `window` once is closed, to prevent
|
||||
// memory leak
|
||||
window.addEventListener("DOMWindowClose", removeFromListeners);
|
||||
ShimWaiver.getProperty(window, "addEventListener")("DOMWindowClose", removeFromListeners);
|
||||
}
|
||||
|
||||
cleaners.push(() => target.removeEventListener(type, listener, capture));
|
||||
target.addEventListener(type, listener, capture);
|
||||
cleaners.push(() => ShimWaiver.getProperty(target, "removeEventListener")(type, listener, capture));
|
||||
ShimWaiver.getProperty(target, "addEventListener")(type, listener, capture);
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@ -9,8 +9,12 @@ const { once, off } = require("../event/core");
|
||||
const { id: addonID } = require("../self");
|
||||
|
||||
const unloadMessage = require("@loader/unload");
|
||||
const { addObserver, removeObserver } = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
const observerService = Cc['@mozilla.org/observer-service;1'].
|
||||
getService(Ci.nsIObserverService);
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
|
||||
const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
|
||||
|
||||
|
||||
const addonUnloadTopic = "sdk:loader:destroy";
|
||||
|
||||
|
@ -50,7 +50,8 @@ const Observer = Class({
|
||||
* Keyboard event being emitted.
|
||||
*/
|
||||
handleEvent(event) {
|
||||
emit(this, event.type, event, event.target.ownerDocument.defaultView);
|
||||
emit(this, event.type, event, event.target.ownerDocument ? event.target.ownerDocument.defaultView
|
||||
: undefined);
|
||||
}
|
||||
});
|
||||
|
||||
|
16
addon-sdk/source/lib/sdk/system/events-shimmed.js
Normal file
16
addon-sdk/source/lib/sdk/system/events-shimmed.js
Normal file
@ -0,0 +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/. */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.metadata = {
|
||||
'stability': 'unstable'
|
||||
};
|
||||
|
||||
const events = require('./events.js');
|
||||
|
||||
exports.emit = (type, event) => events.emit(type, event, true);
|
||||
exports.on = (type, listener, strong) => events.on(type, listener, strong, true);
|
||||
exports.once = (type, listener) => events.once(type, listener, true);
|
||||
exports.off = (type, listener) => events.off(type, listener, true);
|
@ -12,8 +12,13 @@ const { Cc, Ci, Cu } = require('chrome');
|
||||
const { Unknown } = require('../platform/xpcom');
|
||||
const { Class } = require('../core/heritage');
|
||||
const { ns } = require('../core/namespace');
|
||||
const { addObserver, removeObserver, notifyObservers } =
|
||||
const observerService =
|
||||
Cc['@mozilla.org/observer-service;1'].getService(Ci.nsIObserverService);
|
||||
const { addObserver, removeObserver, notifyObservers } = observerService;
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
const addObserverNoShim = ShimWaiver.getProperty(observerService, "addObserver");
|
||||
const removeObserverNoShim = ShimWaiver.getProperty(observerService, "removeObserver");
|
||||
const notifyObserversNoShim = ShimWaiver.getProperty(observerService, "notifyObservers");
|
||||
const unloadSubject = require('@loader/unload');
|
||||
|
||||
const Subject = Class({
|
||||
@ -33,7 +38,7 @@ const Subject = Class({
|
||||
getInterfaces: function() {}
|
||||
});
|
||||
|
||||
function emit(type, event) {
|
||||
function emit(type, event, shimmed = false) {
|
||||
// From bug 910599
|
||||
// We must test to see if 'subject' or 'data' is a defined property
|
||||
// of the event object, but also allow primitives to be passed in,
|
||||
@ -48,7 +53,11 @@ function emit(type, event) {
|
||||
// All other types return themselves (and cast to strings/null
|
||||
// via observer service)
|
||||
event;
|
||||
notifyObservers(subject, type, data);
|
||||
if (shimmed) {
|
||||
notifyObservers(subject, type, data);
|
||||
} else {
|
||||
notifyObserversNoShim(subject, type, data);
|
||||
}
|
||||
}
|
||||
exports.emit = emit;
|
||||
|
||||
@ -83,7 +92,7 @@ const Observer = Class({
|
||||
|
||||
const subscribers = ns();
|
||||
|
||||
function on(type, listener, strong) {
|
||||
function on(type, listener, strong, shimmed = false) {
|
||||
// Unless last optional argument is `true` we use a weak reference to a
|
||||
// listener.
|
||||
let weak = !strong;
|
||||
@ -94,29 +103,34 @@ function on(type, listener, strong) {
|
||||
if (!(type in observers)) {
|
||||
let observer = Observer(listener);
|
||||
observers[type] = observer;
|
||||
addObserver(observer, type, weak);
|
||||
if (shimmed) {
|
||||
addObserver(observer, type, weak);
|
||||
} else {
|
||||
addObserverNoShim(observer, type, weak);
|
||||
}
|
||||
// WeakRef gymnastics to remove all alive observers on unload
|
||||
let ref = Cu.getWeakReference(observer);
|
||||
weakRefs.set(observer, ref);
|
||||
stillAlive.set(ref, type);
|
||||
wasShimmed.set(ref, shimmed);
|
||||
}
|
||||
}
|
||||
exports.on = on;
|
||||
|
||||
function once(type, listener) {
|
||||
function once(type, listener, shimmed = false) {
|
||||
// Note: this code assumes order in which listeners are called, which is fine
|
||||
// as long as dispatch happens in same order as listener registration which
|
||||
// is the case now. That being said we should be aware that this may break
|
||||
// in a future if order will change.
|
||||
on(type, listener);
|
||||
on(type, listener, shimmed);
|
||||
on(type, function cleanup() {
|
||||
off(type, listener);
|
||||
off(type, cleanup);
|
||||
}, true);
|
||||
off(type, listener, shimmed);
|
||||
off(type, cleanup, shimmed);
|
||||
}, true, shimmed);
|
||||
}
|
||||
exports.once = once;
|
||||
|
||||
function off(type, listener) {
|
||||
function off(type, listener, shimmed = false) {
|
||||
// Take list of observers as with the given `listener`.
|
||||
let observers = subscribers(listener);
|
||||
// If `observer` for the given `type` is registered, then
|
||||
@ -124,8 +138,13 @@ function off(type, listener) {
|
||||
if (type in observers) {
|
||||
let observer = observers[type];
|
||||
delete observers[type];
|
||||
removeObserver(observer, type);
|
||||
if (shimmed) {
|
||||
removeObserver(observer, type);
|
||||
} else {
|
||||
removeObserverNoShim(observer, type);
|
||||
}
|
||||
stillAlive.delete(weakRefs.get(observer));
|
||||
wasShimmed.delete(weakRefs.get(observer));
|
||||
}
|
||||
}
|
||||
exports.off = off;
|
||||
@ -134,12 +153,14 @@ exports.off = off;
|
||||
var weakRefs = new WeakMap();
|
||||
|
||||
// and we're out of beta, we're releasing on time!
|
||||
var stillAlive = new Map();
|
||||
var stillAlive = new Map();
|
||||
|
||||
var wasShimmed = new Map();
|
||||
|
||||
on('sdk:loader:destroy', function onunload({ subject, data: reason }) {
|
||||
// using logic from ./unload, to avoid a circular module reference
|
||||
if (subject.wrappedJSObject === unloadSubject) {
|
||||
off('sdk:loader:destroy', onunload);
|
||||
off('sdk:loader:destroy', onunload, false);
|
||||
|
||||
// don't bother
|
||||
if (reason === 'shutdown')
|
||||
@ -147,9 +168,14 @@ on('sdk:loader:destroy', function onunload({ subject, data: reason }) {
|
||||
|
||||
stillAlive.forEach( (type, ref) => {
|
||||
let observer = ref.get();
|
||||
if (observer)
|
||||
removeObserver(observer, type);
|
||||
if (observer) {
|
||||
if (wasShimmed.get(ref)) {
|
||||
removeObserver(observer, type);
|
||||
} else {
|
||||
removeObserverNoShim(observer, type);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// a strong reference
|
||||
}, true);
|
||||
}, true, false);
|
||||
|
@ -17,7 +17,7 @@
|
||||
"preferences-service": "sdk/preferences/service",
|
||||
"promise": "sdk/core/promise",
|
||||
"system": "sdk/system",
|
||||
"system/events": "sdk/system/events",
|
||||
"system/events": "sdk/system/events-shimmed",
|
||||
"tabs/tab": "sdk/tabs/tab",
|
||||
"tabs/utils": "sdk/tabs/utils",
|
||||
"timer": "sdk/timers",
|
||||
@ -40,7 +40,7 @@
|
||||
"app-strings": "sdk/deprecated/app-strings",
|
||||
"environment": "sdk/system/environment",
|
||||
"keyboard/utils": "sdk/keyboard/utils",
|
||||
"dom/events": "sdk/dom/events",
|
||||
"dom/events": "sdk/dom/events-shimmed",
|
||||
"utils/data": "sdk/io/data",
|
||||
"test/assert": "sdk/test/assert",
|
||||
"hidden-frame": "sdk/frame/hidden-frame",
|
||||
|
@ -142,7 +142,7 @@ exports["test compatibility"] = function(assert) {
|
||||
require("sdk/tabs/utils"), "sdk/tabs/utils -> tabs/utils");
|
||||
|
||||
assert.equal(require("dom/events"),
|
||||
require("sdk/dom/events"), "sdk/dom/events -> dom/events");
|
||||
require("sdk/dom/events-shimmed"), "sdk/dom/events-shimmed -> dom/events");
|
||||
|
||||
assert.equal(require("tabs/tab.js"),
|
||||
require("sdk/tabs/tab"), "sdk/tabs/tab -> tabs/tab.js");
|
||||
|
@ -42,86 +42,6 @@ var close = function(tab) {
|
||||
return promise;
|
||||
}
|
||||
|
||||
exports["test multiple tabs"] = function(assert, done) {
|
||||
let loader = Loader(module);
|
||||
let { events } = loader.require("sdk/content/events");
|
||||
let { on, off } = loader.require("sdk/event/core");
|
||||
let actual = [];
|
||||
|
||||
on(events, "data", handler);
|
||||
function handler ({type, target, timeStamp}) {
|
||||
eventFilter(type, target, () => {
|
||||
actual.push(type + " -> " + target.URL)
|
||||
});
|
||||
}
|
||||
|
||||
let window = getMostRecentBrowserWindow();
|
||||
let firstTab = open("data:text/html,first-tab", window);
|
||||
|
||||
when("pageshow", firstTab).
|
||||
then(close).
|
||||
then(use(window)).
|
||||
then(open("data:text/html,second-tab")).
|
||||
then(when("pageshow")).
|
||||
then(close).
|
||||
then(function() {
|
||||
assert.deepEqual(actual, [
|
||||
"document-element-inserted -> data:text/html,first-tab",
|
||||
"DOMContentLoaded -> data:text/html,first-tab",
|
||||
"load -> data:text/html,first-tab",
|
||||
"pageshow -> data:text/html,first-tab",
|
||||
"document-element-inserted -> data:text/html,second-tab",
|
||||
"DOMContentLoaded -> data:text/html,second-tab",
|
||||
"load -> data:text/html,second-tab",
|
||||
"pageshow -> data:text/html,second-tab"
|
||||
], "all events dispatche as expeced")
|
||||
}, function(reason) {
|
||||
assert.fail(Error(reason));
|
||||
}).then(function() {
|
||||
loader.unload();
|
||||
off(events, "data", handler);
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
exports["test nested frames"] = function(assert, done) {
|
||||
let loader = Loader(module);
|
||||
let { events } = loader.require("sdk/content/events");
|
||||
let { on, off } = loader.require("sdk/event/core");
|
||||
let actual = [];
|
||||
on(events, "data", handler);
|
||||
function handler ({type, target, timeStamp}) {
|
||||
eventFilter(type, target, () => {
|
||||
actual.push(type + " -> " + target.URL)
|
||||
});
|
||||
}
|
||||
|
||||
let window = getMostRecentBrowserWindow();
|
||||
let uri = encodeURI("data:text/html,<iframe src='data:text/html,iframe'>");
|
||||
let tab = open(uri, window);
|
||||
|
||||
when("pageshow", tab).
|
||||
then(close).
|
||||
then(function() {
|
||||
assert.deepEqual(actual, [
|
||||
"document-element-inserted -> " + uri,
|
||||
"DOMContentLoaded -> " + uri,
|
||||
"document-element-inserted -> data:text/html,iframe",
|
||||
"DOMContentLoaded -> data:text/html,iframe",
|
||||
"load -> data:text/html,iframe",
|
||||
"pageshow -> data:text/html,iframe",
|
||||
"load -> " + uri,
|
||||
"pageshow -> " + uri
|
||||
], "events where dispatched")
|
||||
}, function(reason) {
|
||||
assert.fail(Error(reason))
|
||||
}).then(function() {
|
||||
loader.unload();
|
||||
off(events, "data", handler);
|
||||
done();
|
||||
});
|
||||
};
|
||||
|
||||
exports["test dead object errors"] = function(assert, done) {
|
||||
let system = require("sdk/system/events");
|
||||
let loader = Loader(module);
|
||||
|
@ -14,7 +14,7 @@ const { Panel } = require("dev/panel");
|
||||
const { Class } = require("sdk/core/heritage");
|
||||
const { openToolbox, closeToolbox, getCurrentPanel } = require("dev/utils");
|
||||
const { MessageChannel } = require("sdk/messaging");
|
||||
const { when } = require("sdk/dom/events");
|
||||
const { when } = require("sdk/dom/events-shimmed");
|
||||
const { viewFor } = require("sdk/view/core");
|
||||
const { createView } = require("dev/panel/view");
|
||||
|
||||
|
@ -12,16 +12,20 @@ const {when} = require("sdk/dom/events");
|
||||
var observerService = Cc["@mozilla.org/observer-service;1"]
|
||||
.getService(Ci.nsIObserverService);
|
||||
|
||||
const { ShimWaiver } = Cu.import("resource://gre/modules/ShimWaiver.jsm");
|
||||
const addObserver = ShimWaiver.getProperty(observerService, "addObserver");
|
||||
const removeObserver = ShimWaiver.getProperty(observerService, "removeObserver");
|
||||
|
||||
const getActiveTab = (window=getMostRecentBrowserWindow()) =>
|
||||
tabUtils.getActiveTab(window)
|
||||
|
||||
const openWindow = () => {
|
||||
const window = open();
|
||||
return new Promise((resolve) => {
|
||||
observerService.addObserver({
|
||||
addObserver({
|
||||
observe(subject, topic) {
|
||||
if (subject === window) {
|
||||
observerService.removeObserver(this, topic);
|
||||
removeObserver(this, topic);
|
||||
resolve(subject);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user