1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/browser/components/customizableui/content/toolbar.xml Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,615 @@ 1.4 +<?xml version="1.0"?> 1.5 +<!-- This Source Code Form is subject to the terms of the Mozilla Public 1.6 + - License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + - file, You can obtain one at http://mozilla.org/MPL/2.0/. --> 1.8 + 1.9 +<bindings id="browserToolbarBindings" 1.10 + xmlns="http://www.mozilla.org/xbl" 1.11 + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" 1.12 + xmlns:xbl="http://www.mozilla.org/xbl"> 1.13 + 1.14 + <binding id="toolbar" role="xul:toolbar"> 1.15 + <resources> 1.16 + <stylesheet src="chrome://global/skin/toolbar.css"/> 1.17 + </resources> 1.18 + <implementation> 1.19 + <field name="overflowedDuringConstruction">null</field> 1.20 + 1.21 + <constructor><![CDATA[ 1.22 + let scope = {}; 1.23 + Cu.import("resource:///modules/CustomizableUI.jsm", scope); 1.24 + // Add an early overflow event listener that will mark if the 1.25 + // toolbar overflowed during construction. 1.26 + if (scope.CustomizableUI.isAreaOverflowable(this.id)) { 1.27 + this.addEventListener("overflow", this); 1.28 + this.addEventListener("underflow", this); 1.29 + } 1.30 + 1.31 + if (document.readyState == "complete") { 1.32 + this._init(); 1.33 + } else { 1.34 + // Need to wait until XUL overlays are loaded. See bug 554279. 1.35 + let self = this; 1.36 + document.addEventListener("readystatechange", function onReadyStateChange() { 1.37 + if (document.readyState != "complete") 1.38 + return; 1.39 + document.removeEventListener("readystatechange", onReadyStateChange, false); 1.40 + self._init(); 1.41 + }, false); 1.42 + } 1.43 + ]]></constructor> 1.44 + 1.45 + <method name="_init"> 1.46 + <body><![CDATA[ 1.47 + let scope = {}; 1.48 + Cu.import("resource:///modules/CustomizableUI.jsm", scope); 1.49 + let CustomizableUI = scope.CustomizableUI; 1.50 + 1.51 + // Bug 989289: Forcibly set the now unsupported "mode" and "iconsize" 1.52 + // attributes, just in case they accidentally get restored from 1.53 + // persistence from a user that's been upgrading and downgrading. 1.54 + if (CustomizableUI.isBuiltinToolbar(this.id)) { 1.55 + const kAttributes = new Map([["mode", "icons"], ["iconsize", "small"]]); 1.56 + for (let [attribute, value] of kAttributes) { 1.57 + if (this.getAttribute(attribute) != value) { 1.58 + this.setAttribute(attribute, value); 1.59 + document.persist(this.id, attribute); 1.60 + } 1.61 + if (this.toolbox) { 1.62 + if (this.toolbox.getAttribute(attribute) != value) { 1.63 + this.toolbox.setAttribute(attribute, value); 1.64 + document.persist(this.toolbox.id, attribute); 1.65 + } 1.66 + } 1.67 + } 1.68 + } 1.69 + 1.70 + // Searching for the toolbox palette in the toolbar binding because 1.71 + // toolbars are constructed first. 1.72 + let toolbox = this.toolbox; 1.73 + if (toolbox && !toolbox.palette) { 1.74 + for (let node of toolbox.children) { 1.75 + if (node.localName == "toolbarpalette") { 1.76 + // Hold on to the palette but remove it from the document. 1.77 + toolbox.palette = node; 1.78 + toolbox.removeChild(node); 1.79 + break; 1.80 + } 1.81 + } 1.82 + } 1.83 + 1.84 + // pass the current set of children for comparison with placements: 1.85 + let children = [node.id for (node of this.childNodes) 1.86 + if (node.getAttribute("skipintoolbarset") != "true" && node.id)]; 1.87 + CustomizableUI.registerToolbarNode(this, children); 1.88 + ]]></body> 1.89 + </method> 1.90 + 1.91 + <method name="handleEvent"> 1.92 + <parameter name="aEvent"/> 1.93 + <body><![CDATA[ 1.94 + if (aEvent.type == "overflow" && aEvent.detail > 0) { 1.95 + if (this.overflowable && this.overflowable.initialized) { 1.96 + this.overflowable.onOverflow(aEvent); 1.97 + } else { 1.98 + this.overflowedDuringConstruction = aEvent; 1.99 + } 1.100 + } else if (aEvent.type == "underflow" && aEvent.detail > 0) { 1.101 + this.overflowedDuringConstruction = null; 1.102 + } 1.103 + ]]></body> 1.104 + </method> 1.105 + 1.106 + <method name="insertItem"> 1.107 + <parameter name="aId"/> 1.108 + <parameter name="aBeforeElt"/> 1.109 + <parameter name="aWrapper"/> 1.110 + <body><![CDATA[ 1.111 + if (aWrapper) { 1.112 + Cu.reportError("Can't insert " + aId + ": using insertItem " + 1.113 + "no longer supports wrapper elements."); 1.114 + return null; 1.115 + } 1.116 + 1.117 + // Hack, the customizable UI code makes this be the last position 1.118 + let pos = null; 1.119 + if (aBeforeElt) { 1.120 + let beforeInfo = CustomizableUI.getPlacementOfWidget(aBeforeElt.id); 1.121 + if (beforeInfo.area != this.id) { 1.122 + Cu.reportError("Can't insert " + aId + " before " + 1.123 + aBeforeElt.id + " which isn't in this area (" + 1.124 + this.id + ")."); 1.125 + return null; 1.126 + } 1.127 + pos = beforeInfo.position; 1.128 + } 1.129 + 1.130 + CustomizableUI.addWidgetToArea(aId, this.id, pos); 1.131 + return this.ownerDocument.getElementById(aId); 1.132 + ]]></body> 1.133 + </method> 1.134 + 1.135 + <property name="toolbarName" 1.136 + onget="return this.getAttribute('toolbarname');" 1.137 + onset="this.setAttribute('toolbarname', val); return val;"/> 1.138 + 1.139 + <property name="customizationTarget" readonly="true"> 1.140 + <getter><![CDATA[ 1.141 + if (this._customizationTarget) 1.142 + return this._customizationTarget; 1.143 + 1.144 + let id = this.getAttribute("customizationtarget"); 1.145 + if (id) 1.146 + this._customizationTarget = document.getElementById(id); 1.147 + 1.148 + if (this._customizationTarget) 1.149 + this._customizationTarget.insertItem = this.insertItem.bind(this); 1.150 + else 1.151 + this._customizationTarget = this; 1.152 + 1.153 + return this._customizationTarget; 1.154 + ]]></getter> 1.155 + </property> 1.156 + 1.157 + <property name="toolbox" readonly="true"> 1.158 + <getter><![CDATA[ 1.159 + if (this._toolbox) 1.160 + return this._toolbox; 1.161 + 1.162 + let toolboxId = this.getAttribute("toolboxid"); 1.163 + if (toolboxId) { 1.164 + let toolbox = document.getElementById(toolboxId); 1.165 + if (toolbox) { 1.166 + if (toolbox.externalToolbars.indexOf(this) == -1) 1.167 + toolbox.externalToolbars.push(this); 1.168 + 1.169 + this._toolbox = toolbox; 1.170 + } 1.171 + } 1.172 + 1.173 + if (!this._toolbox && this.parentNode && 1.174 + this.parentNode.localName == "toolbox") { 1.175 + this._toolbox = this.parentNode; 1.176 + } 1.177 + 1.178 + return this._toolbox; 1.179 + ]]></getter> 1.180 + </property> 1.181 + 1.182 + <property name="currentSet"> 1.183 + <getter><![CDATA[ 1.184 + let currentWidgets = new Set(); 1.185 + for (let node of this.customizationTarget.children) { 1.186 + let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node; 1.187 + if (realNode.getAttribute("skipintoolbarset") != "true") { 1.188 + currentWidgets.add(realNode.id); 1.189 + } 1.190 + } 1.191 + if (this.getAttribute("overflowing") == "true") { 1.192 + let overflowTarget = this.getAttribute("overflowtarget"); 1.193 + let overflowList = this.ownerDocument.getElementById(overflowTarget); 1.194 + for (let node of overflowList.children) { 1.195 + let realNode = node.localName == "toolbarpaletteitem" ? node.firstChild : node; 1.196 + if (realNode.getAttribute("skipintoolbarset") != "true") { 1.197 + currentWidgets.add(realNode.id); 1.198 + } 1.199 + } 1.200 + } 1.201 + let orderedPlacements = CustomizableUI.getWidgetIdsInArea(this.id); 1.202 + return orderedPlacements.filter((x) => currentWidgets.has(x)).join(','); 1.203 + ]]></getter> 1.204 + <setter><![CDATA[ 1.205 + // Get list of new and old ids: 1.206 + let newVal = (val || '').split(',').filter(x => x); 1.207 + let oldIds = CustomizableUI.getWidgetIdsInArea(this.id); 1.208 + 1.209 + // Get a list of items only in the new list 1.210 + let newIds = [id for (id of newVal) if (oldIds.indexOf(id) == -1)]; 1.211 + CustomizableUI.beginBatchUpdate(); 1.212 + try { 1.213 + for (let newId of newIds) { 1.214 + oldIds = CustomizableUI.getWidgetIdsInArea(this.id); 1.215 + let nextId = newId; 1.216 + let pos; 1.217 + do { 1.218 + // Get the next item 1.219 + nextId = newVal[newVal.indexOf(nextId) + 1]; 1.220 + // Figure out where it is in the old list 1.221 + pos = oldIds.indexOf(nextId); 1.222 + // If it's not in the old list, repeat: 1.223 + } while (pos == -1 && nextId); 1.224 + if (pos == -1) { 1.225 + pos = null; // We didn't find anything, insert at the end 1.226 + } 1.227 + CustomizableUI.addWidgetToArea(newId, this.id, pos); 1.228 + } 1.229 + 1.230 + let currentIds = this.currentSet.split(','); 1.231 + let removedIds = [id for (id of currentIds) if (newIds.indexOf(id) == -1 && newVal.indexOf(id) == -1)]; 1.232 + for (let removedId of removedIds) { 1.233 + CustomizableUI.removeWidgetFromArea(removedId); 1.234 + } 1.235 + } finally { 1.236 + CustomizableUI.endBatchUpdate(); 1.237 + } 1.238 + ]]></setter> 1.239 + </property> 1.240 + 1.241 + 1.242 + </implementation> 1.243 + </binding> 1.244 + 1.245 + <binding id="toolbar-menubar-stub"> 1.246 + <implementation> 1.247 + <property name="toolbox" readonly="true"> 1.248 + <getter><![CDATA[ 1.249 + if (this._toolbox) 1.250 + return this._toolbox; 1.251 + 1.252 + if (this.parentNode && this.parentNode.localName == "toolbox") { 1.253 + this._toolbox = this.parentNode; 1.254 + } 1.255 + 1.256 + return this._toolbox; 1.257 + ]]></getter> 1.258 + </property> 1.259 + <property name="currentSet" readonly="true"> 1.260 + <getter><![CDATA[ 1.261 + return this.getAttribute("defaultset"); 1.262 + ]]></getter> 1.263 + </property> 1.264 + <method name="insertItem"> 1.265 + <body><![CDATA[ 1.266 + return null; 1.267 + ]]></body> 1.268 + </method> 1.269 + </implementation> 1.270 + </binding> 1.271 + 1.272 + <!-- The toolbar-menubar-autohide and toolbar-drag bindings are almost 1.273 + verbatim copies of their toolkit counterparts - they just inherit from 1.274 + the customizableui's toolbar binding instead of toolkit's. We're currently 1.275 + OK with the maintainance burden of having two copies of a binding, since 1.276 + the long term goal is to move the customization framework into toolkit. --> 1.277 + 1.278 + <binding id="toolbar-menubar-autohide" 1.279 + extends="chrome://browser/content/customizableui/toolbar.xml#toolbar"> 1.280 + <implementation> 1.281 + <constructor> 1.282 + this._setInactive(); 1.283 + </constructor> 1.284 + <destructor> 1.285 + this._setActive(); 1.286 + </destructor> 1.287 + 1.288 + <field name="_inactiveTimeout">null</field> 1.289 + 1.290 + <field name="_contextMenuListener"><![CDATA[({ 1.291 + toolbar: this, 1.292 + contextMenu: null, 1.293 + 1.294 + get active () !!this.contextMenu, 1.295 + 1.296 + init: function (event) { 1.297 + let node = event.target; 1.298 + while (node != this.toolbar) { 1.299 + if (node.localName == "menupopup") 1.300 + return; 1.301 + node = node.parentNode; 1.302 + } 1.303 + 1.304 + let contextMenuId = this.toolbar.getAttribute("context"); 1.305 + if (!contextMenuId) 1.306 + return; 1.307 + 1.308 + this.contextMenu = document.getElementById(contextMenuId); 1.309 + if (!this.contextMenu) 1.310 + return; 1.311 + 1.312 + this.contextMenu.addEventListener("popupshown", this, false); 1.313 + this.contextMenu.addEventListener("popuphiding", this, false); 1.314 + this.toolbar.addEventListener("mousemove", this, false); 1.315 + }, 1.316 + handleEvent: function (event) { 1.317 + switch (event.type) { 1.318 + case "popupshown": 1.319 + this.toolbar.removeEventListener("mousemove", this, false); 1.320 + break; 1.321 + case "popuphiding": 1.322 + case "mousemove": 1.323 + this.toolbar._setInactiveAsync(); 1.324 + this.toolbar.removeEventListener("mousemove", this, false); 1.325 + this.contextMenu.removeEventListener("popuphiding", this, false); 1.326 + this.contextMenu.removeEventListener("popupshown", this, false); 1.327 + this.contextMenu = null; 1.328 + break; 1.329 + } 1.330 + } 1.331 + })]]></field> 1.332 + 1.333 + <method name="_setInactive"> 1.334 + <body><![CDATA[ 1.335 + this.setAttribute("inactive", "true"); 1.336 + ]]></body> 1.337 + </method> 1.338 + 1.339 + <method name="_setInactiveAsync"> 1.340 + <body><![CDATA[ 1.341 + this._inactiveTimeout = setTimeout(function (self) { 1.342 + if (self.getAttribute("autohide") == "true") { 1.343 + self._inactiveTimeout = null; 1.344 + self._setInactive(); 1.345 + } 1.346 + }, 0, this); 1.347 + ]]></body> 1.348 + </method> 1.349 + 1.350 + <method name="_setActive"> 1.351 + <body><![CDATA[ 1.352 + if (this._inactiveTimeout) { 1.353 + clearTimeout(this._inactiveTimeout); 1.354 + this._inactiveTimeout = null; 1.355 + } 1.356 + this.removeAttribute("inactive"); 1.357 + ]]></body> 1.358 + </method> 1.359 + </implementation> 1.360 + 1.361 + <handlers> 1.362 + <handler event="DOMMenuBarActive" action="this._setActive();"/> 1.363 + <handler event="popupshowing" action="this._setActive();"/> 1.364 + <handler event="mousedown" button="2" action="this._contextMenuListener.init(event);"/> 1.365 + <handler event="DOMMenuBarInactive"><![CDATA[ 1.366 + if (!this._contextMenuListener.active) 1.367 + this._setInactiveAsync(); 1.368 + ]]></handler> 1.369 + </handlers> 1.370 + </binding> 1.371 + 1.372 + <binding id="toolbar-drag" 1.373 + extends="chrome://browser/content/customizableui/toolbar.xml#toolbar"> 1.374 + <implementation> 1.375 + <field name="_dragBindingAlive">true</field> 1.376 + <constructor><![CDATA[ 1.377 + if (!this._draggableStarted) { 1.378 + this._draggableStarted = true; 1.379 + try { 1.380 + let tmp = {}; 1.381 + Components.utils.import("resource://gre/modules/WindowDraggingUtils.jsm", tmp); 1.382 + let draggableThis = new tmp.WindowDraggingElement(this); 1.383 + draggableThis.mouseDownCheck = function(e) { 1.384 + return this._dragBindingAlive; 1.385 + }; 1.386 + } catch (e) {} 1.387 + } 1.388 + ]]></constructor> 1.389 + </implementation> 1.390 + </binding> 1.391 + 1.392 + 1.393 +<!-- This is a peculiar binding. It is here to deal with overlayed/inserted add-on content, 1.394 + and immediately direct such content elsewhere. --> 1.395 + <binding id="addonbar-delegating"> 1.396 + <implementation> 1.397 + <constructor><![CDATA[ 1.398 + // Reading these immediately so nobody messes with them anymore: 1.399 + this._delegatingToolbar = this.getAttribute("toolbar-delegate"); 1.400 + this._wasCollapsed = this.getAttribute("collapsed") == "true"; 1.401 + // Leaving those in here to unbreak some code: 1.402 + if (document.readyState == "complete") { 1.403 + this._init(); 1.404 + } else { 1.405 + // Need to wait until XUL overlays are loaded. See bug 554279. 1.406 + let self = this; 1.407 + document.addEventListener("readystatechange", function onReadyStateChange() { 1.408 + if (document.readyState != "complete") 1.409 + return; 1.410 + document.removeEventListener("readystatechange", onReadyStateChange, false); 1.411 + self._init(); 1.412 + }, false); 1.413 + } 1.414 + ]]></constructor> 1.415 + 1.416 + <method name="_init"> 1.417 + <body><![CDATA[ 1.418 + // Searching for the toolbox palette in the toolbar binding because 1.419 + // toolbars are constructed first. 1.420 + let toolbox = this.toolbox; 1.421 + if (toolbox && !toolbox.palette) { 1.422 + for (let node of toolbox.children) { 1.423 + if (node.localName == "toolbarpalette") { 1.424 + // Hold on to the palette but remove it from the document. 1.425 + toolbox.palette = node; 1.426 + toolbox.removeChild(node); 1.427 + } 1.428 + } 1.429 + } 1.430 + 1.431 + // pass the current set of children for comparison with placements: 1.432 + let children = []; 1.433 + for (let node of this.childNodes) { 1.434 + if (node.getAttribute("skipintoolbarset") != "true" && node.id) { 1.435 + // Force everything to be removable so that buildArea can chuck stuff 1.436 + // out if the user has customized things / we've been here before: 1.437 + if (!this._whiteListed.has(node.id)) { 1.438 + node.setAttribute("removable", "true"); 1.439 + } 1.440 + children.push(node); 1.441 + } 1.442 + } 1.443 + CustomizableUI.registerToolbarNode(this, children); 1.444 + let existingMigratedItems = (this.getAttribute("migratedset") || "").split(','); 1.445 + for (let migratedItem of existingMigratedItems.filter((x) => !!x)) { 1.446 + this._currentSetMigrated.add(migratedItem); 1.447 + } 1.448 + this.evictNodes(); 1.449 + // We can't easily use |this| or strong bindings for the observer fn here 1.450 + // because that creates leaky circular references when the node goes away, 1.451 + // and XBL destructors are unreliable. 1.452 + let mutationObserver = new MutationObserver(function(mutations) { 1.453 + if (!mutations.length) { 1.454 + return; 1.455 + } 1.456 + let toolbar = mutations[0].target; 1.457 + // Can't use our own attribute because we might not have one if we're set to 1.458 + // collapsed 1.459 + let areCustomizing = toolbar.ownerDocument.documentElement.getAttribute("customizing"); 1.460 + if (!toolbar._isModifying && !areCustomizing) { 1.461 + toolbar.evictNodes(); 1.462 + } 1.463 + }); 1.464 + mutationObserver.observe(this, {childList: true}); 1.465 + ]]></body> 1.466 + </method> 1.467 + <method name="evictNodes"> 1.468 + <body><![CDATA[ 1.469 + this._isModifying = true; 1.470 + let i = this.childNodes.length; 1.471 + while (i--) { 1.472 + let node = this.childNodes[i]; 1.473 + if (this.childNodes[i].id) { 1.474 + this.evictNode(this.childNodes[i]); 1.475 + } else { 1.476 + node.remove(); 1.477 + } 1.478 + } 1.479 + this._isModifying = false; 1.480 + this._updateMigratedSet(); 1.481 + ]]></body> 1.482 + </method> 1.483 + <method name="evictNode"> 1.484 + <parameter name="aNode"/> 1.485 + <body> 1.486 + <![CDATA[ 1.487 + if (this._whiteListed.has(aNode.id) || CustomizableUI.isSpecialWidget(aNode.id)) { 1.488 + return; 1.489 + } 1.490 + const kItemMaxWidth = 100; 1.491 + let oldParent = aNode.parentNode; 1.492 + aNode.setAttribute("removable", "true"); 1.493 + this._currentSetMigrated.add(aNode.id); 1.494 + 1.495 + let movedOut = false; 1.496 + if (!this._wasCollapsed) { 1.497 + try { 1.498 + let nodeWidth = aNode.getBoundingClientRect().width; 1.499 + if (nodeWidth == 0 || nodeWidth > kItemMaxWidth) { 1.500 + throw new Error(aNode.id + " is too big (" + nodeWidth + 1.501 + "px wide), moving to the palette"); 1.502 + } 1.503 + CustomizableUI.addWidgetToArea(aNode.id, this._delegatingToolbar); 1.504 + movedOut = true; 1.505 + } catch (ex) { 1.506 + // This will throw if the node is too big, or can't be moved there for 1.507 + // some reason. Report this: 1.508 + Cu.reportError(ex); 1.509 + } 1.510 + } 1.511 + 1.512 + /* We won't have moved the widget if either the add-on bar was collapsed, 1.513 + * or if it was too wide to be inserted into the navbar. */ 1.514 + if (!movedOut) { 1.515 + try { 1.516 + CustomizableUI.removeWidgetFromArea(aNode.id); 1.517 + } catch (ex) { 1.518 + Cu.reportError(ex); 1.519 + aNode.remove(); 1.520 + } 1.521 + } 1.522 + 1.523 + // Surprise: addWidgetToArea(palette) will get you nothing if the palette 1.524 + // is not constructed yet. Fix: 1.525 + if (aNode.parentNode == oldParent) { 1.526 + let palette = this.toolbox.palette; 1.527 + if (palette && oldParent != palette) { 1.528 + palette.appendChild(aNode); 1.529 + } 1.530 + } 1.531 + ]]></body> 1.532 + </method> 1.533 + <method name="insertItem"> 1.534 + <parameter name="aId"/> 1.535 + <parameter name="aBeforeElt"/> 1.536 + <parameter name="aWrapper"/> 1.537 + <body><![CDATA[ 1.538 + if (aWrapper) { 1.539 + Cu.reportError("Can't insert " + aId + ": using insertItem " + 1.540 + "no longer supports wrapper elements."); 1.541 + return null; 1.542 + } 1.543 + 1.544 + let widget = CustomizableUI.getWidget(aId); 1.545 + widget = widget && widget.forWindow(window); 1.546 + let node = widget && widget.node; 1.547 + if (!node) { 1.548 + return null; 1.549 + } 1.550 + 1.551 + this._isModifying = true; 1.552 + // Temporarily add it here so it can have a width, then ditch it: 1.553 + this.appendChild(node); 1.554 + this.evictNode(node); 1.555 + this._isModifying = false; 1.556 + this._updateMigratedSet(); 1.557 + // We will now have moved stuff around; kick off some events 1.558 + // so add-ons know we've just moved their stuff: 1.559 + // XXXgijs: only in this window. It's hard to know for sure what's the right 1.560 + // thing to do here - typically insertItem is used on each window, so 1.561 + // this seems to make the most sense, even if some of the effects of 1.562 + // evictNode might affect multiple windows. 1.563 + CustomizableUI.dispatchToolboxEvent("customizationchange", {}, window); 1.564 + CustomizableUI.dispatchToolboxEvent("aftercustomization", {}, window); 1.565 + return node; 1.566 + ]]></body> 1.567 + </method> 1.568 + <method name="getMigratedItems"> 1.569 + <body><![CDATA[ 1.570 + return [... this._currentSetMigrated]; 1.571 + ]]></body> 1.572 + </method> 1.573 + <method name="_updateMigratedSet"> 1.574 + <body><![CDATA[ 1.575 + let newMigratedItems = this.getMigratedItems().join(','); 1.576 + if (this.getAttribute("migratedset") != newMigratedItems) { 1.577 + this.setAttribute("migratedset", newMigratedItems); 1.578 + this.ownerDocument.persist(this.id, "migratedset"); 1.579 + } 1.580 + ]]></body> 1.581 + </method> 1.582 + <property name="customizationTarget" readonly="true"> 1.583 + <getter><![CDATA[ 1.584 + return this; 1.585 + ]]></getter> 1.586 + </property> 1.587 + <property name="currentSet"> 1.588 + <getter><![CDATA[ 1.589 + return [node.id for (node of this.children)].join(','); 1.590 + ]]></getter> 1.591 + <setter><![CDATA[ 1.592 + let v = val.split(','); 1.593 + let newButtons = v.filter(x => x && (!this._whiteListed.has(x) && 1.594 + !CustomizableUI.isSpecialWidget(x) && 1.595 + !this._currentSetMigrated.has(x))); 1.596 + for (let newButton of newButtons) { 1.597 + this._currentSetMigrated.add(newButton); 1.598 + this.insertItem(newButton); 1.599 + } 1.600 + this._updateMigratedSet(); 1.601 + ]]></setter> 1.602 + </property> 1.603 + <property name="toolbox" readonly="true"> 1.604 + <getter><![CDATA[ 1.605 + if (!this._toolbox && this.parentNode && 1.606 + this.parentNode.localName == "toolbox") { 1.607 + this._toolbox = this.parentNode; 1.608 + } 1.609 + 1.610 + return this._toolbox; 1.611 + ]]></getter> 1.612 + </property> 1.613 + <field name="_whiteListed" readonly="true">new Set(["addonbar-closebutton", "status-bar"])</field> 1.614 + <field name="_isModifying">false</field> 1.615 + <field name="_currentSetMigrated">new Set()</field> 1.616 + </implementation> 1.617 + </binding> 1.618 +</bindings>