Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | "use strict"; |
michael@0 | 5 | |
michael@0 | 6 | module.metadata = { |
michael@0 | 7 | "stability": "experimental", |
michael@0 | 8 | "engines": { |
michael@0 | 9 | "Firefox": "> 28" |
michael@0 | 10 | } |
michael@0 | 11 | }; |
michael@0 | 12 | |
michael@0 | 13 | const { Cu, Ci } = require("chrome"); |
michael@0 | 14 | const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {}); |
michael@0 | 15 | const { subscribe, send, Reactor, foldp, lift, merges, keepIf } = require("../../event/utils"); |
michael@0 | 16 | const { InputPort } = require("../../input/system"); |
michael@0 | 17 | const { OutputPort } = require("../../output/system"); |
michael@0 | 18 | const { LastClosed } = require("../../input/browser"); |
michael@0 | 19 | const { pairs, keys, object, each } = require("../../util/sequence"); |
michael@0 | 20 | const { curry, compose } = require("../../lang/functional"); |
michael@0 | 21 | const { getFrameElement, getOuterId, |
michael@0 | 22 | getByOuterId, getOwnerBrowserWindow } = require("../../window/utils"); |
michael@0 | 23 | const { patch, diff } = require("diffpatcher/index"); |
michael@0 | 24 | const { encode } = require("../../base64"); |
michael@0 | 25 | const { Frames } = require("../../input/frame"); |
michael@0 | 26 | |
michael@0 | 27 | const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; |
michael@0 | 28 | const HTML_NS = "http://www.w3.org/1999/xhtml"; |
michael@0 | 29 | const OUTER_FRAME_URI = module.uri.replace(/\.js$/, ".html"); |
michael@0 | 30 | |
michael@0 | 31 | const mailbox = new OutputPort({ id: "frame-mailbox" }); |
michael@0 | 32 | |
michael@0 | 33 | const frameID = frame => frame.id.replace("outer-", ""); |
michael@0 | 34 | const windowID = compose(getOuterId, getOwnerBrowserWindow); |
michael@0 | 35 | |
michael@0 | 36 | const getOuterFrame = (windowID, frameID) => |
michael@0 | 37 | getByOuterId(windowID).document.getElementById("outer-" + frameID); |
michael@0 | 38 | |
michael@0 | 39 | const listener = ({target, source, data, origin, timeStamp}) => { |
michael@0 | 40 | // And sent received message to outbox so that frame API model |
michael@0 | 41 | // will deal with it. |
michael@0 | 42 | if (source && source !== target) { |
michael@0 | 43 | const frame = getFrameElement(target); |
michael@0 | 44 | const id = frameID(frame); |
michael@0 | 45 | send(mailbox, object([id, { |
michael@0 | 46 | outbox: {type: "message", |
michael@0 | 47 | source: {id: id, ownerID: windowID(frame)}, |
michael@0 | 48 | data: data, |
michael@0 | 49 | origin: origin, |
michael@0 | 50 | timeStamp: timeStamp}}])); |
michael@0 | 51 | } |
michael@0 | 52 | }; |
michael@0 | 53 | |
michael@0 | 54 | // Utility function used to create frame with a given `state` and |
michael@0 | 55 | // inject it into given `window`. |
michael@0 | 56 | const registerFrame = ({id, url}) => { |
michael@0 | 57 | CustomizableUI.createWidget({ |
michael@0 | 58 | id: id, |
michael@0 | 59 | type: "custom", |
michael@0 | 60 | removable: true, |
michael@0 | 61 | onBuild: document => { |
michael@0 | 62 | let view = document.createElementNS(XUL_NS, "toolbaritem"); |
michael@0 | 63 | view.setAttribute("id", id); |
michael@0 | 64 | view.setAttribute("flex", 2); |
michael@0 | 65 | |
michael@0 | 66 | let innerFrame = document.createElementNS(HTML_NS, "iframe"); |
michael@0 | 67 | innerFrame.setAttribute("id", id); |
michael@0 | 68 | innerFrame.setAttribute("src", url); |
michael@0 | 69 | innerFrame.setAttribute("seamless", "seamless"); |
michael@0 | 70 | innerFrame.setAttribute("sandbox", "allow-scripts"); |
michael@0 | 71 | innerFrame.setAttribute("scrolling", "no"); |
michael@0 | 72 | innerFrame.setAttribute("data-is-sdk-inner-frame", true); |
michael@0 | 73 | innerFrame.setAttribute("style", [ "border:none", |
michael@0 | 74 | "position:absolute", "width:100%", "top: 0", |
michael@0 | 75 | "left: 0", "overflow: hidden"].join(";")); |
michael@0 | 76 | |
michael@0 | 77 | let outerFrame = document.createElementNS(XUL_NS, "iframe"); |
michael@0 | 78 | outerFrame.setAttribute("src", OUTER_FRAME_URI + "#" + |
michael@0 | 79 | encode(innerFrame.outerHTML)); |
michael@0 | 80 | outerFrame.setAttribute("id", "outer-" + id); |
michael@0 | 81 | outerFrame.setAttribute("data-is-sdk-outer-frame", true); |
michael@0 | 82 | outerFrame.setAttribute("type", "content"); |
michael@0 | 83 | outerFrame.setAttribute("transparent", true); |
michael@0 | 84 | outerFrame.setAttribute("flex", 2); |
michael@0 | 85 | outerFrame.setAttribute("style", "overflow: hidden;"); |
michael@0 | 86 | outerFrame.setAttribute("scrolling", "no"); |
michael@0 | 87 | outerFrame.setAttribute("disablehistory", true); |
michael@0 | 88 | outerFrame.setAttribute("seamless", "seamless"); |
michael@0 | 89 | |
michael@0 | 90 | view.appendChild(outerFrame); |
michael@0 | 91 | |
michael@0 | 92 | return view; |
michael@0 | 93 | } |
michael@0 | 94 | }); |
michael@0 | 95 | }; |
michael@0 | 96 | |
michael@0 | 97 | const unregisterFrame = CustomizableUI.destroyWidget; |
michael@0 | 98 | |
michael@0 | 99 | const deliverMessage = curry((frameID, data, windowID) => { |
michael@0 | 100 | const frame = getOuterFrame(windowID, frameID); |
michael@0 | 101 | const content = frame && frame.contentWindow; |
michael@0 | 102 | |
michael@0 | 103 | if (content) |
michael@0 | 104 | content.postMessage(data, content.location.origin); |
michael@0 | 105 | }); |
michael@0 | 106 | |
michael@0 | 107 | const updateFrame = (id, {inbox, owners}, present) => { |
michael@0 | 108 | if (inbox) { |
michael@0 | 109 | const { data, target:{ownerID}, source } = present[id].inbox; |
michael@0 | 110 | if (ownerID) |
michael@0 | 111 | deliverMessage(id, data, ownerID); |
michael@0 | 112 | else |
michael@0 | 113 | each(deliverMessage(id, data), keys(present[id].owners)); |
michael@0 | 114 | } |
michael@0 | 115 | |
michael@0 | 116 | each(setupView(id), pairs(owners)); |
michael@0 | 117 | }; |
michael@0 | 118 | |
michael@0 | 119 | const setupView = curry((frameID, [windowID, state]) => { |
michael@0 | 120 | if (state && state.readyState === "loading") { |
michael@0 | 121 | const frame = getOuterFrame(windowID, frameID); |
michael@0 | 122 | // Setup a message listener on contentWindow. |
michael@0 | 123 | frame.contentWindow.addEventListener("message", listener); |
michael@0 | 124 | } |
michael@0 | 125 | }); |
michael@0 | 126 | |
michael@0 | 127 | |
michael@0 | 128 | const reactor = new Reactor({ |
michael@0 | 129 | onStep: (present, past) => { |
michael@0 | 130 | const delta = diff(past, present); |
michael@0 | 131 | |
michael@0 | 132 | // Apply frame changes |
michael@0 | 133 | each(([id, update]) => { |
michael@0 | 134 | if (update === null) |
michael@0 | 135 | unregisterFrame(id); |
michael@0 | 136 | else if (past[id]) |
michael@0 | 137 | updateFrame(id, update, present); |
michael@0 | 138 | else |
michael@0 | 139 | registerFrame(update); |
michael@0 | 140 | }, pairs(delta)); |
michael@0 | 141 | }, |
michael@0 | 142 | onEnd: state => each(unregisterFrame, keys(state)) |
michael@0 | 143 | }); |
michael@0 | 144 | reactor.run(Frames); |