browser/components/customizableui/src/CustomizableWidgets.jsm

Wed, 31 Dec 2014 06:55:46 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:46 +0100
changeset 1
ca08bd8f51b2
permissions
-rw-r--r--

Added tag TORBROWSER_REPLICA for changeset 6474c204b198

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
michael@0 5 "use strict";
michael@0 6 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
michael@0 7
michael@0 8 this.EXPORTED_SYMBOLS = ["CustomizableWidgets"];
michael@0 9
michael@0 10 Cu.import("resource:///modules/CustomizableUI.jsm");
michael@0 11 Cu.import("resource://gre/modules/Services.jsm");
michael@0 12 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
michael@0 13 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
michael@0 14 "resource://gre/modules/PlacesUtils.jsm");
michael@0 15 XPCOMUtils.defineLazyModuleGetter(this, "PlacesUIUtils",
michael@0 16 "resource:///modules/PlacesUIUtils.jsm");
michael@0 17 XPCOMUtils.defineLazyModuleGetter(this, "RecentlyClosedTabsAndWindowsMenuUtils",
michael@0 18 "resource:///modules/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.jsm");
michael@0 19 XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
michael@0 20 "resource://gre/modules/ShortcutUtils.jsm");
michael@0 21 XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
michael@0 22 "resource://gre/modules/CharsetMenu.jsm");
michael@0 23 XPCOMUtils.defineLazyServiceGetter(this, "CharsetManager",
michael@0 24 "@mozilla.org/charset-converter-manager;1",
michael@0 25 "nsICharsetConverterManager");
michael@0 26
michael@0 27 XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
michael@0 28 const kCharsetBundle = "chrome://global/locale/charsetMenu.properties";
michael@0 29 return Services.strings.createBundle(kCharsetBundle);
michael@0 30 });
michael@0 31 XPCOMUtils.defineLazyGetter(this, "BrandBundle", function() {
michael@0 32 const kBrandBundle = "chrome://branding/locale/brand.properties";
michael@0 33 return Services.strings.createBundle(kBrandBundle);
michael@0 34 });
michael@0 35
michael@0 36 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
michael@0 37 const kPrefCustomizationDebug = "browser.uiCustomization.debug";
michael@0 38 const kWidePanelItemClass = "panel-wide-item";
michael@0 39
michael@0 40 let gModuleName = "[CustomizableWidgets]";
michael@0 41 #include logging.js
michael@0 42
michael@0 43 function setAttributes(aNode, aAttrs) {
michael@0 44 let doc = aNode.ownerDocument;
michael@0 45 for (let [name, value] of Iterator(aAttrs)) {
michael@0 46 if (!value) {
michael@0 47 if (aNode.hasAttribute(name))
michael@0 48 aNode.removeAttribute(name);
michael@0 49 } else {
michael@0 50 if (name == "shortcutId") {
michael@0 51 continue;
michael@0 52 }
michael@0 53 if (name == "label" || name == "tooltiptext") {
michael@0 54 let stringId = (typeof value == "string") ? value : name;
michael@0 55 let additionalArgs = [];
michael@0 56 if (aAttrs.shortcutId) {
michael@0 57 let shortcut = doc.getElementById(aAttrs.shortcutId);
michael@0 58 if (doc) {
michael@0 59 additionalArgs.push(ShortcutUtils.prettifyShortcut(shortcut));
michael@0 60 }
michael@0 61 }
michael@0 62 value = CustomizableUI.getLocalizedProperty({id: aAttrs.id}, stringId, additionalArgs);
michael@0 63 }
michael@0 64 aNode.setAttribute(name, value);
michael@0 65 }
michael@0 66 }
michael@0 67 }
michael@0 68
michael@0 69 function updateCombinedWidgetStyle(aNode, aArea, aModifyCloseMenu) {
michael@0 70 let inPanel = (aArea == CustomizableUI.AREA_PANEL);
michael@0 71 let cls = inPanel ? "panel-combined-button" : "toolbarbutton-1 toolbarbutton-combined";
michael@0 72 let attrs = {class: cls};
michael@0 73 if (aModifyCloseMenu) {
michael@0 74 attrs.closemenu = inPanel ? "none" : null;
michael@0 75 }
michael@0 76 attrs["cui-areatype"] = aArea ? CustomizableUI.getAreaType(aArea) : null;
michael@0 77 for (let i = 0, l = aNode.childNodes.length; i < l; ++i) {
michael@0 78 if (aNode.childNodes[i].localName == "separator")
michael@0 79 continue;
michael@0 80 setAttributes(aNode.childNodes[i], attrs);
michael@0 81 }
michael@0 82 }
michael@0 83
michael@0 84 function addShortcut(aNode, aDocument, aItem) {
michael@0 85 let shortcutId = aNode.getAttribute("key");
michael@0 86 if (!shortcutId) {
michael@0 87 return;
michael@0 88 }
michael@0 89 let shortcut = aDocument.getElementById(shortcutId);
michael@0 90 if (!shortcut) {
michael@0 91 return;
michael@0 92 }
michael@0 93 aItem.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(shortcut));
michael@0 94 }
michael@0 95
michael@0 96 function fillSubviewFromMenuItems(aMenuItems, aSubview) {
michael@0 97 let attrs = ["oncommand", "onclick", "label", "key", "disabled",
michael@0 98 "command", "observes", "hidden", "class", "origin",
michael@0 99 "image", "checked"];
michael@0 100
michael@0 101 let doc = aSubview.ownerDocument;
michael@0 102 let fragment = doc.createDocumentFragment();
michael@0 103 for (let menuChild of aMenuItems) {
michael@0 104 if (menuChild.hidden)
michael@0 105 continue;
michael@0 106
michael@0 107 let subviewItem;
michael@0 108 if (menuChild.localName == "menuseparator") {
michael@0 109 // Don't insert duplicate or leading separators. This can happen if there are
michael@0 110 // menus (which we don't copy) above the separator.
michael@0 111 if (!fragment.lastChild || fragment.lastChild.localName == "menuseparator") {
michael@0 112 continue;
michael@0 113 }
michael@0 114 subviewItem = doc.createElementNS(kNSXUL, "menuseparator");
michael@0 115 } else if (menuChild.localName == "menuitem") {
michael@0 116 subviewItem = doc.createElementNS(kNSXUL, "toolbarbutton");
michael@0 117 addShortcut(menuChild, doc, subviewItem);
michael@0 118
michael@0 119 let item = menuChild;
michael@0 120 if (!item.hasAttribute("onclick")) {
michael@0 121 subviewItem.addEventListener("click", event => {
michael@0 122 let newEvent = new doc.defaultView.MouseEvent(event.type, event);
michael@0 123 item.dispatchEvent(newEvent);
michael@0 124 });
michael@0 125 }
michael@0 126
michael@0 127 if (!item.hasAttribute("oncommand")) {
michael@0 128 subviewItem.addEventListener("command", event => {
michael@0 129 let newEvent = doc.createEvent("XULCommandEvent");
michael@0 130 newEvent.initCommandEvent(
michael@0 131 event.type, event.bubbles, event.cancelable, event.view,
michael@0 132 event.detail, event.ctrlKey, event.altKey, event.shiftKey,
michael@0 133 event.metaKey, event.sourceEvent);
michael@0 134 item.dispatchEvent(newEvent);
michael@0 135 });
michael@0 136 }
michael@0 137 } else {
michael@0 138 continue;
michael@0 139 }
michael@0 140 for (let attr of attrs) {
michael@0 141 let attrVal = menuChild.getAttribute(attr);
michael@0 142 if (attrVal)
michael@0 143 subviewItem.setAttribute(attr, attrVal);
michael@0 144 }
michael@0 145 // We do this after so the .subviewbutton class doesn't get overriden.
michael@0 146 if (menuChild.localName == "menuitem") {
michael@0 147 subviewItem.classList.add("subviewbutton");
michael@0 148 }
michael@0 149 fragment.appendChild(subviewItem);
michael@0 150 }
michael@0 151 aSubview.appendChild(fragment);
michael@0 152 }
michael@0 153
michael@0 154 function clearSubview(aSubview) {
michael@0 155 let parent = aSubview.parentNode;
michael@0 156 // We'll take the container out of the document before cleaning it out
michael@0 157 // to avoid reflowing each time we remove something.
michael@0 158 parent.removeChild(aSubview);
michael@0 159
michael@0 160 while (aSubview.firstChild) {
michael@0 161 aSubview.firstChild.remove();
michael@0 162 }
michael@0 163
michael@0 164 parent.appendChild(aSubview);
michael@0 165 }
michael@0 166
michael@0 167 const CustomizableWidgets = [{
michael@0 168 id: "history-panelmenu",
michael@0 169 type: "view",
michael@0 170 viewId: "PanelUI-history",
michael@0 171 shortcutId: "key_gotoHistory",
michael@0 172 tooltiptext: "history-panelmenu.tooltiptext2",
michael@0 173 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 174 onViewShowing: function(aEvent) {
michael@0 175 // Populate our list of history
michael@0 176 const kMaxResults = 15;
michael@0 177 let doc = aEvent.detail.ownerDocument;
michael@0 178
michael@0 179 let options = PlacesUtils.history.getNewQueryOptions();
michael@0 180 options.excludeQueries = true;
michael@0 181 options.includeHidden = false;
michael@0 182 options.resultType = options.RESULTS_AS_URI;
michael@0 183 options.queryType = options.QUERY_TYPE_HISTORY;
michael@0 184 options.sortingMode = options.SORT_BY_DATE_DESCENDING;
michael@0 185 options.maxResults = kMaxResults;
michael@0 186 let query = PlacesUtils.history.getNewQuery();
michael@0 187
michael@0 188 let items = doc.getElementById("PanelUI-historyItems");
michael@0 189 // Clear previous history items.
michael@0 190 while (items.firstChild) {
michael@0 191 items.removeChild(items.firstChild);
michael@0 192 }
michael@0 193
michael@0 194 PlacesUtils.history.QueryInterface(Ci.nsPIPlacesDatabase)
michael@0 195 .asyncExecuteLegacyQueries([query], 1, options, {
michael@0 196 handleResult: function (aResultSet) {
michael@0 197 let onHistoryVisit = function (aUri, aEvent, aItem) {
michael@0 198 doc.defaultView.openUILink(aUri, aEvent);
michael@0 199 CustomizableUI.hidePanelForNode(aItem);
michael@0 200 };
michael@0 201 let fragment = doc.createDocumentFragment();
michael@0 202 for (let row, i = 0; (row = aResultSet.getNextRow()); i++) {
michael@0 203 try {
michael@0 204 let uri = row.getResultByIndex(1);
michael@0 205 let title = row.getResultByIndex(2);
michael@0 206 let icon = row.getResultByIndex(6);
michael@0 207
michael@0 208 let item = doc.createElementNS(kNSXUL, "toolbarbutton");
michael@0 209 item.setAttribute("label", title || uri);
michael@0 210 item.setAttribute("targetURI", uri);
michael@0 211 item.setAttribute("class", "subviewbutton");
michael@0 212 item.addEventListener("click", function (aEvent) {
michael@0 213 onHistoryVisit(uri, aEvent, item);
michael@0 214 });
michael@0 215 if (icon)
michael@0 216 item.setAttribute("image", "moz-anno:favicon:" + icon);
michael@0 217 fragment.appendChild(item);
michael@0 218 } catch (e) {
michael@0 219 ERROR("Error while showing history subview: " + e);
michael@0 220 }
michael@0 221 }
michael@0 222 items.appendChild(fragment);
michael@0 223 },
michael@0 224 handleError: function (aError) {
michael@0 225 LOG("History view tried to show but had an error: " + aError);
michael@0 226 },
michael@0 227 handleCompletion: function (aReason) {
michael@0 228 LOG("History view is being shown!");
michael@0 229 },
michael@0 230 });
michael@0 231
michael@0 232 let recentlyClosedTabs = doc.getElementById("PanelUI-recentlyClosedTabs");
michael@0 233 while (recentlyClosedTabs.firstChild) {
michael@0 234 recentlyClosedTabs.removeChild(recentlyClosedTabs.firstChild);
michael@0 235 }
michael@0 236
michael@0 237 let recentlyClosedWindows = doc.getElementById("PanelUI-recentlyClosedWindows");
michael@0 238 while (recentlyClosedWindows.firstChild) {
michael@0 239 recentlyClosedWindows.removeChild(recentlyClosedWindows.firstChild);
michael@0 240 }
michael@0 241
michael@0 242 #ifdef MOZ_SERVICES_SYNC
michael@0 243 let tabsFromOtherComputers = doc.getElementById("sync-tabs-menuitem2");
michael@0 244 if (PlacesUIUtils.shouldShowTabsFromOtherComputersMenuitem()) {
michael@0 245 tabsFromOtherComputers.removeAttribute("hidden");
michael@0 246 } else {
michael@0 247 tabsFromOtherComputers.setAttribute("hidden", true);
michael@0 248 }
michael@0 249
michael@0 250 if (PlacesUIUtils.shouldEnableTabsFromOtherComputersMenuitem()) {
michael@0 251 tabsFromOtherComputers.removeAttribute("disabled");
michael@0 252 } else {
michael@0 253 tabsFromOtherComputers.setAttribute("disabled", true);
michael@0 254 }
michael@0 255 #endif
michael@0 256
michael@0 257 let utils = RecentlyClosedTabsAndWindowsMenuUtils;
michael@0 258 let tabsFragment = utils.getTabsFragment(doc.defaultView, "toolbarbutton", true,
michael@0 259 "menuRestoreAllTabsSubview.label");
michael@0 260 let separator = doc.getElementById("PanelUI-recentlyClosedTabs-separator");
michael@0 261 let elementCount = tabsFragment.childElementCount;
michael@0 262 separator.hidden = !elementCount;
michael@0 263 while (--elementCount >= 0) {
michael@0 264 tabsFragment.children[elementCount].classList.add("subviewbutton");
michael@0 265 }
michael@0 266 recentlyClosedTabs.appendChild(tabsFragment);
michael@0 267
michael@0 268 let windowsFragment = utils.getWindowsFragment(doc.defaultView, "toolbarbutton", true,
michael@0 269 "menuRestoreAllWindowsSubview.label");
michael@0 270 separator = doc.getElementById("PanelUI-recentlyClosedWindows-separator");
michael@0 271 elementCount = windowsFragment.childElementCount;
michael@0 272 separator.hidden = !elementCount;
michael@0 273 while (--elementCount >= 0) {
michael@0 274 windowsFragment.children[elementCount].classList.add("subviewbutton");
michael@0 275 }
michael@0 276 recentlyClosedWindows.appendChild(windowsFragment);
michael@0 277 },
michael@0 278 onCreated: function(aNode) {
michael@0 279 // Middle clicking recently closed items won't close the panel - cope:
michael@0 280 let onRecentlyClosedClick = function(aEvent) {
michael@0 281 if (aEvent.button == 1) {
michael@0 282 CustomizableUI.hidePanelForNode(this);
michael@0 283 }
michael@0 284 };
michael@0 285 let doc = aNode.ownerDocument;
michael@0 286 let recentlyClosedTabs = doc.getElementById("PanelUI-recentlyClosedTabs");
michael@0 287 let recentlyClosedWindows = doc.getElementById("PanelUI-recentlyClosedWindows");
michael@0 288 recentlyClosedTabs.addEventListener("click", onRecentlyClosedClick);
michael@0 289 recentlyClosedWindows.addEventListener("click", onRecentlyClosedClick);
michael@0 290 },
michael@0 291 onViewHiding: function(aEvent) {
michael@0 292 LOG("History view is being hidden!");
michael@0 293 }
michael@0 294 }, {
michael@0 295 id: "privatebrowsing-button",
michael@0 296 shortcutId: "key_privatebrowsing",
michael@0 297 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 298 onCommand: function(e) {
michael@0 299 if (e.target && e.target.ownerDocument && e.target.ownerDocument.defaultView) {
michael@0 300 let win = e.target.ownerDocument.defaultView;
michael@0 301 if (typeof win.OpenBrowserWindow == "function") {
michael@0 302 win.OpenBrowserWindow({private: true});
michael@0 303 }
michael@0 304 }
michael@0 305 }
michael@0 306 }, {
michael@0 307 id: "save-page-button",
michael@0 308 shortcutId: "key_savePage",
michael@0 309 tooltiptext: "save-page-button.tooltiptext3",
michael@0 310 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 311 onCommand: function(aEvent) {
michael@0 312 let win = aEvent.target &&
michael@0 313 aEvent.target.ownerDocument &&
michael@0 314 aEvent.target.ownerDocument.defaultView;
michael@0 315 if (win && typeof win.saveDocument == "function") {
michael@0 316 win.saveDocument(win.content.document);
michael@0 317 }
michael@0 318 }
michael@0 319 }, {
michael@0 320 id: "find-button",
michael@0 321 shortcutId: "key_find",
michael@0 322 tooltiptext: "find-button.tooltiptext3",
michael@0 323 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 324 onCommand: function(aEvent) {
michael@0 325 let win = aEvent.target &&
michael@0 326 aEvent.target.ownerDocument &&
michael@0 327 aEvent.target.ownerDocument.defaultView;
michael@0 328 if (win && win.gFindBar) {
michael@0 329 win.gFindBar.onFindCommand();
michael@0 330 }
michael@0 331 }
michael@0 332 }, {
michael@0 333 id: "open-file-button",
michael@0 334 shortcutId: "openFileKb",
michael@0 335 tooltiptext: "open-file-button.tooltiptext3",
michael@0 336 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 337 onCommand: function(aEvent) {
michael@0 338 let win = aEvent.target
michael@0 339 && aEvent.target.ownerDocument
michael@0 340 && aEvent.target.ownerDocument.defaultView;
michael@0 341 if (win && typeof win.BrowserOpenFileWindow == "function") {
michael@0 342 win.BrowserOpenFileWindow();
michael@0 343 }
michael@0 344 }
michael@0 345 }, {
michael@0 346 id: "developer-button",
michael@0 347 type: "view",
michael@0 348 viewId: "PanelUI-developer",
michael@0 349 shortcutId: "key_devToolboxMenuItem",
michael@0 350 tooltiptext: "developer-button.tooltiptext2",
michael@0 351 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 352 onViewShowing: function(aEvent) {
michael@0 353 // Populate the subview with whatever menuitems are in the developer
michael@0 354 // menu. We skip menu elements, because the menu panel has no way
michael@0 355 // of dealing with those right now.
michael@0 356 let doc = aEvent.target.ownerDocument;
michael@0 357 let win = doc.defaultView;
michael@0 358
michael@0 359 let menu = doc.getElementById("menuWebDeveloperPopup");
michael@0 360
michael@0 361 let itemsToDisplay = [...menu.children];
michael@0 362 // Hardcode the addition of the "work offline" menuitem at the bottom:
michael@0 363 itemsToDisplay.push({localName: "menuseparator", getAttribute: () => {}});
michael@0 364 itemsToDisplay.push(doc.getElementById("goOfflineMenuitem"));
michael@0 365 fillSubviewFromMenuItems(itemsToDisplay, doc.getElementById("PanelUI-developerItems"));
michael@0 366
michael@0 367 },
michael@0 368 onViewHiding: function(aEvent) {
michael@0 369 let doc = aEvent.target.ownerDocument;
michael@0 370 clearSubview(doc.getElementById("PanelUI-developerItems"));
michael@0 371 }
michael@0 372 }, {
michael@0 373 id: "sidebar-button",
michael@0 374 type: "view",
michael@0 375 viewId: "PanelUI-sidebar",
michael@0 376 tooltiptext: "sidebar-button.tooltiptext2",
michael@0 377 onViewShowing: function(aEvent) {
michael@0 378 // Largely duplicated from the developer-button above with a couple minor
michael@0 379 // alterations.
michael@0 380 // Populate the subview with whatever menuitems are in the
michael@0 381 // sidebar menu. We skip menu elements, because the menu panel has no way
michael@0 382 // of dealing with those right now.
michael@0 383 let doc = aEvent.target.ownerDocument;
michael@0 384 let win = doc.defaultView;
michael@0 385 let menu = doc.getElementById("viewSidebarMenu");
michael@0 386
michael@0 387 // First clear any existing menuitems then populate. Social sidebar
michael@0 388 // options may not have been added yet, so we do that here. Add it to the
michael@0 389 // standard menu first, then copy all sidebar options to the panel.
michael@0 390 win.SocialSidebar.clearProviderMenus();
michael@0 391 let providerMenuSeps = menu.getElementsByClassName("social-provider-menu");
michael@0 392 if (providerMenuSeps.length > 0)
michael@0 393 win.SocialSidebar.populateProviderMenu(providerMenuSeps[0]);
michael@0 394
michael@0 395 fillSubviewFromMenuItems([...menu.children], doc.getElementById("PanelUI-sidebarItems"));
michael@0 396 },
michael@0 397 onViewHiding: function(aEvent) {
michael@0 398 let doc = aEvent.target.ownerDocument;
michael@0 399 clearSubview(doc.getElementById("PanelUI-sidebarItems"));
michael@0 400 }
michael@0 401 }, {
michael@0 402 id: "add-ons-button",
michael@0 403 shortcutId: "key_openAddons",
michael@0 404 tooltiptext: "add-ons-button.tooltiptext3",
michael@0 405 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 406 onCommand: function(aEvent) {
michael@0 407 let win = aEvent.target &&
michael@0 408 aEvent.target.ownerDocument &&
michael@0 409 aEvent.target.ownerDocument.defaultView;
michael@0 410 if (win && typeof win.BrowserOpenAddonsMgr == "function") {
michael@0 411 win.BrowserOpenAddonsMgr();
michael@0 412 }
michael@0 413 }
michael@0 414 }, {
michael@0 415 id: "preferences-button",
michael@0 416 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 417 #ifdef XP_WIN
michael@0 418 label: "preferences-button.labelWin",
michael@0 419 tooltiptext: "preferences-button.tooltipWin2",
michael@0 420 #else
michael@0 421 #ifdef XP_MACOSX
michael@0 422 tooltiptext: "preferences-button.tooltiptext.withshortcut",
michael@0 423 shortcutId: "key_preferencesCmdMac",
michael@0 424 #else
michael@0 425 tooltiptext: "preferences-button.tooltiptext2",
michael@0 426 #endif
michael@0 427 #endif
michael@0 428 onCommand: function(aEvent) {
michael@0 429 let win = aEvent.target &&
michael@0 430 aEvent.target.ownerDocument &&
michael@0 431 aEvent.target.ownerDocument.defaultView;
michael@0 432 if (win && typeof win.openPreferences == "function") {
michael@0 433 win.openPreferences();
michael@0 434 }
michael@0 435 }
michael@0 436 }, {
michael@0 437 id: "zoom-controls",
michael@0 438 type: "custom",
michael@0 439 tooltiptext: "zoom-controls.tooltiptext2",
michael@0 440 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 441 onBuild: function(aDocument) {
michael@0 442 const kPanelId = "PanelUI-popup";
michael@0 443 let areaType = CustomizableUI.getAreaType(this.currentArea);
michael@0 444 let inPanel = areaType == CustomizableUI.TYPE_MENU_PANEL;
michael@0 445 let inToolbar = areaType == CustomizableUI.TYPE_TOOLBAR;
michael@0 446
michael@0 447 let buttons = [{
michael@0 448 id: "zoom-out-button",
michael@0 449 command: "cmd_fullZoomReduce",
michael@0 450 label: true,
michael@0 451 tooltiptext: "tooltiptext2",
michael@0 452 shortcutId: "key_fullZoomReduce",
michael@0 453 }, {
michael@0 454 id: "zoom-reset-button",
michael@0 455 command: "cmd_fullZoomReset",
michael@0 456 tooltiptext: "tooltiptext2",
michael@0 457 shortcutId: "key_fullZoomReset",
michael@0 458 }, {
michael@0 459 id: "zoom-in-button",
michael@0 460 command: "cmd_fullZoomEnlarge",
michael@0 461 label: true,
michael@0 462 tooltiptext: "tooltiptext2",
michael@0 463 shortcutId: "key_fullZoomEnlarge",
michael@0 464 }];
michael@0 465
michael@0 466 let node = aDocument.createElementNS(kNSXUL, "toolbaritem");
michael@0 467 node.setAttribute("id", "zoom-controls");
michael@0 468 node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
michael@0 469 node.setAttribute("title", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
michael@0 470 // Set this as an attribute in addition to the property to make sure we can style correctly.
michael@0 471 node.setAttribute("removable", "true");
michael@0 472 node.classList.add("chromeclass-toolbar-additional");
michael@0 473 node.classList.add("toolbaritem-combined-buttons");
michael@0 474 node.classList.add(kWidePanelItemClass);
michael@0 475
michael@0 476 buttons.forEach(function(aButton, aIndex) {
michael@0 477 if (aIndex != 0)
michael@0 478 node.appendChild(aDocument.createElementNS(kNSXUL, "separator"));
michael@0 479 let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton");
michael@0 480 setAttributes(btnNode, aButton);
michael@0 481 node.appendChild(btnNode);
michael@0 482 });
michael@0 483
michael@0 484 // The middle node is the 'Reset Zoom' button.
michael@0 485 let zoomResetButton = node.childNodes[2];
michael@0 486 let window = aDocument.defaultView;
michael@0 487 function updateZoomResetButton() {
michael@0 488 let updateDisplay = true;
michael@0 489 // Label should always show 100% in customize mode, so don't update:
michael@0 490 if (aDocument.documentElement.hasAttribute("customizing")) {
michael@0 491 updateDisplay = false;
michael@0 492 }
michael@0 493 //XXXgijs in some tests we get called very early, and there's no docShell on the
michael@0 494 // tabbrowser. This breaks the zoom toolkit code (see bug 897410). Don't let that happen:
michael@0 495 let zoomFactor = 100;
michael@0 496 try {
michael@0 497 zoomFactor = Math.round(window.ZoomManager.zoom * 100);
michael@0 498 } catch (e) {}
michael@0 499 zoomResetButton.setAttribute("label", CustomizableUI.getLocalizedProperty(
michael@0 500 buttons[1], "label", [updateDisplay ? zoomFactor : 100]
michael@0 501 ));
michael@0 502 };
michael@0 503
michael@0 504 // Register ourselves with the service so we know when the zoom prefs change.
michael@0 505 Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomChange", false);
michael@0 506 Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:zoomReset", false);
michael@0 507 Services.obs.addObserver(updateZoomResetButton, "browser-fullZoom:location-change", false);
michael@0 508
michael@0 509 if (inPanel) {
michael@0 510 let panel = aDocument.getElementById(kPanelId);
michael@0 511 panel.addEventListener("popupshowing", updateZoomResetButton);
michael@0 512 } else {
michael@0 513 if (inToolbar) {
michael@0 514 let container = window.gBrowser.tabContainer;
michael@0 515 container.addEventListener("TabSelect", updateZoomResetButton);
michael@0 516 }
michael@0 517 updateZoomResetButton();
michael@0 518 }
michael@0 519 updateCombinedWidgetStyle(node, this.currentArea, true);
michael@0 520
michael@0 521 let listener = {
michael@0 522 onWidgetAdded: function(aWidgetId, aArea, aPosition) {
michael@0 523 if (aWidgetId != this.id)
michael@0 524 return;
michael@0 525
michael@0 526 updateCombinedWidgetStyle(node, aArea, true);
michael@0 527 updateZoomResetButton();
michael@0 528
michael@0 529 let areaType = CustomizableUI.getAreaType(aArea);
michael@0 530 if (areaType == CustomizableUI.TYPE_MENU_PANEL) {
michael@0 531 let panel = aDocument.getElementById(kPanelId);
michael@0 532 panel.addEventListener("popupshowing", updateZoomResetButton);
michael@0 533 } else if (areaType == CustomizableUI.TYPE_TOOLBAR) {
michael@0 534 let container = window.gBrowser.tabContainer;
michael@0 535 container.addEventListener("TabSelect", updateZoomResetButton);
michael@0 536 }
michael@0 537 }.bind(this),
michael@0 538
michael@0 539 onWidgetRemoved: function(aWidgetId, aPrevArea) {
michael@0 540 if (aWidgetId != this.id)
michael@0 541 return;
michael@0 542
michael@0 543 let areaType = CustomizableUI.getAreaType(aPrevArea);
michael@0 544 if (areaType == CustomizableUI.TYPE_MENU_PANEL) {
michael@0 545 let panel = aDocument.getElementById(kPanelId);
michael@0 546 panel.removeEventListener("popupshowing", updateZoomResetButton);
michael@0 547 } else if (areaType == CustomizableUI.TYPE_TOOLBAR) {
michael@0 548 let container = window.gBrowser.tabContainer;
michael@0 549 container.removeEventListener("TabSelect", updateZoomResetButton);
michael@0 550 }
michael@0 551
michael@0 552 // When a widget is demoted to the palette ('removed'), it's visual
michael@0 553 // style should change.
michael@0 554 updateCombinedWidgetStyle(node, null, true);
michael@0 555 updateZoomResetButton();
michael@0 556 }.bind(this),
michael@0 557
michael@0 558 onWidgetReset: function(aWidgetNode) {
michael@0 559 if (aWidgetNode != node)
michael@0 560 return;
michael@0 561 updateCombinedWidgetStyle(node, this.currentArea, true);
michael@0 562 updateZoomResetButton();
michael@0 563 }.bind(this),
michael@0 564
michael@0 565 onWidgetMoved: function(aWidgetId, aArea) {
michael@0 566 if (aWidgetId != this.id)
michael@0 567 return;
michael@0 568 updateCombinedWidgetStyle(node, aArea, true);
michael@0 569 updateZoomResetButton();
michael@0 570 }.bind(this),
michael@0 571
michael@0 572 onWidgetInstanceRemoved: function(aWidgetId, aDoc) {
michael@0 573 if (aWidgetId != this.id || aDoc != aDocument)
michael@0 574 return;
michael@0 575
michael@0 576 CustomizableUI.removeListener(listener);
michael@0 577 Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomChange");
michael@0 578 Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:zoomReset");
michael@0 579 Services.obs.removeObserver(updateZoomResetButton, "browser-fullZoom:location-change");
michael@0 580 let panel = aDoc.getElementById(kPanelId);
michael@0 581 panel.removeEventListener("popupshowing", updateZoomResetButton);
michael@0 582 let container = aDoc.defaultView.gBrowser.tabContainer;
michael@0 583 container.removeEventListener("TabSelect", updateZoomResetButton);
michael@0 584 }.bind(this),
michael@0 585
michael@0 586 onCustomizeStart: function(aWindow) {
michael@0 587 if (aWindow.document == aDocument) {
michael@0 588 updateZoomResetButton();
michael@0 589 }
michael@0 590 },
michael@0 591
michael@0 592 onCustomizeEnd: function(aWindow) {
michael@0 593 if (aWindow.document == aDocument) {
michael@0 594 updateZoomResetButton();
michael@0 595 }
michael@0 596 },
michael@0 597
michael@0 598 onWidgetDrag: function(aWidgetId, aArea) {
michael@0 599 if (aWidgetId != this.id)
michael@0 600 return;
michael@0 601 aArea = aArea || this.currentArea;
michael@0 602 updateCombinedWidgetStyle(node, aArea, true);
michael@0 603 }.bind(this)
michael@0 604 };
michael@0 605 CustomizableUI.addListener(listener);
michael@0 606
michael@0 607 return node;
michael@0 608 }
michael@0 609 }, {
michael@0 610 id: "edit-controls",
michael@0 611 type: "custom",
michael@0 612 tooltiptext: "edit-controls.tooltiptext2",
michael@0 613 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 614 onBuild: function(aDocument) {
michael@0 615 let buttons = [{
michael@0 616 id: "cut-button",
michael@0 617 command: "cmd_cut",
michael@0 618 label: true,
michael@0 619 tooltiptext: "tooltiptext2",
michael@0 620 shortcutId: "key_cut",
michael@0 621 }, {
michael@0 622 id: "copy-button",
michael@0 623 command: "cmd_copy",
michael@0 624 label: true,
michael@0 625 tooltiptext: "tooltiptext2",
michael@0 626 shortcutId: "key_copy",
michael@0 627 }, {
michael@0 628 id: "paste-button",
michael@0 629 command: "cmd_paste",
michael@0 630 label: true,
michael@0 631 tooltiptext: "tooltiptext2",
michael@0 632 shortcutId: "key_paste",
michael@0 633 }];
michael@0 634
michael@0 635 let node = aDocument.createElementNS(kNSXUL, "toolbaritem");
michael@0 636 node.setAttribute("id", "edit-controls");
michael@0 637 node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
michael@0 638 node.setAttribute("title", CustomizableUI.getLocalizedProperty(this, "tooltiptext"));
michael@0 639 // Set this as an attribute in addition to the property to make sure we can style correctly.
michael@0 640 node.setAttribute("removable", "true");
michael@0 641 node.classList.add("chromeclass-toolbar-additional");
michael@0 642 node.classList.add("toolbaritem-combined-buttons");
michael@0 643 node.classList.add(kWidePanelItemClass);
michael@0 644
michael@0 645 buttons.forEach(function(aButton, aIndex) {
michael@0 646 if (aIndex != 0)
michael@0 647 node.appendChild(aDocument.createElementNS(kNSXUL, "separator"));
michael@0 648 let btnNode = aDocument.createElementNS(kNSXUL, "toolbarbutton");
michael@0 649 setAttributes(btnNode, aButton);
michael@0 650 node.appendChild(btnNode);
michael@0 651 });
michael@0 652
michael@0 653 updateCombinedWidgetStyle(node, this.currentArea);
michael@0 654
michael@0 655 let listener = {
michael@0 656 onWidgetAdded: function(aWidgetId, aArea, aPosition) {
michael@0 657 if (aWidgetId != this.id)
michael@0 658 return;
michael@0 659 updateCombinedWidgetStyle(node, aArea);
michael@0 660 }.bind(this),
michael@0 661
michael@0 662 onWidgetRemoved: function(aWidgetId, aPrevArea) {
michael@0 663 if (aWidgetId != this.id)
michael@0 664 return;
michael@0 665 // When a widget is demoted to the palette ('removed'), it's visual
michael@0 666 // style should change.
michael@0 667 updateCombinedWidgetStyle(node);
michael@0 668 }.bind(this),
michael@0 669
michael@0 670 onWidgetReset: function(aWidgetNode) {
michael@0 671 if (aWidgetNode != node)
michael@0 672 return;
michael@0 673 updateCombinedWidgetStyle(node, this.currentArea);
michael@0 674 }.bind(this),
michael@0 675
michael@0 676 onWidgetMoved: function(aWidgetId, aArea) {
michael@0 677 if (aWidgetId != this.id)
michael@0 678 return;
michael@0 679 updateCombinedWidgetStyle(node, aArea);
michael@0 680 }.bind(this),
michael@0 681
michael@0 682 onWidgetInstanceRemoved: function(aWidgetId, aDoc) {
michael@0 683 if (aWidgetId != this.id || aDoc != aDocument)
michael@0 684 return;
michael@0 685 CustomizableUI.removeListener(listener);
michael@0 686 }.bind(this),
michael@0 687
michael@0 688 onWidgetDrag: function(aWidgetId, aArea) {
michael@0 689 if (aWidgetId != this.id)
michael@0 690 return;
michael@0 691 aArea = aArea || this.currentArea;
michael@0 692 updateCombinedWidgetStyle(node, aArea);
michael@0 693 }.bind(this)
michael@0 694 };
michael@0 695 CustomizableUI.addListener(listener);
michael@0 696
michael@0 697 return node;
michael@0 698 }
michael@0 699 },
michael@0 700 {
michael@0 701 id: "feed-button",
michael@0 702 type: "view",
michael@0 703 viewId: "PanelUI-feeds",
michael@0 704 tooltiptext: "feed-button.tooltiptext2",
michael@0 705 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 706 onClick: function(aEvent) {
michael@0 707 let win = aEvent.target.ownerDocument.defaultView;
michael@0 708 let feeds = win.gBrowser.selectedBrowser.feeds;
michael@0 709
michael@0 710 // Here, we only care about the case where we have exactly 1 feed and the
michael@0 711 // user clicked...
michael@0 712 let isClick = (aEvent.button == 0 || aEvent.button == 1);
michael@0 713 if (feeds && feeds.length == 1 && isClick) {
michael@0 714 aEvent.preventDefault();
michael@0 715 aEvent.stopPropagation();
michael@0 716 win.FeedHandler.subscribeToFeed(feeds[0].href, aEvent);
michael@0 717 CustomizableUI.hidePanelForNode(aEvent.target);
michael@0 718 }
michael@0 719 },
michael@0 720 onViewShowing: function(aEvent) {
michael@0 721 let doc = aEvent.detail.ownerDocument;
michael@0 722 let container = doc.getElementById("PanelUI-feeds");
michael@0 723 let gotView = doc.defaultView.FeedHandler.buildFeedList(container, true);
michael@0 724
michael@0 725 // For no feeds or only a single one, don't show the panel.
michael@0 726 if (!gotView) {
michael@0 727 aEvent.preventDefault();
michael@0 728 aEvent.stopPropagation();
michael@0 729 return;
michael@0 730 }
michael@0 731 },
michael@0 732 onCreated: function(node) {
michael@0 733 let win = node.ownerDocument.defaultView;
michael@0 734 let selectedBrowser = win.gBrowser.selectedBrowser;
michael@0 735 let feeds = selectedBrowser && selectedBrowser.feeds;
michael@0 736 if (!feeds || !feeds.length) {
michael@0 737 node.setAttribute("disabled", "true");
michael@0 738 }
michael@0 739 }
michael@0 740 }, {
michael@0 741 id: "characterencoding-button",
michael@0 742 type: "view",
michael@0 743 viewId: "PanelUI-characterEncodingView",
michael@0 744 tooltiptext: "characterencoding-button.tooltiptext2",
michael@0 745 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 746 maybeDisableMenu: function(aDocument) {
michael@0 747 let window = aDocument.defaultView;
michael@0 748 return !(window.gBrowser &&
michael@0 749 window.gBrowser.docShell &&
michael@0 750 window.gBrowser.docShell.mayEnableCharacterEncodingMenu);
michael@0 751 },
michael@0 752 populateList: function(aDocument, aContainerId, aSection) {
michael@0 753 let containerElem = aDocument.getElementById(aContainerId);
michael@0 754
michael@0 755 containerElem.addEventListener("command", this.onCommand, false);
michael@0 756
michael@0 757 let list = this.charsetInfo[aSection];
michael@0 758
michael@0 759 for (let item of list) {
michael@0 760 let elem = aDocument.createElementNS(kNSXUL, "toolbarbutton");
michael@0 761 elem.setAttribute("label", item.label);
michael@0 762 elem.setAttribute("type", "checkbox");
michael@0 763 elem.section = aSection;
michael@0 764 elem.value = item.value;
michael@0 765 elem.setAttribute("class", "subviewbutton");
michael@0 766 containerElem.appendChild(elem);
michael@0 767 }
michael@0 768 },
michael@0 769 updateCurrentCharset: function(aDocument) {
michael@0 770 let content = aDocument.defaultView.content;
michael@0 771 let currentCharset = content && content.document && content.document.characterSet;
michael@0 772 currentCharset = CharsetMenu.foldCharset(currentCharset);
michael@0 773
michael@0 774 let pinnedContainer = aDocument.getElementById("PanelUI-characterEncodingView-pinned");
michael@0 775 let charsetContainer = aDocument.getElementById("PanelUI-characterEncodingView-charsets");
michael@0 776 let elements = [...(pinnedContainer.childNodes), ...(charsetContainer.childNodes)];
michael@0 777
michael@0 778 this._updateElements(elements, currentCharset);
michael@0 779 },
michael@0 780 updateCurrentDetector: function(aDocument) {
michael@0 781 let detectorContainer = aDocument.getElementById("PanelUI-characterEncodingView-autodetect");
michael@0 782 let currentDetector;
michael@0 783 try {
michael@0 784 currentDetector = Services.prefs.getComplexValue(
michael@0 785 "intl.charset.detector", Ci.nsIPrefLocalizedString).data;
michael@0 786 } catch (e) {}
michael@0 787
michael@0 788 this._updateElements(detectorContainer.childNodes, currentDetector);
michael@0 789 },
michael@0 790 _updateElements: function(aElements, aCurrentItem) {
michael@0 791 if (!aElements.length) {
michael@0 792 return;
michael@0 793 }
michael@0 794 let disabled = this.maybeDisableMenu(aElements[0].ownerDocument);
michael@0 795 for (let elem of aElements) {
michael@0 796 if (disabled) {
michael@0 797 elem.setAttribute("disabled", "true");
michael@0 798 } else {
michael@0 799 elem.removeAttribute("disabled");
michael@0 800 }
michael@0 801 if (elem.value.toLowerCase() == aCurrentItem.toLowerCase()) {
michael@0 802 elem.setAttribute("checked", "true");
michael@0 803 } else {
michael@0 804 elem.removeAttribute("checked");
michael@0 805 }
michael@0 806 }
michael@0 807 },
michael@0 808 onViewShowing: function(aEvent) {
michael@0 809 let document = aEvent.target.ownerDocument;
michael@0 810
michael@0 811 let autoDetectLabelId = "PanelUI-characterEncodingView-autodetect-label";
michael@0 812 let autoDetectLabel = document.getElementById(autoDetectLabelId);
michael@0 813 if (!autoDetectLabel.hasAttribute("value")) {
michael@0 814 let label = CharsetBundle.GetStringFromName("charsetMenuAutodet");
michael@0 815 autoDetectLabel.setAttribute("value", label);
michael@0 816 this.populateList(document,
michael@0 817 "PanelUI-characterEncodingView-pinned",
michael@0 818 "pinnedCharsets");
michael@0 819 this.populateList(document,
michael@0 820 "PanelUI-characterEncodingView-charsets",
michael@0 821 "otherCharsets");
michael@0 822 this.populateList(document,
michael@0 823 "PanelUI-characterEncodingView-autodetect",
michael@0 824 "detectors");
michael@0 825 }
michael@0 826 this.updateCurrentDetector(document);
michael@0 827 this.updateCurrentCharset(document);
michael@0 828 },
michael@0 829 onCommand: function(aEvent) {
michael@0 830 let node = aEvent.target;
michael@0 831 if (!node.hasAttribute || !node.section) {
michael@0 832 return;
michael@0 833 }
michael@0 834
michael@0 835 let window = node.ownerDocument.defaultView;
michael@0 836 let section = node.section;
michael@0 837 let value = node.value;
michael@0 838
michael@0 839 // The behavior as implemented here is directly based off of the
michael@0 840 // `MultiplexHandler()` method in browser.js.
michael@0 841 if (section != "detectors") {
michael@0 842 window.BrowserSetForcedCharacterSet(value);
michael@0 843 } else {
michael@0 844 // Set the detector pref.
michael@0 845 try {
michael@0 846 let str = Cc["@mozilla.org/supports-string;1"]
michael@0 847 .createInstance(Ci.nsISupportsString);
michael@0 848 str.data = value;
michael@0 849 Services.prefs.setComplexValue("intl.charset.detector", Ci.nsISupportsString, str);
michael@0 850 } catch (e) {
michael@0 851 Cu.reportError("Failed to set the intl.charset.detector preference.");
michael@0 852 }
michael@0 853 // Prepare a browser page reload with a changed charset.
michael@0 854 window.BrowserCharsetReload();
michael@0 855 }
michael@0 856 },
michael@0 857 onCreated: function(aNode) {
michael@0 858 const kPanelId = "PanelUI-popup";
michael@0 859 let document = aNode.ownerDocument;
michael@0 860
michael@0 861 let updateButton = () => {
michael@0 862 if (this.maybeDisableMenu(document))
michael@0 863 aNode.setAttribute("disabled", "true");
michael@0 864 else
michael@0 865 aNode.removeAttribute("disabled");
michael@0 866 };
michael@0 867
michael@0 868 if (this.currentArea == CustomizableUI.AREA_PANEL) {
michael@0 869 let panel = document.getElementById(kPanelId);
michael@0 870 panel.addEventListener("popupshowing", updateButton);
michael@0 871 }
michael@0 872
michael@0 873 let listener = {
michael@0 874 onWidgetAdded: (aWidgetId, aArea) => {
michael@0 875 if (aWidgetId != this.id)
michael@0 876 return;
michael@0 877 if (aArea == CustomizableUI.AREA_PANEL) {
michael@0 878 let panel = document.getElementById(kPanelId);
michael@0 879 panel.addEventListener("popupshowing", updateButton);
michael@0 880 }
michael@0 881 },
michael@0 882 onWidgetRemoved: (aWidgetId, aPrevArea) => {
michael@0 883 if (aWidgetId != this.id)
michael@0 884 return;
michael@0 885 aNode.removeAttribute("disabled");
michael@0 886 if (aPrevArea == CustomizableUI.AREA_PANEL) {
michael@0 887 let panel = document.getElementById(kPanelId);
michael@0 888 panel.removeEventListener("popupshowing", updateButton);
michael@0 889 }
michael@0 890 },
michael@0 891 onWidgetInstanceRemoved: (aWidgetId, aDoc) => {
michael@0 892 if (aWidgetId != this.id || aDoc != document)
michael@0 893 return;
michael@0 894
michael@0 895 CustomizableUI.removeListener(listener);
michael@0 896 let panel = aDoc.getElementById(kPanelId);
michael@0 897 panel.removeEventListener("popupshowing", updateButton);
michael@0 898 }
michael@0 899 };
michael@0 900 CustomizableUI.addListener(listener);
michael@0 901 if (!this.charsetInfo) {
michael@0 902 this.charsetInfo = CharsetMenu.getData();
michael@0 903 }
michael@0 904 }
michael@0 905 }, {
michael@0 906 id: "email-link-button",
michael@0 907 tooltiptext: "email-link-button.tooltiptext3",
michael@0 908 onCommand: function(aEvent) {
michael@0 909 let win = aEvent.view;
michael@0 910 win.MailIntegration.sendLinkForWindow(win.content);
michael@0 911 }
michael@0 912 }];
michael@0 913
michael@0 914 #ifdef XP_WIN
michael@0 915 #ifdef MOZ_METRO
michael@0 916 if (Services.metro && Services.metro.supported) {
michael@0 917 let widgetArgs = {tooltiptext: "switch-to-metro-button2.tooltiptext"};
michael@0 918 let brandShortName = BrandBundle.GetStringFromName("brandShortName");
michael@0 919 let metroTooltip = CustomizableUI.getLocalizedProperty(widgetArgs, "tooltiptext",
michael@0 920 [brandShortName]);
michael@0 921 CustomizableWidgets.push({
michael@0 922 id: "switch-to-metro-button",
michael@0 923 label: "switch-to-metro-button2.label",
michael@0 924 tooltiptext: metroTooltip,
michael@0 925 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 926 showInPrivateBrowsing: false, /* See bug 928068 */
michael@0 927 onCommand: function(aEvent) {
michael@0 928 let win = aEvent.view;
michael@0 929 if (win && typeof win.SwitchToMetro == "function") {
michael@0 930 win.SwitchToMetro();
michael@0 931 }
michael@0 932 }
michael@0 933 });
michael@0 934 }
michael@0 935 #endif
michael@0 936 #endif
michael@0 937
michael@0 938 #ifdef NIGHTLY_BUILD
michael@0 939 /**
michael@0 940 * The e10s button's purpose is to lower the barrier of entry
michael@0 941 * for our Nightly testers to use e10s windows. We'll be removing it
michael@0 942 * once remote tabs are enabled. This button should never ever make it
michael@0 943 * to production. If it does, that'd be bad, and we should all feel bad.
michael@0 944 */
michael@0 945 if (Services.prefs.getBoolPref("browser.tabs.remote")) {
michael@0 946 let getCommandFunction = function(aOpenRemote) {
michael@0 947 return function(aEvent) {
michael@0 948 let win = aEvent.view;
michael@0 949 if (win && typeof win.OpenBrowserWindow == "function") {
michael@0 950 win.OpenBrowserWindow({remote: aOpenRemote});
michael@0 951 }
michael@0 952 };
michael@0 953 }
michael@0 954
michael@0 955 let openRemote = !Services.prefs.getBoolPref("browser.tabs.remote.autostart");
michael@0 956 // Like the XUL menuitem counterparts, we hard-code these strings in because
michael@0 957 // this button should never roll into production.
michael@0 958 let buttonLabel = openRemote ? "New e10s Window"
michael@0 959 : "New Non-e10s Window";
michael@0 960
michael@0 961 CustomizableWidgets.push({
michael@0 962 id: "e10s-button",
michael@0 963 label: buttonLabel,
michael@0 964 tooltiptext: buttonLabel,
michael@0 965 defaultArea: CustomizableUI.AREA_PANEL,
michael@0 966 onCommand: getCommandFunction(openRemote),
michael@0 967 });
michael@0 968 }
michael@0 969 #endif

mercurial