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.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 'use strict';
6 module.metadata = {
7 'stability': 'experimental',
8 'engines': {
9 'Firefox': '> 28'
10 }
11 };
13 const { Cu } = require('chrome');
14 const { on, off, emit } = require('../../event/core');
16 const { data } = require('sdk/self');
18 const { isObject } = require('../../lang/type');
20 const { getMostRecentBrowserWindow } = require('../../window/utils');
21 const { ignoreWindow } = require('../../private-browsing/utils');
22 const { CustomizableUI } = Cu.import('resource:///modules/CustomizableUI.jsm', {});
23 const { AREA_PANEL, AREA_NAVBAR } = CustomizableUI;
25 const { events: viewEvents } = require('./view/events');
27 const XUL_NS = 'http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul';
29 const views = new Map();
30 const customizedWindows = new WeakMap();
32 const buttonListener = {
33 onCustomizeStart: window => {
34 for (let [id, view] of views) {
35 setIcon(id, window, view.icon);
36 setLabel(id, window, view.label);
37 }
39 customizedWindows.set(window, true);
40 },
41 onCustomizeEnd: window => {
42 customizedWindows.delete(window);
44 for (let [id, ] of views) {
45 let placement = CustomizableUI.getPlacementOfWidget(id);
47 if (placement)
48 emit(viewEvents, 'data', { type: 'update', target: id, window: window });
49 }
50 },
51 onWidgetAfterDOMChange: (node, nextNode, container) => {
52 let { id } = node;
53 let view = views.get(id);
54 let window = node.ownerDocument.defaultView;
56 if (view) {
57 emit(viewEvents, 'data', { type: 'update', target: id, window: window });
58 }
59 }
60 };
62 CustomizableUI.addListener(buttonListener);
64 require('../../system/unload').when( _ =>
65 CustomizableUI.removeListener(buttonListener)
66 );
68 function getNode(id, window) {
69 return !views.has(id) || ignoreWindow(window)
70 ? null
71 : CustomizableUI.getWidget(id).forWindow(window).node
72 };
74 function isInToolbar(id) {
75 let placement = CustomizableUI.getPlacementOfWidget(id);
77 return placement && CustomizableUI.getAreaType(placement.area) === 'toolbar';
78 }
81 function getImage(icon, isInToolbar, pixelRatio) {
82 let targetSize = (isInToolbar ? 18 : 32) * pixelRatio;
83 let bestSize = 0;
84 let image = icon;
86 if (isObject(icon)) {
87 for (let size of Object.keys(icon)) {
88 size = +size;
89 let offset = targetSize - size;
91 if (offset === 0) {
92 bestSize = size;
93 break;
94 }
96 let delta = Math.abs(offset) - Math.abs(targetSize - bestSize);
98 if (delta < 0)
99 bestSize = size;
100 }
102 image = icon[bestSize];
103 }
105 if (image.indexOf('./') === 0)
106 return data.url(image.substr(2));
108 return image;
109 }
111 function nodeFor(id, window=getMostRecentBrowserWindow()) {
112 return customizedWindows.has(window) ? null : getNode(id, window);
113 };
114 exports.nodeFor = nodeFor;
116 function create(options) {
117 let { id, label, icon, type } = options;
119 if (views.has(id))
120 throw new Error('The ID "' + id + '" seems already used.');
122 CustomizableUI.createWidget({
123 id: id,
124 type: 'custom',
125 removable: true,
126 defaultArea: AREA_NAVBAR,
127 allowedAreas: [ AREA_PANEL, AREA_NAVBAR ],
129 onBuild: function(document) {
130 let window = document.defaultView;
132 let node = document.createElementNS(XUL_NS, 'toolbarbutton');
134 let image = getImage(icon, true, window.devicePixelRatio);
136 if (ignoreWindow(window))
137 node.style.display = 'none';
139 node.setAttribute('id', this.id);
140 node.setAttribute('class', 'toolbarbutton-1 chromeclass-toolbar-additional');
141 node.setAttribute('type', type);
142 node.setAttribute('label', label);
143 node.setAttribute('tooltiptext', label);
144 node.setAttribute('image', image);
145 node.setAttribute('sdk-button', 'true');
147 views.set(id, {
148 area: this.currentArea,
149 icon: icon,
150 label: label
151 });
153 node.addEventListener('command', function(event) {
154 if (views.has(id)) {
155 emit(viewEvents, 'data', {
156 type: 'click',
157 target: id,
158 window: event.view,
159 checked: node.checked
160 });
161 }
162 });
164 return node;
165 }
166 });
167 };
168 exports.create = create;
170 function dispose(id) {
171 if (!views.has(id)) return;
173 views.delete(id);
174 CustomizableUI.destroyWidget(id);
175 }
176 exports.dispose = dispose;
178 function setIcon(id, window, icon) {
179 let node = getNode(id, window);
181 if (node) {
182 icon = customizedWindows.has(window) ? views.get(id).icon : icon;
183 let image = getImage(icon, isInToolbar(id), window.devicePixelRatio);
185 node.setAttribute('image', image);
186 }
187 }
188 exports.setIcon = setIcon;
190 function setLabel(id, window, label) {
191 let node = nodeFor(id, window);
193 if (node) {
194 node.setAttribute('label', label);
195 node.setAttribute('tooltiptext', label);
196 }
197 }
198 exports.setLabel = setLabel;
200 function setDisabled(id, window, disabled) {
201 let node = nodeFor(id, window);
203 if (node)
204 node.disabled = disabled;
205 }
206 exports.setDisabled = setDisabled;
208 function setChecked(id, window, checked) {
209 let node = nodeFor(id, window);
211 if (node)
212 node.checked = checked;
213 }
214 exports.setChecked = setChecked;
216 function click(id) {
217 let node = nodeFor(id);
219 if (node)
220 node.click();
221 }
222 exports.click = click;