forked from mirrors/gecko-dev
***
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
193 lines
5.8 KiB
JavaScript
193 lines
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"];
|
|
|
|
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", "sizemodechange", "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 "sizemodechange":
|
|
WindowHelper.onSizemodeChange(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) {
|
|
_trackedWindows.splice(window.windowState == window.STATE_MINIMIZED ?
|
|
_trackedWindows.length - 1 : 0, 0, 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);
|
|
},
|
|
|
|
onSizemodeChange(window) {
|
|
if (window.windowState == window.STATE_MINIMIZED) {
|
|
// Make sure to have the minimized window at the end of the list.
|
|
_untrackWindowOrder(window);
|
|
_trackedWindows.push(window);
|
|
}
|
|
},
|
|
};
|
|
|
|
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);
|
|
},
|
|
};
|