forked from mirrors/gecko-dev
This patch adds the ability to run SingletonEventManager handlers in different modes: sync, async, raw (no exception handling, arg cloning, or asynchrony), or asyncWithoutClone. When you call the handler, you're required to specify which variant you want. Existing uses of SingletonEventManager are all converted to async calls. Note that some of them were previously synchronous, but it didn't appear to be necessary. Also added a callOnClose for SingletonEventManager when the last listener is removed. MozReview-Commit-ID: ATHO97dWf3X --HG-- extra : rebase_source : bf02d79e3fbab84892be8a7e52ea7a1caf2e003d
107 lines
3.9 KiB
JavaScript
107 lines
3.9 KiB
JavaScript
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
/* vim: set sts=2 sw=2 et tw=80: */
|
|
"use strict";
|
|
|
|
Cu.import("resource://gre/modules/ExtensionUtils.jsm");
|
|
var {
|
|
promiseObserved,
|
|
SingletonEventManager,
|
|
} = ExtensionUtils;
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "SessionStore",
|
|
"resource:///modules/sessionstore/SessionStore.jsm");
|
|
|
|
const SS_ON_CLOSED_OBJECTS_CHANGED = "sessionstore-closed-objects-changed";
|
|
|
|
function getRecentlyClosed(maxResults, extension) {
|
|
let recentlyClosed = [];
|
|
|
|
// Get closed windows
|
|
let closedWindowData = SessionStore.getClosedWindowData(false);
|
|
for (let window of closedWindowData) {
|
|
recentlyClosed.push({
|
|
lastModified: window.closedAt,
|
|
window: WindowManager.convertFromSessionStoreClosedData(window, extension)});
|
|
}
|
|
|
|
// Get closed tabs
|
|
for (let window of WindowListManager.browserWindows()) {
|
|
let closedTabData = SessionStore.getClosedTabData(window, false);
|
|
for (let tab of closedTabData) {
|
|
recentlyClosed.push({
|
|
lastModified: tab.closedAt,
|
|
tab: TabManager.for(extension).convertFromSessionStoreClosedData(tab, window)});
|
|
}
|
|
}
|
|
|
|
// Sort windows and tabs
|
|
recentlyClosed.sort((a, b) => b.lastModified - a.lastModified);
|
|
return recentlyClosed.slice(0, maxResults);
|
|
}
|
|
|
|
function createSession(restored, extension, sessionId) {
|
|
if (!restored) {
|
|
return Promise.reject({message: `Could not restore object using sessionId ${sessionId}.`});
|
|
}
|
|
let sessionObj = {lastModified: Date.now()};
|
|
if (restored instanceof Ci.nsIDOMChromeWindow) {
|
|
return promiseObserved("sessionstore-single-window-restored", subject => subject == restored).then(() => {
|
|
sessionObj.window = WindowManager.convert(extension, restored, {populate: true});
|
|
return Promise.resolve([sessionObj]);
|
|
});
|
|
}
|
|
sessionObj.tab = TabManager.for(extension).convert(restored);
|
|
return Promise.resolve([sessionObj]);
|
|
}
|
|
|
|
extensions.registerSchemaAPI("sessions", "addon_parent", context => {
|
|
let {extension} = context;
|
|
return {
|
|
sessions: {
|
|
getRecentlyClosed: function(filter) {
|
|
let maxResults = filter.maxResults == undefined ? this.MAX_SESSION_RESULTS : filter.maxResults;
|
|
return Promise.resolve(getRecentlyClosed(maxResults, extension));
|
|
},
|
|
|
|
restore: function(sessionId) {
|
|
let session, closedId;
|
|
if (sessionId) {
|
|
closedId = sessionId;
|
|
session = SessionStore.undoCloseById(closedId);
|
|
} else if (SessionStore.lastClosedObjectType == "window") {
|
|
// If the most recently closed object is a window, just undo closing the most recent window.
|
|
session = SessionStore.undoCloseWindow(0);
|
|
} else {
|
|
// It is a tab, and we cannot call SessionStore.undoCloseTab without a window,
|
|
// so we must find the tab in which case we can just use its closedId.
|
|
let recentlyClosedTabs = [];
|
|
for (let window of WindowListManager.browserWindows()) {
|
|
let closedTabData = SessionStore.getClosedTabData(window, false);
|
|
for (let tab of closedTabData) {
|
|
recentlyClosedTabs.push(tab);
|
|
}
|
|
}
|
|
|
|
// Sort the tabs.
|
|
recentlyClosedTabs.sort((a, b) => b.closedAt - a.closedAt);
|
|
|
|
// Use the closedId of the most recently closed tab to restore it.
|
|
closedId = recentlyClosedTabs[0].closedId;
|
|
session = SessionStore.undoCloseById(closedId);
|
|
}
|
|
return createSession(session, extension, closedId);
|
|
},
|
|
|
|
onChanged: new SingletonEventManager(context, "sessions.onChanged", fire => {
|
|
let observer = () => {
|
|
fire.async();
|
|
};
|
|
|
|
Services.obs.addObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED, false);
|
|
return () => {
|
|
Services.obs.removeObserver(observer, SS_ON_CLOSED_OBJECTS_CHANGED);
|
|
};
|
|
}).api(),
|
|
},
|
|
};
|
|
});
|