gecko-dev/browser/modules/BrowserWindowTracker.jsm

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

212 строки
5.8 KiB
JavaScript
Исходник Обычный вид История

/* 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/. */
/*
* This module tracks each browser window and informs network module
* the current selected tab's content outer window ID.
*/
var EXPORTED_SYMBOLS = ["BrowserWindowTracker"];
Bug 1514594: Part 3 - Change ChromeUtils.import API. *** Bug 1514594: Part 3a - Change ChromeUtils.import to return an exports object; not pollute global. r=mccr8 This changes the behavior of ChromeUtils.import() to return an exports object, rather than a module global, in all cases except when `null` is passed as a second argument, and changes the default behavior not to pollute the global scope with the module's exports. Thus, the following code written for the old model: ChromeUtils.import("resource://gre/modules/Services.jsm"); is approximately the same as the following, in the new model: var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); Since the two behaviors are mutually incompatible, this patch will land with a scripted rewrite to update all existing callers to use the new model rather than the old. *** Bug 1514594: Part 3b - Mass rewrite all JS code to use the new ChromeUtils.import API. rs=Gijs This was done using the followng script: https://bitbucket.org/kmaglione/m-c-rewrites/src/tip/processors/cu-import-exports.jsm *** Bug 1514594: Part 3c - Update ESLint plugin for ChromeUtils.import API changes. r=Standard8 Differential Revision: https://phabricator.services.mozilla.com/D16747 *** Bug 1514594: Part 3d - Remove/fix hundreds of duplicate imports from sync tests. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16748 *** Bug 1514594: Part 3e - Remove no-op ChromeUtils.import() calls. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16749 *** Bug 1514594: Part 3f.1 - Cleanup various test corner cases after mass rewrite. r=Gijs *** Bug 1514594: Part 3f.2 - Cleanup various non-test corner cases after mass rewrite. r=Gijs Differential Revision: https://phabricator.services.mozilla.com/D16750 --HG-- extra : rebase_source : 359574ee3064c90f33bf36c2ebe3159a24cc8895 extra : histedit_source : b93c8f42808b1599f9122d7842d2c0b3e656a594%2C64a3a4e3359dc889e2ab2b49461bab9e27fc10a7
2019-01-17 21:18:31 +03:00
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
// Lazy getters
XPCOMUtils.defineLazyModuleGetters(this, {
PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
});
// Constants
const TAB_EVENTS = ["TabBrowserInserted", "TabSelect"];
const WINDOW_EVENTS = ["activate", "unload"];
const DEBUG = false;
// Variables
var _lastTopLevelWindowID = 0;
var _trackedWindows = [];
// Global methods
function debug(s) {
if (DEBUG) {
dump("-*- UpdateTopLevelContentWindowIDHelper: " + s + "\n");
}
}
function _updateCurrentContentOuterWindowID(browser) {
if (
!browser.outerWindowID ||
browser.outerWindowID === _lastTopLevelWindowID ||
browser.ownerGlobal != _trackedWindows[0]
) {
return;
}
debug(
"Current window uri=" +
(browser.currentURI && browser.currentURI.spec) +
" id=" +
browser.outerWindowID
);
_lastTopLevelWindowID = browser.outerWindowID;
let windowIDWrapper = Cc["@mozilla.org/supports-PRUint64;1"].createInstance(
Ci.nsISupportsPRUint64
);
windowIDWrapper.data = _lastTopLevelWindowID;
Services.obs.notifyObservers(
windowIDWrapper,
"net:current-toplevel-outer-content-windowid"
);
}
function _handleEvent(event) {
switch (event.type) {
case "TabBrowserInserted":
if (
event.target.ownerGlobal.gBrowser.selectedBrowser ===
event.target.linkedBrowser
) {
_updateCurrentContentOuterWindowID(event.target.linkedBrowser);
}
break;
case "TabSelect":
_updateCurrentContentOuterWindowID(event.target.linkedBrowser);
break;
case "activate":
WindowHelper.onActivate(event.target);
break;
case "unload":
WindowHelper.removeWindow(event.currentTarget);
break;
}
}
function _handleMessage(message) {
let browser = message.target;
if (
message.name === "Browser:Init" &&
browser === browser.ownerGlobal.gBrowser.selectedBrowser
) {
_updateCurrentContentOuterWindowID(browser);
}
}
function _trackWindowOrder(window) {
if (window.windowState == window.STATE_MINIMIZED) {
let firstMinimizedWindow = _trackedWindows.findIndex(
w => w.windowState == w.STATE_MINIMIZED
);
if (firstMinimizedWindow == -1) {
firstMinimizedWindow = _trackedWindows.length;
}
_trackedWindows.splice(firstMinimizedWindow, 0, window);
} else {
_trackedWindows.unshift(window);
}
}
function _untrackWindowOrder(window) {
let idx = _trackedWindows.indexOf(window);
if (idx >= 0) {
_trackedWindows.splice(idx, 1);
}
}
// Methods that impact a window. Put into single object for organization.
var WindowHelper = {
addWindow(window) {
// Add event listeners
TAB_EVENTS.forEach(function(event) {
window.gBrowser.tabContainer.addEventListener(event, _handleEvent);
});
WINDOW_EVENTS.forEach(function(event) {
window.addEventListener(event, _handleEvent);
});
let messageManager = window.getGroupMessageManager("browsers");
messageManager.addMessageListener("Browser:Init", _handleMessage);
_trackWindowOrder(window);
// Update the selected tab's content outer window ID.
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
},
removeWindow(window) {
_untrackWindowOrder(window);
// Remove the event listeners
TAB_EVENTS.forEach(function(event) {
window.gBrowser.tabContainer.removeEventListener(event, _handleEvent);
});
WINDOW_EVENTS.forEach(function(event) {
window.removeEventListener(event, _handleEvent);
});
let messageManager = window.getGroupMessageManager("browsers");
messageManager.removeMessageListener("Browser:Init", _handleMessage);
},
onActivate(window) {
// If this window was the last focused window, we don't need to do anything
if (window == _trackedWindows[0]) {
return;
}
_untrackWindowOrder(window);
_trackWindowOrder(window);
_updateCurrentContentOuterWindowID(window.gBrowser.selectedBrowser);
},
};
this.BrowserWindowTracker = {
/**
* Get the most recent browser window.
*
* @param options an object accepting the arguments for the search.
* * private: true to restrict the search to private windows
* only, false to restrict the search to non-private only.
* Omit the property to search in both groups.
* * allowPopups: true if popup windows are permissable.
*/
getTopWindow(options = {}) {
for (let win of _trackedWindows) {
if (
!win.closed &&
(options.allowPopups || win.toolbar.visible) &&
(!("private" in options) ||
PrivateBrowsingUtils.permanentPrivateBrowsing ||
PrivateBrowsingUtils.isWindowPrivate(win) == options.private)
) {
return win;
}
}
return null;
},
/**
* Number of currently open browser windows.
*/
get windowCount() {
return _trackedWindows.length;
},
/**
* Array of browser windows ordered by z-index, in reverse order.
* This means that the top-most browser window will be the first item.
*/
get orderedWindows() {
// Clone the windows array immediately as it may change during iteration,
// we'd rather have an outdated order than skip/revisit windows.
return [..._trackedWindows];
},
track(window) {
return WindowHelper.addWindow(window);
},
};