Created
April 30, 2013 20:17
-
-
Save darkowlzz/5491597 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 { Cc, Ci } = require('chrome'); | |
const array = require('../util/array'); | |
const observers = require('../deprecated/observer-service'); | |
const { defer } = require('sdk/core/promise'); | |
const windowWatcher = Cc['@mozilla.org/embedcomp/window-watcher;1']. | |
getService(Ci.nsIWindowWatcher); | |
const appShellService = Cc['@mozilla.org/appshell/appShellService;1']. | |
getService(Ci.nsIAppShellService); | |
const WM = Cc['@mozilla.org/appshell/window-mediator;1']. | |
getService(Ci.nsIWindowMediator); | |
const io = Cc['@mozilla.org/network/io-service;1']. | |
getService(Ci.nsIIOService); | |
const BROWSER = 'navigator:browser', | |
URI_BROWSER = 'chrome://browser/content/browser.xul', | |
NAME = '_blank', | |
FEATURES = 'chrome,all,dialog=no'; | |
function isWindowPrivate(win) { | |
if (!win) | |
return false; | |
// if the pbService is undefined, the PrivateBrowsingUtils.jsm is available, | |
// and the app is Firefox, then assume per-window private browsing is | |
// enabled. | |
try { | |
return win.QueryInterface(Ci.nsIInterfaceRequestor) | |
.getInterface(Ci.nsIWebNavigation) | |
.QueryInterface(Ci.nsILoadContext) | |
.usePrivateBrowsing; | |
} | |
catch(e) {} | |
// Sometimes the input is not a nsIDOMWindow.. but it is still a winodw. | |
try { | |
return !!win.docShell.QueryInterface(Ci.nsILoadContext).usePrivateBrowsing; | |
} | |
catch (e) {} | |
return false; | |
} | |
exports.isWindowPrivate = isWindowPrivate; | |
function getMostRecentBrowserWindow() { | |
return getMostRecentWindow(BROWSER); | |
} | |
exports.getMostRecentBrowserWindow = getMostRecentBrowserWindow; | |
function getHiddenWindow() { | |
return appShellService.hiddenDOMWindow; | |
} | |
exports.getHiddenWindow = getHiddenWindow; | |
function getMostRecentWindow(type) { | |
return WM.getMostRecentWindow(type); | |
} | |
exports.getMostRecentWindow = getMostRecentWindow; | |
/** | |
* Returns the ID of the window's current inner window. | |
*/ | |
function getInnerId(window) { | |
return window.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIDOMWindowUtils).currentInnerWindowID; | |
}; | |
exports.getInnerId = getInnerId; | |
/** | |
* Returns the ID of the window's outer window. | |
*/ | |
function getOuterId(window) { | |
return window.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIDOMWindowUtils).outerWindowID; | |
}; | |
exports.getOuterId = getOuterId; | |
/** | |
* Returns `nsIXULWindow` for the given `nsIDOMWindow`. | |
*/ | |
function getXULWindow(window) { | |
return window.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIWebNavigation). | |
QueryInterface(Ci.nsIDocShellTreeItem). | |
treeOwner.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIXULWindow); | |
}; | |
exports.getXULWindow = getXULWindow; | |
function getDOMWindow(xulWindow) { | |
return xulWindow.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIDOMWindow); | |
} | |
exports.getDOMWindow = getDOMWindow; | |
/** | |
* Returns `nsIBaseWindow` for the given `nsIDOMWindow`. | |
*/ | |
function getBaseWindow(window) { | |
return window.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIWebNavigation). | |
QueryInterface(Ci.nsIDocShell). | |
QueryInterface(Ci.nsIDocShellTreeItem). | |
treeOwner. | |
QueryInterface(Ci.nsIBaseWindow); | |
} | |
exports.getBaseWindow = getBaseWindow; | |
/** | |
* Returns the `nsIDOMWindow` toplevel window for any child/inner window | |
*/ | |
function getToplevelWindow(window) { | |
return window.QueryInterface(Ci.nsIInterfaceRequestor) | |
.getInterface(Ci.nsIWebNavigation) | |
.QueryInterface(Ci.nsIDocShellTreeItem) | |
.rootTreeItem | |
.QueryInterface(Ci.nsIInterfaceRequestor) | |
.getInterface(Ci.nsIDOMWindow); | |
} | |
exports.getToplevelWindow = getToplevelWindow; | |
function getWindowDocShell(window) window.gBrowser.docShell; | |
exports.getWindowDocShell = getWindowDocShell; | |
function getWindowLoadingContext(window) { | |
return getWindowDocShell(window). | |
QueryInterface(Ci.nsILoadContext); | |
} | |
exports.getWindowLoadingContext = getWindowLoadingContext; | |
/** | |
* Removes given window from the application's window registry. Unless | |
* `options.close` is `false` window is automatically closed on application | |
* quit. | |
* @params {nsIDOMWindow} window | |
* @params {Boolean} options.close | |
*/ | |
function backgroundify(window, options) { | |
let base = getBaseWindow(window); | |
base.visibility = false; | |
base.enabled = false; | |
appShellService.unregisterTopLevelWindow(getXULWindow(window)); | |
if (!options || options.close !== false) | |
observers.add('quit-application-granted', window.close.bind(window)); | |
return window; | |
} | |
exports.backgroundify = backgroundify; | |
/** | |
* Takes hash of options and serializes it to a features string that | |
* can be used passed to `window.open`. For more details on features string see: | |
* https://developer.mozilla.org/en/DOM/window.open#Position_and_size_features | |
*/ | |
function serializeFeatures(options) { | |
return Object.keys(options).reduce(function(result, name) { | |
let value = options[name]; | |
// the chrome and private features are special | |
if ((name == 'private' || name == 'chrome')) | |
return result + ((value === true) ? ',' + name : ''); | |
return result + ',' + name + '=' + | |
(value === true ? 'yes' : value === false ? 'no' : value); | |
}, '').substr(1); | |
} | |
/** | |
* Opens a top level window and returns it's `nsIDOMWindow` representation. | |
* @params {String} uri | |
* URI of the document to be loaded into window. | |
* @params {nsIDOMWindow} options.parent | |
* Used as parent for the created window. | |
* @params {String} options.name | |
* Optional name that is assigned to the window. | |
* @params {Object} options.features | |
* Map of key, values like: `{ width: 10, height: 15, chrome: true, private: true }`. | |
*/ | |
function open(uri, options) { | |
console.log("URI : " + io.newURI(uri, null, null).scheme); | |
if (['chrome', 'resource'].indexOf(io.newURI(uri, 'UTF-8', null).scheme) < 0) | |
throw new Error("only chrome and resource uris are allowed"); | |
options = options || {}; | |
let newWindow = windowWatcher. | |
openWindow(options.parent || null, | |
uri || URI_BROWSER, | |
options.name || null, | |
serializeFeatures(options.features || {}), | |
options.args || null); | |
return newWindow; | |
} | |
exports.open = open; | |
function onFocus(window) { | |
let { resolve, promise } = defer(); | |
if (isFocused(window)) { | |
resolve(window); | |
} | |
else { | |
window.addEventListener("focus", function focusListener() { | |
window.removeEventListener("focus", focusListener, true); | |
resolve(window); | |
}, true); | |
} | |
return promise; | |
} | |
exports.onFocus = onFocus; | |
function isFocused(window) { | |
const FM = Cc["@mozilla.org/focus-manager;1"]. | |
getService(Ci.nsIFocusManager); | |
let childTargetWindow = {}; | |
FM.getFocusedElementForWindow(window, true, childTargetWindow); | |
childTargetWindow = childTargetWindow.value; | |
let focusedChildWindow = {}; | |
if (FM.activeWindow) { | |
FM.getFocusedElementForWindow(FM.activeWindow, true, focusedChildWindow); | |
focusedChildWindow = focusedChildWindow.value; | |
} | |
return (focusedChildWindow === childTargetWindow); | |
} | |
exports.isFocused = isFocused; | |
/** | |
* Opens a top level window and returns it's `nsIDOMWindow` representation. | |
* Same as `open` but with more features | |
* @param {Object} options | |
* | |
*/ | |
function openDialog(options) { | |
options = options || {}; | |
let features = options.features || FEATURES; | |
if (!!options.private && | |
!array.has(features.toLowerCase().split(','), 'private')) { | |
features = features.split(',').concat('private').join(','); | |
} | |
let browser = getMostRecentBrowserWindow(); | |
// if there is no browser then do nothing | |
if (!browser) | |
return undefined; | |
let newWindow = browser.openDialog.apply( | |
browser, | |
array.flatten([ | |
options.url || URI_BROWSER, | |
options.name || NAME, | |
features, | |
options.args || null | |
]) | |
); | |
return newWindow; | |
} | |
exports.openDialog = openDialog; | |
/** | |
* Returns an array of all currently opened windows. | |
* Note that these windows may still be loading. | |
*/ | |
function windows(type, options) { | |
options = options || {}; | |
let list = []; | |
let winEnum = WM.getEnumerator(type); | |
while (winEnum.hasMoreElements()) { | |
let window = winEnum.getNext().QueryInterface(Ci.nsIDOMWindow); | |
// Only add non-private windows when pb permission isn't set, | |
// unless an option forces the addition of them. | |
if (options.includePrivate || !isWindowPrivate(window)) { | |
list.push(window); | |
} | |
} | |
return list; | |
} | |
exports.windows = windows; | |
/** | |
* Check if the given window is interactive. | |
* i.e. if its "DOMContentLoaded" event has already been fired. | |
* @params {nsIDOMWindow} window | |
*/ | |
function isInteractive(window) | |
window.document.readyState === "interactive" || isDocumentLoaded(window) | |
exports.isInteractive = isInteractive; | |
/** | |
* Check if the given window is completely loaded. | |
* i.e. if its "load" event has already been fired and all possible DOM content | |
* is done loading (the whole DOM document, images content, ...) | |
* @params {nsIDOMWindow} window | |
*/ | |
function isDocumentLoaded(window) { | |
return window.document.readyState == "complete"; | |
} | |
exports.isDocumentLoaded = isDocumentLoaded; | |
function isBrowser(window) { | |
try { | |
return window.document.documentElement.getAttribute("windowtype") === BROWSER; | |
} | |
catch (e) {} | |
return false; | |
}; | |
exports.isBrowser = isBrowser; | |
function getWindowTitle(window) { | |
return window && window.document ? window.document.title : null; | |
} | |
exports.getWindowTitle = getWindowTitle; | |
function isXULBrowser(window) { | |
return !!(isBrowser(window) && window.XULBrowserWindow); | |
} | |
exports.isXULBrowser = isXULBrowser; | |
/** | |
* Returns the most recent focused window | |
*/ | |
function getFocusedWindow() { | |
let window = WM.getMostRecentWindow(BROWSER); | |
return window ? window.document.commandDispatcher.focusedWindow : null; | |
} | |
exports.getFocusedWindow = getFocusedWindow; | |
/** | |
* Returns the focused element in the most recent focused window | |
*/ | |
function getFocusedElement() { | |
let window = WM.getMostRecentWindow(BROWSER); | |
return window ? window.document.commandDispatcher.focusedElement : null; | |
} | |
exports.getFocusedElement = getFocusedElement; | |
function getFrames(window) { | |
return Array.slice(window.frames).reduce(function(frames, frame) { | |
return frames.concat(frame, getFrames(frame)) | |
}, []) | |
} | |
exports.getFrames = getFrames; | |
function getScreenPixelsPerCSSPixel(window) { | |
return window.QueryInterface(Ci.nsIInterfaceRequestor). | |
getInterface(Ci.nsIDOMWindowUtils).screenPixelsPerCSSPixel; | |
} | |
exports.getScreenPixelsPerCSSPixel = getScreenPixelsPerCSSPixel; | |
function getOwnerBrowserWindow(node) { | |
/** | |
Takes DOM node and returns browser window that contains it. | |
**/ | |
let window = node.ownerDocument.defaultView.top; | |
// If anchored window is browser then it's target browser window. | |
if (isBrowser(window)) return window; | |
// Otherwise iterate over each browser window and find a one that | |
// contains browser for the anchored window document. | |
let document = window.document; | |
let browsers = windows("navigator:browser", { includePrivate: true }); | |
return array.find(browsers, function isTargetBrowser(window) { | |
return !!window.gBrowser.getBrowserForDocument(document); | |
}); | |
} | |
exports.getOwnerBrowserWindow = getOwnerBrowserWindow; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment