diff options
Diffstat (limited to 'addon-sdk/source/lib/dev/panel.js')
-rw-r--r-- | addon-sdk/source/lib/dev/panel.js | 259 |
1 files changed, 0 insertions, 259 deletions
diff --git a/addon-sdk/source/lib/dev/panel.js b/addon-sdk/source/lib/dev/panel.js deleted file mode 100644 index 1ef6a303a..000000000 --- a/addon-sdk/source/lib/dev/panel.js +++ /dev/null @@ -1,259 +0,0 @@ -/* 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": "experimental" -}; - -const { Cu } = require("chrome"); -const { Class } = require("../sdk/core/heritage"); -const { curry } = require("../sdk/lang/functional"); -const { EventTarget } = require("../sdk/event/target"); -const { Disposable, setup, dispose } = require("../sdk/core/disposable"); -const { emit, off, setListeners } = require("../sdk/event/core"); -const { when } = require("../sdk/event/utils"); -const { getFrameElement } = require("../sdk/window/utils"); -const { contract, validate } = require("../sdk/util/contract"); -const { data: { url: resolve }} = require("../sdk/self"); -const { identify } = require("../sdk/ui/id"); -const { isLocalURL, URL } = require("../sdk/url"); -const { encode } = require("../sdk/base64"); -const { marshal, demarshal } = require("./ports"); -const { fromTarget } = require("./debuggee"); -const { removed } = require("../sdk/dom/events"); -const { id: addonID } = require("../sdk/self"); -const { viewFor } = require("../sdk/view/core"); -const { createView } = require("./panel/view"); - -const OUTER_FRAME_URI = module.uri.replace(/\.js$/, ".html"); -const FRAME_SCRIPT = module.uri.replace("/panel.js", "/frame-script.js"); -const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; -const HTML_NS = "http://www.w3.org/1999/xhtml"; - -const makeID = name => - ("dev-panel-" + addonID + "-" + name). - split("/").join("-"). - split(".").join("-"). - split(" ").join("-"). - replace(/[^A-Za-z0-9_\-]/g, ""); - - -// Weak mapping between `Panel` instances and their frame's -// `nsIMessageManager`. -const managers = new WeakMap(); -// Return `nsIMessageManager` for the given `Panel` instance. -const managerFor = x => managers.get(x); - -// Weak mappinging between iframe's and their owner -// `Panel` instances. -const panels = new WeakMap(); -const panelFor = frame => panels.get(frame); - -// Weak mapping between panels and debugees they're targeting. -const debuggees = new WeakMap(); -const debuggeeFor = panel => debuggees.get(panel); - -const frames = new WeakMap(); -const frameFor = panel => frames.get(panel); - -const setAttributes = (node, attributes) => { - for (var key in attributes) - node.setAttribute(key, attributes[key]); -}; - -const onStateChange = ({target, data}) => { - const panel = panelFor(target); - panel.readyState = data.readyState; - emit(panel, data.type, { target: panel, type: data.type }); -}; - -// port event listener on the message manager that demarshalls -// and forwards to the actual receiver. This is a workaround -// until Bug 914974 is fixed. -const onPortMessage = ({data, target}) => { - const port = demarshal(target, data.port); - if (port) - port.postMessage(data.message); -}; - -// When frame is removed from the toolbox destroy panel -// associated with it to release all the resources. -const onFrameRemove = frame => { - panelFor(frame).destroy(); -}; - -const onFrameInited = frame => { - frame.style.visibility = "visible"; -} - -const inited = frame => new Promise(resolve => { - const { messageManager } = frame.frameLoader; - const listener = message => { - messageManager.removeMessageListener("sdk/event/ready", listener); - resolve(frame); - }; - messageManager.addMessageListener("sdk/event/ready", listener); -}); - -const getTarget = ({target}) => target; - -const Panel = Class({ - extends: Disposable, - implements: [EventTarget], - get id() { - return makeID(this.name || this.label); - }, - readyState: "uninitialized", - ready: function() { - const { readyState } = this; - const isReady = readyState === "complete" || - readyState === "interactive"; - return isReady ? Promise.resolve(this) : - when(this, "ready").then(getTarget); - }, - loaded: function() { - const { readyState } = this; - const isLoaded = readyState === "complete"; - return isLoaded ? Promise.resolve(this) : - when(this, "load").then(getTarget); - }, - unloaded: function() { - const { readyState } = this; - const isUninitialized = readyState === "uninitialized"; - return isUninitialized ? Promise.resolve(this) : - when(this, "unload").then(getTarget); - }, - postMessage: function(data, ports=[]) { - const manager = managerFor(this); - manager.sendAsyncMessage("sdk/event/message", { - type: "message", - bubbles: false, - cancelable: false, - data: data, - origin: this.url, - ports: ports.map(marshal(manager)) - }); - } -}); -exports.Panel = Panel; - -validate.define(Panel, contract({ - label: { - is: ["string"], - msg: "The `option.label` must be a provided" - }, - tooltip: { - is: ["string", "undefined"], - msg: "The `option.tooltip` must be a string" - }, - icon: { - is: ["string"], - map: x => x && resolve(x), - ok: x => isLocalURL(x), - msg: "The `options.icon` must be a valid local URI." - }, - url: { - map: x => resolve(x.toString()), - is: ["string"], - ok: x => isLocalURL(x), - msg: "The `options.url` must be a valid local URI." - }, - invertIconForLightTheme: { - is: ["boolean", "undefined"], - msg: "The `options.invertIconForLightTheme` must be a boolean." - }, - invertIconForDarkTheme: { - is: ["boolean", "undefined"], - msg: "The `options.invertIconForDarkTheme` must be a boolean." - } -})); - -setup.define(Panel, (panel, {window, toolbox, url}) => { - // Hack: Given that iframe created by devtools API is no good for us, - // we obtain original iframe and replace it with the one that has - // desired configuration. - const original = getFrameElement(window); - const container = original.parentNode; - original.remove(); - const frame = createView(panel, container.ownerDocument); - - // Following modifications are a temporary workaround until Bug 1049188 - // is fixed. - // Enforce certain iframe customizations regardless of users request. - setAttributes(frame, { - "id": original.id, - "src": url, - "flex": 1, - "forceOwnRefreshDriver": "", - "tooltip": "aHTMLTooltip" - }); - frame.style.visibility = "hidden"; - frame.classList.add("toolbox-panel-iframe"); - // Inject iframe into designated node until add-on author decides - // to inject it elsewhere instead. - if (!frame.parentNode) - container.appendChild(frame); - - // associate view with a panel - frames.set(panel, frame); - - // associate panel model with a frame view. - panels.set(frame, panel); - - const debuggee = fromTarget(toolbox.target); - // associate debuggee with a panel. - debuggees.set(panel, debuggee); - - - // Setup listeners for the frame message manager. - const { messageManager } = frame.frameLoader; - messageManager.addMessageListener("sdk/event/ready", onStateChange); - messageManager.addMessageListener("sdk/event/load", onStateChange); - messageManager.addMessageListener("sdk/event/unload", onStateChange); - messageManager.addMessageListener("sdk/port/message", onPortMessage); - messageManager.loadFrameScript(FRAME_SCRIPT, false); - - managers.set(panel, messageManager); - - // destroy panel if frame is removed. - removed(frame).then(onFrameRemove); - // show frame when it is initialized. - inited(frame).then(onFrameInited); - - - // set listeners if there are ones defined on the prototype. - setListeners(panel, Object.getPrototypeOf(panel)); - - - panel.setup({ debuggee: debuggee }); -}); - -createView.define(Panel, (panel, document) => { - const frame = document.createElement("iframe"); - setAttributes(frame, { - "sandbox": "allow-scripts", - // We end up using chrome iframe with forced message manager - // as fixing a swapFrameLoader seemed like a giant task (see - // Bug 1075490). - "type": "chrome", - "forcemessagemanager": true, - "transparent": true, - "seamless": "seamless", - }); - return frame; -}); - -dispose.define(Panel, function(panel) { - debuggeeFor(panel).close(); - - debuggees.delete(panel); - managers.delete(panel); - frames.delete(panel); - panel.readyState = "destroyed"; - panel.dispose(); -}); - -viewFor.define(Panel, frameFor); |