diff options
Diffstat (limited to 'toolkit/modules/addons/WebNavigationFrames.jsm')
-rw-r--r-- | toolkit/modules/addons/WebNavigationFrames.jsm | 142 |
1 files changed, 142 insertions, 0 deletions
diff --git a/toolkit/modules/addons/WebNavigationFrames.jsm b/toolkit/modules/addons/WebNavigationFrames.jsm new file mode 100644 index 000000000..5efa6d104 --- /dev/null +++ b/toolkit/modules/addons/WebNavigationFrames.jsm @@ -0,0 +1,142 @@ +/* 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"; + +const EXPORTED_SYMBOLS = ["WebNavigationFrames"]; + +var Ci = Components.interfaces; + +/* exported WebNavigationFrames */ + +function getWindowId(window) { + return window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindowUtils) + .outerWindowID; +} + +function getParentWindowId(window) { + return getWindowId(window.parent); +} + +/** + * Retrieve the DOMWindow associated to the docShell passed as parameter. + * + * @param {nsIDocShell} docShell - the docShell that we want to get the DOMWindow from. + * @returns {nsIDOMWindow} - the DOMWindow associated to the docShell. + */ +function docShellToWindow(docShell) { + return docShell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); +} + +/** + * The FrameDetail object which represents a frame in WebExtensions APIs. + * + * @typedef {Object} FrameDetail + * @inner + * @property {number} windowId - Represents the numeric id which identify the frame in its tab. + * @property {number} parentWindowId - Represents the numeric id which identify the parent frame. + * @property {string} url - Represents the current location URL loaded in the frame. + * @property {boolean} errorOccurred - Indicates whether an error is occurred during the last load + * happened on this frame (NOT YET SUPPORTED). + */ + +/** + * Convert a docShell object into its internal FrameDetail representation. + * + * @param {nsIDocShell} docShell - the docShell object to be converted into a FrameDetail JSON object. + * @returns {FrameDetail} the FrameDetail JSON object which represents the docShell. + */ +function convertDocShellToFrameDetail(docShell) { + let window = docShellToWindow(docShell); + + return { + windowId: getWindowId(window), + parentWindowId: getParentWindowId(window), + url: window.location.href, + }; +} + +/** + * A generator function which iterates over a docShell tree, given a root docShell. + * + * @param {nsIDocShell} docShell - the root docShell object + * @returns {Iterator<DocShell>} the FrameDetail JSON object which represents the docShell. + */ +function* iterateDocShellTree(docShell) { + let docShellsEnum = docShell.getDocShellEnumerator( + Ci.nsIDocShellTreeItem.typeContent, + Ci.nsIDocShell.ENUMERATE_FORWARDS + ); + + while (docShellsEnum.hasMoreElements()) { + yield docShellsEnum.getNext(); + } + + return null; +} + +/** + * Returns the frame ID of the given window. If the window is the + * top-level content window, its frame ID is 0. Otherwise, its frame ID + * is its outer window ID. + * + * @param {Window} window - The window to retrieve the frame ID for. + * @returns {number} + */ +function getFrameId(window) { + let docShell = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDocShell); + + if (!docShell.sameTypeParent) { + return 0; + } + + let utils = window.getInterface(Ci.nsIDOMWindowUtils); + return utils.outerWindowID; +} + +/** + * Search for a frame starting from the passed root docShell and + * convert it to its related frame detail representation. + * + * @param {number} frameId - the frame ID of the frame to retrieve, as + * described in getFrameId. + * @param {nsIDocShell} rootDocShell - the root docShell object + * @returns {nsIDocShell?} the docShell with the given frameId, or null + * if no match. + */ +function findDocShell(frameId, rootDocShell) { + for (let docShell of iterateDocShellTree(rootDocShell)) { + if (frameId == getFrameId(docShellToWindow(docShell))) { + return docShell; + } + } + + return null; +} + +var WebNavigationFrames = { + iterateDocShellTree, + + findDocShell, + + getFrame(docShell, frameId) { + let result = findDocShell(frameId, docShell); + if (result) { + return convertDocShellToFrameDetail(result); + } + return null; + }, + + getFrameId, + + getAllFrames(docShell) { + return Array.from(iterateDocShellTree(docShell), convertDocShellToFrameDetail); + }, + + getWindowId, + getParentWindowId, +}; |