summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/framescript
diff options
context:
space:
mode:
Diffstat (limited to 'addon-sdk/source/lib/framescript')
-rw-r--r--addon-sdk/source/lib/framescript/FrameScriptManager.jsm27
-rw-r--r--addon-sdk/source/lib/framescript/content.jsm94
-rw-r--r--addon-sdk/source/lib/framescript/context-menu.js215
-rw-r--r--addon-sdk/source/lib/framescript/manager.js26
-rw-r--r--addon-sdk/source/lib/framescript/util.js25
5 files changed, 0 insertions, 387 deletions
diff --git a/addon-sdk/source/lib/framescript/FrameScriptManager.jsm b/addon-sdk/source/lib/framescript/FrameScriptManager.jsm
deleted file mode 100644
index 1ce6ceb07..000000000
--- a/addon-sdk/source/lib/framescript/FrameScriptManager.jsm
+++ /dev/null
@@ -1,27 +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";
-
-const globalMM = Components.classes["@mozilla.org/globalmessagemanager;1"].
- getService(Components.interfaces.nsIMessageListenerManager);
-
-// Load frame scripts from the same dir as this module.
-// Since this JSM will be loaded using require(), PATH will be
-// overridden while running tests, just like any other module.
-const PATH = __URI__.replace('framescript/FrameScriptManager.jsm', '');
-
-// Builds a unique loader ID for this runtime. We prefix with the SDK path so
-// overriden versions of the SDK don't conflict
-var LOADER_ID = 0;
-this.getNewLoaderID = () => {
- return PATH + ":" + LOADER_ID++;
-}
-
-const frame_script = function(contentFrame, PATH) {
- let { registerContentFrame } = Components.utils.import(PATH + 'framescript/content.jsm', {});
- registerContentFrame(contentFrame);
-}
-globalMM.loadFrameScript("data:,(" + frame_script.toString() + ")(this, " + JSON.stringify(PATH) + ");", true);
-
-this.EXPORTED_SYMBOLS = ['getNewLoaderID'];
diff --git a/addon-sdk/source/lib/framescript/content.jsm b/addon-sdk/source/lib/framescript/content.jsm
deleted file mode 100644
index eaee26be3..000000000
--- a/addon-sdk/source/lib/framescript/content.jsm
+++ /dev/null
@@ -1,94 +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";
-
-const { utils: Cu, classes: Cc, interfaces: Ci } = Components;
-const { Services } = Cu.import('resource://gre/modules/Services.jsm');
-
-const cpmm = Cc['@mozilla.org/childprocessmessagemanager;1'].
- getService(Ci.nsISyncMessageSender);
-
-this.EXPORTED_SYMBOLS = ["registerContentFrame"];
-
-// This may be an overriden version of the SDK so use the PATH as a key for the
-// initial messages before we have a loaderID.
-const PATH = __URI__.replace('framescript/content.jsm', '');
-
-const { Loader } = Cu.import(PATH + 'toolkit/loader.js', {});
-
-// one Loader instance per addon (per @loader/options to be precise)
-var addons = new Map();
-
-// Tell the parent that a new process is ready
-cpmm.sendAsyncMessage('sdk/remote/process/start', {
- modulePath: PATH
-});
-
-// Load a child process module loader with the given loader options
-cpmm.addMessageListener('sdk/remote/process/load', ({ data: { modulePath, loaderID, options, reason } }) => {
- if (modulePath != PATH)
- return;
-
- // During startup races can mean we get a second load message
- if (addons.has(loaderID))
- return;
-
- options.waiveInterposition = true;
-
- let loader = Loader.Loader(options);
- let addon = {
- loader,
- require: Loader.Require(loader, { id: 'LoaderHelper' }),
- }
- addons.set(loaderID, addon);
-
- cpmm.sendAsyncMessage('sdk/remote/process/attach', {
- loaderID,
- processID: Services.appinfo.processID,
- isRemote: Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT
- });
-
- addon.child = addon.require('sdk/remote/child');
-
- for (let contentFrame of frames.values())
- addon.child.registerContentFrame(contentFrame);
-});
-
-// Unload a child process loader
-cpmm.addMessageListener('sdk/remote/process/unload', ({ data: { loaderID, reason } }) => {
- if (!addons.has(loaderID))
- return;
-
- let addon = addons.get(loaderID);
- Loader.unload(addon.loader, reason);
-
- // We want to drop the reference to the loader but never allow creating a new
- // loader with the same ID
- addons.set(loaderID, {});
-})
-
-
-var frames = new Set();
-
-this.registerContentFrame = contentFrame => {
- contentFrame.addEventListener("unload", () => {
- unregisterContentFrame(contentFrame);
- }, false);
-
- frames.add(contentFrame);
-
- for (let addon of addons.values()) {
- if ("child" in addon)
- addon.child.registerContentFrame(contentFrame);
- }
-};
-
-function unregisterContentFrame(contentFrame) {
- frames.delete(contentFrame);
-
- for (let addon of addons.values()) {
- if ("child" in addon)
- addon.child.unregisterContentFrame(contentFrame);
- }
-}
diff --git a/addon-sdk/source/lib/framescript/context-menu.js b/addon-sdk/source/lib/framescript/context-menu.js
deleted file mode 100644
index 3915b7cd8..000000000
--- a/addon-sdk/source/lib/framescript/context-menu.js
+++ /dev/null
@@ -1,215 +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";
-
-const { query, constant, cache } = require("sdk/lang/functional");
-const { pairs, each, map, object } = require("sdk/util/sequence");
-const { nodeToMessageManager } = require("./util");
-
-// Decorator function that takes `f` function and returns one that attempts
-// to run `f` with given arguments. In case of exception error is logged
-// and `fallback` is returned instead.
-const Try = (fn, fallback=null) => (...args) => {
- try {
- return fn(...args);
- } catch(error) {
- console.error(error);
- return fallback;
- }
-};
-
-// Decorator funciton that takes `f` function and returns one that returns
-// JSON cloned result of whatever `f` returns for given arguments.
-const JSONReturn = f => (...args) => JSON.parse(JSON.stringify(f(...args)));
-
-const Null = constant(null);
-
-// Table of readers mapped to field names they're going to be reading.
-const readers = Object.create(null);
-// Read function takes "contextmenu" event target `node` and returns table of
-// read field names mapped to appropriate values. Read uses above defined read
-// table to read data for all registered readers.
-const read = node =>
- object(...map(([id, read]) => [id, read(node, id)], pairs(readers)));
-
-// Table of built-in readers, each takes a descriptor and returns a reader:
-// descriptor -> node -> JSON
-const parsers = Object.create(null)
-// Function takes a descriptor of the remotely defined reader and parsese it
-// to construct a local reader that's going to read out data from context menu
-// target.
-const parse = descriptor => {
- const parser = parsers[descriptor.category];
- if (!parser) {
- console.error("Unknown reader descriptor was received", descriptor, `"${descriptor.category}"`);
- return Null
- }
- return Try(parser(descriptor));
-}
-
-// TODO: Test how chrome's mediaType behaves to try and match it's behavior.
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const SVG_NS = "http://www.w3.org/2000/svg";
-
-// Firefox always creates a HTMLVideoElement when loading an ogg file
-// directly. If the media is actually audio, be smarter and provide a
-// context menu with audio operations.
-// Source: https://github.com/mozilla/gecko-dev/blob/28c2fca3753c5371643843fc2f2f205146b083b7/browser/base/content/nsContextMenu.js#L632-L637
-const isVideoLoadingAudio = node =>
- node.readyState >= node.HAVE_METADATA &&
- (node.videoWidth == 0 || node.videoHeight == 0)
-
-const isVideo = node =>
- node instanceof node.ownerDocument.defaultView.HTMLVideoElement &&
- !isVideoLoadingAudio(node);
-
-const isAudio = node => {
- const {HTMLVideoElement, HTMLAudioElement} = node.ownerDocument.defaultView;
- return node instanceof HTMLAudioElement ? true :
- node instanceof HTMLVideoElement ? isVideoLoadingAudio(node) :
- false;
-};
-
-const isImage = ({namespaceURI, localName}) =>
- namespaceURI === HTML_NS && localName === "img" ? true :
- namespaceURI === XUL_NS && localName === "image" ? true :
- namespaceURI === SVG_NS && localName === "image" ? true :
- false;
-
-parsers["reader/MediaType()"] = constant(node =>
- isImage(node) ? "image" :
- isAudio(node) ? "audio" :
- isVideo(node) ? "video" :
- null);
-
-
-const readLink = node =>
- node.namespaceURI === HTML_NS && node.localName === "a" ? node.href :
- readLink(node.parentNode);
-
-parsers["reader/LinkURL()"] = constant(node =>
- node.matches("a, a *") ? readLink(node) : null);
-
-// Reader that reads out `true` if "contextmenu" `event.target` matches
-// `descriptor.selector` and `false` if it does not.
-parsers["reader/SelectorMatch()"] = ({selector}) =>
- node => node.matches(selector);
-
-// Accessing `selectionStart` and `selectionEnd` properties on non
-// editable input nodes throw exceptions, there for we need this util
-// function to guard us against them.
-const getInputSelection = node => {
- try {
- if ("selectionStart" in node && "selectionEnd" in node) {
- const {selectionStart, selectionEnd} = node;
- return {selectionStart, selectionEnd}
- }
- }
- catch(_) {}
-
- return null;
-}
-
-// Selection reader does not really cares about descriptor so it is
-// a constant function returning selection reader. Selection reader
-// returns string of the selected text or `null` if there is no selection.
-parsers["reader/Selection()"] = constant(node => {
- const selection = node.ownerDocument.getSelection();
- if (!selection.isCollapsed) {
- return selection.toString();
- }
- // If target node is editable (text, input, textarea, etc..) document does
- // not really handles selections there. There for we fallback to checking
- // `selectionStart` `selectionEnd` properties and if they are present we
- // extract selections manually from the `node.value`.
- else {
- const selection = getInputSelection(node);
- const isSelected = selection &&
- Number.isInteger(selection.selectionStart) &&
- Number.isInteger(selection.selectionEnd) &&
- selection.selectionStart !== selection.selectionEnd;
- return isSelected ? node.value.substring(selection.selectionStart,
- selection.selectionEnd) :
- null;
- }
-});
-
-// Query reader just reads out properties from the node, so we just use `query`
-// utility function.
-parsers["reader/Query()"] = ({path}) => JSONReturn(query(path));
-// Attribute reader just reads attribute of the event target node.
-parsers["reader/Attribute()"] = ({name}) => node => node.getAttribute(name);
-
-// Extractor reader defines generates a reader out of serialized function, who's
-// return value is JSON cloned. Note: We do know source will evaluate to function
-// as that's what we serialized on the other end, it's also ok if generated function
-// is going to throw as registered readers are wrapped in try catch to avoid breakting
-// unrelated readers.
-parsers["reader/Extractor()"] = ({source}) =>
- JSONReturn(new Function("return (" + source + ")")());
-
-// If the context-menu target node or any of its ancestors is one of these,
-// Firefox uses a tailored context menu, and so the page context doesn't apply.
-// There for `reader/isPage()` will read `false` in that case otherwise it's going
-// to read `true`.
-const nonPageElements = ["a", "applet", "area", "button", "canvas", "object",
- "embed", "img", "input", "map", "video", "audio", "menu",
- "option", "select", "textarea", "[contenteditable=true]"];
-const nonPageSelector = nonPageElements.
- concat(nonPageElements.map(tag => `${tag} *`)).
- join(", ");
-
-// Note: isPageContext implementation could have actually used SelectorMatch reader,
-// but old implementation was also checked for collapsed selection there for to keep
-// the behavior same we end up implementing a new reader.
-parsers["reader/isPage()"] = constant(node =>
- node.ownerDocument.defaultView.getSelection().isCollapsed &&
- !node.matches(nonPageSelector));
-
-// Reads `true` if node is in an iframe otherwise returns true.
-parsers["reader/isFrame()"] = constant(node =>
- !!node.ownerDocument.defaultView.frameElement);
-
-parsers["reader/isEditable()"] = constant(node => {
- const selection = getInputSelection(node);
- return selection ? !node.readOnly && !node.disabled : node.isContentEditable;
-});
-
-
-// TODO: Add some reader to read out tab id.
-
-const onReadersUpdate = message => {
- each(([id, descriptor]) => {
- if (descriptor) {
- readers[id] = parse(descriptor);
- }
- else {
- delete readers[id];
- }
- }, pairs(message.data));
-};
-exports.onReadersUpdate = onReadersUpdate;
-
-
-const onContextMenu = event => {
- if (!event.defaultPrevented) {
- const manager = nodeToMessageManager(event.target);
- manager.sendSyncMessage("sdk/context-menu/read", read(event.target), readers);
- }
-};
-exports.onContextMenu = onContextMenu;
-
-
-const onContentFrame = (frame) => {
- // Listen for contextmenu events in on this frame.
- frame.addEventListener("contextmenu", onContextMenu);
- // Listen to registered reader changes and update registry.
- frame.addMessageListener("sdk/context-menu/readers", onReadersUpdate);
-
- // Request table of readers (if this is loaded in a new process some table
- // changes may be missed, this is way to sync up).
- frame.sendAsyncMessage("sdk/context-menu/readers?");
-};
-exports.onContentFrame = onContentFrame;
diff --git a/addon-sdk/source/lib/framescript/manager.js b/addon-sdk/source/lib/framescript/manager.js
deleted file mode 100644
index 1f261e1fa..000000000
--- a/addon-sdk/source/lib/framescript/manager.js
+++ /dev/null
@@ -1,26 +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": "unstable"
-};
-
-const mime = "application/javascript";
-const requireURI = module.uri.replace("framescript/manager.js",
- "toolkit/require.js");
-
-const requireLoadURI = `data:${mime},this["Components"].utils.import("${requireURI}")`
-
-// Loads module with given `id` into given `messageManager` via shared module loader. If `init`
-// string is passed, will call module export with that name and pass frame script environment
-// of the `messageManager` into it. Since module will load only once per process (which is
-// once for chrome proces & second for content process) it is useful to have an init function
-// to setup event listeners on each content frame.
-const loadModule = (messageManager, id, allowDelayed, init) => {
- const moduleLoadURI = `${requireLoadURI}.require("${id}")`
- const uri = init ? `${moduleLoadURI}.${init}(this)` : moduleLoadURI;
- messageManager.loadFrameScript(uri, allowDelayed);
-};
-exports.loadModule = loadModule;
diff --git a/addon-sdk/source/lib/framescript/util.js b/addon-sdk/source/lib/framescript/util.js
deleted file mode 100644
index fb6834608..000000000
--- a/addon-sdk/source/lib/framescript/util.js
+++ /dev/null
@@ -1,25 +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": "unstable"
-};
-
-
-const { Ci } = require("chrome");
-
-const windowToMessageManager = window =>
- window.
- QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIDocShell).
- sameTypeRootTreeItem.
- QueryInterface(Ci.nsIDocShell).
- QueryInterface(Ci.nsIInterfaceRequestor).
- getInterface(Ci.nsIContentFrameMessageManager);
-exports.windowToMessageManager = windowToMessageManager;
-
-const nodeToMessageManager = node =>
- windowToMessageManager(node.ownerDocument.defaultView);
-exports.nodeToMessageManager = nodeToMessageManager;