summaryrefslogtreecommitdiffstats
path: root/addon-sdk/source/lib/sdk/ui/frame
diff options
context:
space:
mode:
authorMatt A. Tobin <email@mattatobin.com>2018-02-09 06:46:43 -0500
committerMatt A. Tobin <email@mattatobin.com>2018-02-09 06:46:43 -0500
commitac46df8daea09899ce30dc8fd70986e258c746bf (patch)
tree2750d3125fc253fd5b0671e4bd268eff1fd97296 /addon-sdk/source/lib/sdk/ui/frame
parent8cecf8d5208f3945b35f879bba3015bb1a11bec6 (diff)
downloadUXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.gz
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.lz
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.tar.xz
UXP-ac46df8daea09899ce30dc8fd70986e258c746bf.zip
Move Add-on SDK source to toolkit/jetpack
Diffstat (limited to 'addon-sdk/source/lib/sdk/ui/frame')
-rw-r--r--addon-sdk/source/lib/sdk/ui/frame/model.js154
-rw-r--r--addon-sdk/source/lib/sdk/ui/frame/view.html18
-rw-r--r--addon-sdk/source/lib/sdk/ui/frame/view.js150
3 files changed, 0 insertions, 322 deletions
diff --git a/addon-sdk/source/lib/sdk/ui/frame/model.js b/addon-sdk/source/lib/sdk/ui/frame/model.js
deleted file mode 100644
index 627310874..000000000
--- a/addon-sdk/source/lib/sdk/ui/frame/model.js
+++ /dev/null
@@ -1,154 +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",
- "engines": {
- "Firefox": "> 28"
- }
-};
-
-const { Class } = require("../../core/heritage");
-const { EventTarget } = require("../../event/target");
-const { emit, off, setListeners } = require("../../event/core");
-const { Reactor, foldp, send, merges } = require("../../event/utils");
-const { Disposable } = require("../../core/disposable");
-const { OutputPort } = require("../../output/system");
-const { InputPort } = require("../../input/system");
-const { identify } = require("../id");
-const { pairs, object, map, each } = require("../../util/sequence");
-const { patch, diff } = require("diffpatcher/index");
-const { isLocalURL } = require("../../url");
-const { compose } = require("../../lang/functional");
-const { contract } = require("../../util/contract");
-const { id: addonID, data: { url: resolve }} = require("../../self");
-const { Frames } = require("../../input/frame");
-
-
-const output = new OutputPort({ id: "frame-change" });
-const mailbox = new OutputPort({ id: "frame-mailbox" });
-const input = Frames;
-
-
-const makeID = url =>
- ("frame-" + addonID + "-" + url).
- split("/").join("-").
- split(".").join("-").
- replace(/[^A-Za-z0-9_\-]/g, "");
-
-const validate = contract({
- name: {
- is: ["string", "undefined"],
- ok: x => /^[a-z][a-z0-9-_]+$/i.test(x),
- msg: "The `option.name` must be a valid alphanumeric string (hyphens and " +
- "underscores are allowed) starting with letter."
- },
- url: {
- map: x => x.toString(),
- is: ["string"],
- ok: x => isLocalURL(x),
- msg: "The `options.url` must be a valid local URI."
- }
-});
-
-const Source = function({id, ownerID}) {
- this.id = id;
- this.ownerID = ownerID;
-};
-Source.postMessage = ({id, ownerID}, data, origin) => {
- send(mailbox, object([id, {
- inbox: {
- target: {id: id, ownerID: ownerID},
- timeStamp: Date.now(),
- data: data,
- origin: origin
- }
- }]));
-};
-Source.prototype.postMessage = function(data, origin) {
- Source.postMessage(this, data, origin);
-};
-
-const Message = function({type, data, source, origin, timeStamp}) {
- this.type = type;
- this.data = data;
- this.origin = origin;
- this.timeStamp = timeStamp;
- this.source = new Source(source);
-};
-
-
-const frames = new Map();
-const sources = new Map();
-
-const Frame = Class({
- extends: EventTarget,
- implements: [Disposable, Source],
- initialize: function(params={}) {
- const options = validate(params);
- const id = makeID(options.name || options.url);
-
- if (frames.has(id))
- throw Error("Frame with this id already exists: " + id);
-
- const initial = { id: id, url: resolve(options.url) };
- this.id = id;
-
- setListeners(this, params);
-
- frames.set(this.id, this);
-
- send(output, object([id, initial]));
- },
- get url() {
- const state = reactor.value[this.id];
- return state && state.url;
- },
- destroy: function() {
- send(output, object([this.id, null]));
- frames.delete(this.id);
- off(this);
- },
- // `JSON.stringify` serializes objects based of the return
- // value of this method. For convinienc we provide this method
- // to serialize actual state data.
- toJSON: function() {
- return { id: this.id, url: this.url };
- }
-});
-identify.define(Frame, frame => frame.id);
-
-exports.Frame = Frame;
-
-const reactor = new Reactor({
- onStep: (present, past) => {
- const delta = diff(past, present);
-
- each(([id, update]) => {
- const frame = frames.get(id);
- if (update) {
- if (!past[id])
- emit(frame, "register");
-
- if (update.outbox)
- emit(frame, "message", new Message(present[id].outbox));
-
- each(([ownerID, state]) => {
- const readyState = state ? state.readyState : "detach";
- const type = readyState === "loading" ? "attach" :
- readyState === "interactive" ? "ready" :
- readyState === "complete" ? "load" :
- readyState;
-
- // TODO: Cache `Source` instances somewhere to preserve
- // identity.
- emit(frame, type, {type: type,
- source: new Source({id: id, ownerID: ownerID})});
- }, pairs(update.owners));
- }
- }, pairs(delta));
- }
-});
-reactor.run(input);
diff --git a/addon-sdk/source/lib/sdk/ui/frame/view.html b/addon-sdk/source/lib/sdk/ui/frame/view.html
deleted file mode 100644
index 2a405b583..000000000
--- a/addon-sdk/source/lib/sdk/ui/frame/view.html
+++ /dev/null
@@ -1,18 +0,0 @@
-<!DOCTYPE html>
-<html>
- <head>
- <script>
- // HACK: This is not an ideal way to deliver chrome messages
- // to an inner frame content but seems only way that would
- // make `event.source` this (outer frame) window.
- window.onmessage = function(event) {
- var frame = document.querySelector("iframe");
- var content = frame.contentWindow;
- // If message is posted from chrome it has no `event.source`.
- if (event.source === null)
- content.postMessage(event.data, "*");
- };
- </script>
- </head>
- <body style="overflow: hidden"></body>
-</html>
diff --git a/addon-sdk/source/lib/sdk/ui/frame/view.js b/addon-sdk/source/lib/sdk/ui/frame/view.js
deleted file mode 100644
index 2eb4df2b7..000000000
--- a/addon-sdk/source/lib/sdk/ui/frame/view.js
+++ /dev/null
@@ -1,150 +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",
- "engines": {
- "Firefox": "> 28"
- }
-};
-
-const { Cu, Ci } = require("chrome");
-const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
-const { subscribe, send, Reactor, foldp, lift, merges, keepIf } = require("../../event/utils");
-const { InputPort } = require("../../input/system");
-const { OutputPort } = require("../../output/system");
-const { LastClosed } = require("../../input/browser");
-const { pairs, keys, object, each } = require("../../util/sequence");
-const { curry, compose } = require("../../lang/functional");
-const { getFrameElement, getOuterId,
- getByOuterId, getOwnerBrowserWindow } = require("../../window/utils");
-const { patch, diff } = require("diffpatcher/index");
-const { encode } = require("../../base64");
-const { Frames } = require("../../input/frame");
-
-const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
-const HTML_NS = "http://www.w3.org/1999/xhtml";
-const OUTER_FRAME_URI = module.uri.replace(/\.js$/, ".html");
-
-const mailbox = new OutputPort({ id: "frame-mailbox" });
-
-const frameID = frame => frame.id.replace("outer-", "");
-const windowID = compose(getOuterId, getOwnerBrowserWindow);
-
-const getOuterFrame = (windowID, frameID) =>
- getByOuterId(windowID).document.getElementById("outer-" + frameID);
-
-const listener = ({target, source, data, origin, timeStamp}) => {
- // And sent received message to outbox so that frame API model
- // will deal with it.
- if (source && source !== target) {
- const frame = getFrameElement(target);
- const id = frameID(frame);
- send(mailbox, object([id, {
- outbox: {type: "message",
- source: {id: id, ownerID: windowID(frame)},
- data: data,
- origin: origin,
- timeStamp: timeStamp}}]));
- }
-};
-
-// Utility function used to create frame with a given `state` and
-// inject it into given `window`.
-const registerFrame = ({id, url}) => {
- CustomizableUI.createWidget({
- id: id,
- type: "custom",
- removable: true,
- onBuild: document => {
- let view = document.createElementNS(XUL_NS, "toolbaritem");
- view.setAttribute("id", id);
- view.setAttribute("flex", 2);
-
- let outerFrame = document.createElementNS(XUL_NS, "iframe");
- outerFrame.setAttribute("src", OUTER_FRAME_URI);
- outerFrame.setAttribute("id", "outer-" + id);
- outerFrame.setAttribute("data-is-sdk-outer-frame", true);
- outerFrame.setAttribute("type", "content");
- outerFrame.setAttribute("transparent", true);
- outerFrame.setAttribute("flex", 2);
- outerFrame.setAttribute("style", "overflow: hidden;");
- outerFrame.setAttribute("scrolling", "no");
- outerFrame.setAttribute("disablehistory", true);
- outerFrame.setAttribute("seamless", "seamless");
- outerFrame.addEventListener("load", function onload() {
- outerFrame.removeEventListener("load", onload, true);
-
- let doc = outerFrame.contentDocument;
-
- let innerFrame = doc.createElementNS(HTML_NS, "iframe");
- innerFrame.setAttribute("id", id);
- innerFrame.setAttribute("src", url);
- innerFrame.setAttribute("seamless", "seamless");
- innerFrame.setAttribute("sandbox", "allow-scripts");
- innerFrame.setAttribute("scrolling", "no");
- innerFrame.setAttribute("data-is-sdk-inner-frame", true);
- innerFrame.setAttribute("style", [ "border:none",
- "position:absolute", "width:100%", "top: 0",
- "left: 0", "overflow: hidden"].join(";"));
-
- doc.body.appendChild(innerFrame);
- }, true);
-
- view.appendChild(outerFrame);
-
- return view;
- }
- });
-};
-
-const unregisterFrame = CustomizableUI.destroyWidget;
-
-const deliverMessage = curry((frameID, data, windowID) => {
- const frame = getOuterFrame(windowID, frameID);
- const content = frame && frame.contentWindow;
-
- if (content)
- content.postMessage(data, content.location.origin);
-});
-
-const updateFrame = (id, {inbox, owners}, present) => {
- if (inbox) {
- const { data, target:{ownerID}, source } = present[id].inbox;
- if (ownerID)
- deliverMessage(id, data, ownerID);
- else
- each(deliverMessage(id, data), keys(present[id].owners));
- }
-
- each(setupView(id), pairs(owners));
-};
-
-const setupView = curry((frameID, [windowID, state]) => {
- if (state && state.readyState === "loading") {
- const frame = getOuterFrame(windowID, frameID);
- // Setup a message listener on contentWindow.
- frame.contentWindow.addEventListener("message", listener);
- }
-});
-
-
-const reactor = new Reactor({
- onStep: (present, past) => {
- const delta = diff(past, present);
-
- // Apply frame changes
- each(([id, update]) => {
- if (update === null)
- unregisterFrame(id);
- else if (past[id])
- updateFrame(id, update, present);
- else
- registerFrame(update);
- }, pairs(delta));
- },
- onEnd: state => each(unregisterFrame, keys(state))
-});
-reactor.run(Frames);