Bug 1313429 - Implements basic Touch Bar functionality via JS and exposes customization via a string preference. r?spohl,mikedeboer,amin draft
authorHarry Twyford <htwyford@mozilla.com>
Tue, 24 Jul 2018 10:28:28 -0400
changeset 823207 22ecb19cb2937a9e749ce049657becf076fcfa60
parent 822009 cb59a65fb720ee100bb03cc9f4b02e645755786b
child 823208 d50256d6c01689b3ac4d11d0a650b5fe073de327
push id117610
push userbmo:htwyford@mozilla.com
push dateThu, 26 Jul 2018 20:33:17 +0000
reviewersspohl, mikedeboer, amin
bugs1313429
milestone63.0a1
Bug 1313429 - Implements basic Touch Bar functionality via JS and exposes customization via a string preference. r?spohl,mikedeboer,amin MozReview-Commit-ID: 2GSeKcbg6sB
browser/base/content/browser-places.js
browser/base/content/browser.js
browser/base/content/test/static/browser_all_files_referenced.js
browser/components/moz.build
browser/components/touchbar/MacTouchBar.js
browser/components/touchbar/MacTouchBar.manifest
browser/components/touchbar/moz.build
browser/components/touchbar/tests/.eslintrc.js
browser/components/touchbar/tests/browser/browser.ini
browser/components/touchbar/tests/browser/browser_touchbar_tests.js
browser/components/touchbar/tests/browser/readerModeArticle.html
browser/installer/package-manifest.in
browser/modules/ReaderParent.jsm
modules/libpref/init/all.js
python/mozbuild/mozpack/packager/formats.py
toolkit/library/moz.build
toolkit/locales/en-US/chrome/global/touchbar.properties
toolkit/locales/jar.mn
widget/cocoa/moz.build
widget/cocoa/nsCocoaWindow.mm
widget/cocoa/nsTouchBar.h
widget/cocoa/nsTouchBar.mm
widget/cocoa/nsTouchBarUpdater.h
widget/cocoa/nsTouchBarUpdater.mm
widget/cocoa/nsWidgetFactory.mm
widget/cocoa/touchbar/back.pdf
widget/cocoa/touchbar/bookmark-filled.pdf
widget/cocoa/touchbar/bookmark.pdf
widget/cocoa/touchbar/forward.pdf
widget/cocoa/touchbar/fullscreen.pdf
widget/cocoa/touchbar/home.pdf
widget/cocoa/touchbar/new.pdf
widget/cocoa/touchbar/private-browsing.pdf
widget/cocoa/touchbar/reader-mode.pdf
widget/cocoa/touchbar/refresh.pdf
widget/cocoa/touchbar/search.pdf
widget/cocoa/touchbar/share.pdf
widget/cocoa/touchbar/sidebar-left.pdf
widget/cocoa/touchbar/sidebar-right.pdf
widget/moz.build
widget/nsITouchBarHelper.idl
widget/nsITouchBarInput.idl
widget/nsITouchBarUpdater.idl
widget/nsWidgetsCID.h
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1494,21 +1494,23 @@ var BookmarkingUI = {
        });
   },
 
   _updateStar: function BUI__updateStar() {
     if (this._itemGuids.size > 0) {
       this.broadcaster.setAttribute("starred", "true");
       this.broadcaster.setAttribute("buttontooltiptext", this._starredTooltip);
       this.broadcaster.setAttribute("tooltiptext", this._starredTooltip);
+      Services.obs.notifyObservers(null, "bookmark-icon-updated", "starred");
     } else {
       this.star.removeAttribute("animate");
       this.broadcaster.removeAttribute("starred");
       this.broadcaster.setAttribute("buttontooltiptext", this._unstarredTooltip);
       this.broadcaster.setAttribute("tooltiptext", this._unstarredTooltip);
+      Services.obs.notifyObservers(null, "bookmark-icon-updated", "unstarred");
     }
   },
 
   /**
    * forceReset is passed when we're destroyed and the label should go back
    * to the default (Bookmark This Page) for OS X.
    */
   updateBookmarkPageMenuItem: function BUI_updateBookmarkPageMenuItem(forceReset) {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -1917,16 +1917,17 @@ var gBrowserInit = {
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-confirmation");
       Services.obs.removeObserver(gXPInstallObserver, "addon-install-complete");
       window.messageManager.removeMessageListener("Browser:URIFixup", gKeywordURIFixup);
       window.messageManager.removeMessageListener("Browser:LoadURI", RedirectLoad);
 
       if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
         MenuTouchModeObserver.uninit();
       }
+
       BrowserOffline.uninit();
       IndexedDBPromptHelper.uninit();
       CanvasPermissionPromptHelper.uninit();
       WebAuthnPromptHelper.uninit();
       PanelUI.uninit();
       AutoShowBookmarksToolbar.uninit();
     }
 
@@ -4816,16 +4817,17 @@ var XULBrowserWindow = {
       if (location == "about:blank" &&
           gBrowser.selectedTab.hasAttribute("customizemode")) {
         gCustomizeMode.enter();
       } else if (CustomizationHandler.isEnteringCustomizeMode ||
                  CustomizationHandler.isCustomizing()) {
         gCustomizeMode.exit();
       }
     }
+    Services.obs.notifyObservers(null, "touchbar-location-change", location);
     UpdateBackForwardCommands(gBrowser.webNavigation);
     ReaderParent.updateReaderButton(gBrowser.selectedBrowser);
 
     if (!gMultiProcessBrowser) // Bug 1108553 - Cannot rotate images with e10s
       gGestureSupport.restoreRotationState();
 
     // See bug 358202, when tabs are switched during a drag operation,
     // timers don't fire on windows (bug 203573)
--- a/browser/base/content/test/static/browser_all_files_referenced.js
+++ b/browser/base/content/test/static/browser_all_files_referenced.js
@@ -37,18 +37,20 @@ var gExceptionPaths = [
   "resource://formautofill/addressmetadata/",
 
   // Exclude all search-plugins because they aren't referenced by filename
   "resource://search-plugins/",
 ];
 
 // These are not part of the omni.ja file, so we find them only when running
 // the test on a non-packaged build.
-if (AppConstants.platform == "macosx")
+if (AppConstants.platform == "macosx") {
   gExceptionPaths.push("resource://gre/res/cursors/");
+  gExceptionPaths.push("resource://gre/res/touchbar/");
+}
 
 var whitelist = [
   // browser/extensions/pdfjs/content/PdfStreamConverter.jsm
   {file: "chrome://pdf.js/locale/chrome.properties"},
   {file: "chrome://pdf.js/locale/viewer.properties"},
 
   // security/manager/pki/resources/content/device_manager.js
   {file: "chrome://pippki/content/load_device.xul"},
@@ -56,16 +58,17 @@ var whitelist = [
   // The l10n build system can't package string files only for some platforms.
   // See bug 1339424 for why this is hard to fix.
   {file: "chrome://global/locale/fallbackMenubar.properties",
    platforms: ["linux", "win"]},
   {file: "chrome://global/locale/printPageSetup.dtd", platforms: ["linux", "macosx"]},
   {file: "chrome://global/locale/printPreviewProgress.dtd",
    platforms: ["macosx"]},
   {file: "chrome://global/locale/printProgress.dtd", platforms: ["macosx"]},
+  {file: "chrome://global/locale/touchbar.properties", platforms: ["macosx"]},
 
   // toolkit/content/aboutRights-unbranded.xhtml doesn't use aboutRights.css
   {file: "chrome://global/skin/aboutRights.css", skipUnofficial: true},
 
   // devtools/client/inspector/bin/dev-server.js
   {file: "chrome://devtools/content/inspector/markup/markup.xhtml",
    isFromDevTools: true},
 
--- a/browser/components/moz.build
+++ b/browser/components/moz.build
@@ -57,16 +57,19 @@ DIRS += [
     'translation',
 ]
 
 DIRS += ['build']
 
 if CONFIG['NIGHTLY_BUILD']:
     DIRS += ['payments']
 
+if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'cocoa':
+    DIRS += ['touchbar']
+
 XPIDL_SOURCES += [
     'nsIBrowserHandler.idl',
 ]
 
 XPIDL_MODULE = 'browsercompsbase'
 
 EXTRA_PP_COMPONENTS += [
     'BrowserComponents.manifest',
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/MacTouchBar.js
@@ -0,0 +1,373 @@
+/* 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/. */
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
+
+XPCOMUtils.defineLazyModuleGetters(this, {
+  BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
+  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
+});
+
+function execCommand(aCommandName) {
+  let win = BrowserWindowTracker.getTopWindow();
+  let command = win.document.getElementById(aCommandName);
+  if (command) {
+    command.doCommand();
+  }
+}
+
+/**
+ * JS-implemented TouchBarHelper class.
+ * Provides services to the Mac Touch Bar.
+ */
+function TouchBarHelper() {
+  this._init();
+}
+
+TouchBarHelper.prototype = {
+  classDescription: "Services the Mac Touch Bar",
+  classID: Components.ID("{ea109912-3acc-48de-b679-c23b6a122da5}"),
+  contractID: "@mozilla.org/widget/touchbarhelper;1",
+  QueryInterface: ChromeUtils.generateQI([Ci.nsITouchBarHelper]),
+  activeUrl: "",
+
+  /**
+   * An object containing all implemented TouchBarInput objects.
+   */
+  _implementedInputs: {
+    "Back": {
+      title: "back",
+      image: "back.pdf",
+      type: "button",
+      callback: () => execCommand("Browser:Back")
+    },
+    "Forward": {
+      title: "forward",
+      image: "forward.pdf",
+      type: "button",
+      callback: () => execCommand("Browser:Forward"),
+    },
+    "Reload": {
+      title: "reload",
+      image: "refresh.pdf",
+      type: "button",
+      callback: () => execCommand("Browser:Reload"),
+    },
+    "Home": {
+      title: "home",
+      image: "home.pdf",
+      type: "button",
+      callback: () => execCommand("Browser:Home"),
+    },
+    "Fullscreen": {
+      title: "fullScreen",
+      image: "fullscreen.pdf",
+      type: "button",
+      callback: () => execCommand("View:FullScreen"),
+    },
+    "Find": {
+      title: "find",
+      image: "search.pdf",
+      type: "button",
+      callback: () => execCommand("cmd_find"),
+    },
+    "NewTab": {
+      title: "newTab",
+      image: "new.pdf",
+      type: "button",
+      callback: () => execCommand("cmd_newNavigatorTabNoEvent"),
+    },
+    "Sidebar": {
+      title: "openBookmarksSidebar",
+      image: "sidebar-left.pdf",
+      type: "button",
+      callback: () => execCommand("viewBookmarksSidebar"),
+    },
+    "AddBookmark": {
+      title: "addBookmark",
+      image: "bookmark.pdf",
+      type: "button",
+      callback: () => execCommand("Browser:AddBookmarkAs"),
+    },
+    "ReaderView": {
+      title: "readerView",
+      image: "reader-mode.pdf",
+      type: "button",
+      callback: () => execCommand("View:ReaderView"),
+      disabled: true,  // Updated when the page is found to be Reader View-able
+    },
+    "OpenLocation": {
+      title: "openLocation",
+      image: "search.pdf",
+      type: "mainButton",
+      callback: () => execCommand("Browser:OpenLocation"),
+    },
+    "Focus": {
+      title: "focus",
+      image: "private-browsing.pdf",
+      type: "mainButton",
+      callback: () => execCommand("cmd_closeWindow"),
+      color: "#8000D7",
+      context: () => {
+        let name;
+        if (PrivateBrowsingUtils.isWindowPrivate(
+            BrowserWindowTracker.getTopWindow())) {
+          name = "Focus";
+        }
+        return name;
+      },
+    },
+    "OpenOrFocus": {
+      // this input is just a forwarder to other inputs
+      context: () => {
+        let name;
+        if (PrivateBrowsingUtils.isWindowPrivate(
+            BrowserWindowTracker.getTopWindow())) {
+          name = "Focus";
+        } else {
+          name = "OpenLocation";
+        }
+        return name;
+      },
+    },
+    // This is a special-case `type: "scrubber"` element.
+    // Scrubbers are not yet generally implemented.
+    "Share": {
+      title: "share",
+      type: "scrubber",
+      image: "share.pdf",
+      callback: () => execCommand("cmd_share"),
+    },
+  },
+
+  get activeTitle() {
+    let tabbrowser = this.window.ownerGlobal.gBrowser;
+    let activeTitle;
+    if (tabbrowser) {
+      activeTitle = tabbrowser.selectedBrowser.contentTitle;
+    }
+    return activeTitle;
+  },
+
+  get layout() {
+    let prefArray = this._getPrefLayoutArray();
+
+    let layoutItems = Cc["@mozilla.org/array;1"]
+                      .createInstance(Ci.nsIMutableArray);
+    for (let inputName of prefArray) {
+      if (typeof(this._implementedInputs[inputName].context) == "function") {
+        inputName = this._implementedInputs[inputName].context();
+      }
+      let input = this.getTouchBarInput(inputName);
+      if (!input) {
+        continue;
+      }
+      layoutItems.appendElement(input);
+    }
+
+    return layoutItems;
+  },
+
+  get window() {
+    return BrowserWindowTracker.getTopWindow();
+  },
+
+  get bookmarkingUI() {
+    return this.window.BookmarkingUI;
+  },
+
+  _init() {
+    Services.obs.addObserver(this, "bookmark-icon-updated");
+    Services.obs.addObserver(this, "reader-mode-available");
+    Services.obs.addObserver(this, "touchbar-location-change");
+    Services.obs.addObserver(this, "quit-application");
+  },
+
+  _uninit() {
+    Services.obs.removeObserver(this, "bookmark-icon-updated");
+    Services.obs.removeObserver(this, "reader-mode-available");
+    Services.obs.removeObserver(this, "touchbar-location-change");
+    Services.obs.removeObserver(this, "quit-application");
+  },
+
+  /**
+   * Returns a string array of the user's Touch Bar layout preference.
+   */
+  _getPrefLayoutArray() {
+    const {Preferences} =
+      ChromeUtils.import("resource://gre/modules/Preferences.jsm", {});
+    let layoutString = Preferences.get("ui.touchbar.layout");
+
+    let prefArray = layoutString.split(",");
+    prefArray = prefArray.map(str => str.trim());
+    // remove duplicates
+    prefArray = Array.from(new Set(prefArray));
+
+    // remove unimplemented/mispelled inputs
+    prefArray = prefArray.filter(input =>
+      Object.keys(this._implementedInputs).includes(input));
+    return prefArray;
+  },
+
+  getTouchBarInput(aInputName) {
+    let iImp = this._implementedInputs[aInputName];
+    if (!iImp) {
+      return null;
+    }
+    let item = new TouchBarInput(iImp.title,
+                                  iImp.image,
+                                  iImp.type,
+                                  iImp.callback,
+                                  iImp.color,
+                                  iImp.disabled);
+
+    return item;
+  },
+
+  /**
+   * Fetches a specific Touch Bar Input by name and updates it on the Touch Bar.
+   */
+  _updateTouchBarInput(aInputName) {
+    if (typeof(this._implementedInputs[aInputName].context) == "function") {
+      aInputName = this._implementedInputs[aInputName].context();
+    }
+    let input = this.getTouchBarInput(aInputName);
+    if (!input) {
+      return;
+    }
+    let shell = this.window.ownerGlobal.getInterface(Ci.nsIDocShell);
+    let updater = Cc["@mozilla.org/widget/touchbarupdater;1"]
+                  .getService(Ci.nsITouchBarUpdater);
+    updater.updateTouchBarInput(shell, input);
+  },
+
+  observe(subject, topic, data) {
+    switch (topic) {
+      case "touchbar-location-change":
+        this.activeUrl = data;
+        if (data.startsWith("about:reader")) {
+          this._implementedInputs.ReaderView.disabled = false;
+          this._updateTouchBarInput("ReaderView");
+        } else {
+          // Reader mode available event fires after, so may be updated again
+          this._implementedInputs.ReaderView.disabled = true;
+          this._updateTouchBarInput("ReaderView");
+        }
+        break;
+      case "bookmark-icon-updated":
+        data == "starred" ?
+          this._implementedInputs.AddBookmark.image = "bookmark-filled.pdf"
+          : this._implementedInputs.AddBookmark.image = "bookmark.pdf";
+        this._updateTouchBarInput("AddBookmark");
+        break;
+      case "reader-mode-available":
+        this._implementedInputs.ReaderView.disabled = false;
+        this._updateTouchBarInput("ReaderView");
+        break;
+      case "quit-application":
+        this._uninit();
+        break;
+    }
+  },
+};
+
+/**
+ * A representation of a Touch Bar input.
+ *     @param {string} title
+ *            The lookup key for the button's localized text title.
+ *            Localizations are found in
+ *            /toolkit/locales/LOCALE/chrome/global/touchbar.properties.
+ *     @param {string} image
+ *            The name of a icon file added to
+ *            /widget/cocoa/resources/touchbar_icons.
+ *     @param {string} type
+ *            The type of Touch Bar input represented by the object.
+ *            One of `button`, `mainButton`.
+ *     @param {Function} callback
+ *            A callback invoked when a touchbar item is touched.
+ *     @param {string} color (optional)
+ *            A string in hex format specifying the button's background color.
+ *            If omitted, the default background color is used.
+ *     @param {bool} disabled (optional)
+ *            If `true`, the Touch Bar input is greyed out and inoperable.
+ */
+function TouchBarInput(aTitle, aImage, aType, aCallback,
+    aColor, aDisabled = false) {
+  this._key = aTitle;
+  this._title = aTitle;
+  this._image = aImage;
+  this._type = aType;
+  this._callback = aCallback;
+  this._color = this.hexToInt(aColor);
+  this._disabled = aDisabled;
+}
+
+TouchBarInput.prototype = {
+  classDescription: "Represents an input on the Mac Touch Bar",
+  classID: Components.ID("{77441d17-f29c-49d7-982f-f20a5ab5a900}"),
+  contractID: "@mozilla.org/widget/touchbarinput;1",
+  QueryInterface: ChromeUtils.generateQI([Ci.nsITouchBarInput]),
+  bundle: Services.strings.createBundle(
+    "chrome://global/locale/touchbar.properties"),
+  _title: "",
+  _image: "",
+  _type: "",
+  _callback: () => {},
+  _color: 0,
+  _disabled: false,
+  get key() {
+    return this._key;
+  },
+  get title() {
+    return this.bundle.GetStringFromName(this._title) || this._title;
+  },
+  set title(aTitle) {
+    this._title = aTitle;
+  },
+  get image() {
+    return this._image;
+  },
+  set image(aImage) {
+    this._image = aImage;
+  },
+  get type() {
+    return this._type == "" ? "button" : this._type;
+  },
+  set type(aType) {
+    this._type = aType;
+  },
+  get callback() {
+    return this._callback;
+  },
+  set callback(aCallback) {
+    this._callback = aCallback;
+  },
+  get color() {
+    return this._color;
+  },
+  set color(aColor) {
+    this._color = this.hexToInt(aColor);
+  },
+  get disabled() {
+    return this._disabled || false;
+  },
+  set disabled(aDisabled) {
+    this._disabled = aDisabled;
+  },
+  hexToInt(aHexString) {
+    if (!aHexString) {
+      return null;
+    }
+    if (aHexString.charAt(0) == "#") {
+      aHexString = aHexString.slice(1);
+    }
+    let val = parseInt(aHexString, 16);
+    return isNaN(val) ? null : val;
+  },
+};
+
+var components = [TouchBarHelper, TouchBarInput];
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/MacTouchBar.manifest
@@ -0,0 +1,5 @@
+component {ea109912-3acc-48de-b679-c23b6a122da5} MacTouchBar.js
+contract @mozilla.org/widget/touchbarhelper;1 {ea109912-3acc-48de-b679-c23b6a122da5}
+
+component {77441d17-f29c-49d7-982f-f20a5ab5a900} MacTouchBar.js
+contract @mozilla.org/widget/touchbarinput;1 {77441d17-f29c-49d7-982f-f20a5ab5a900}
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/moz.build
@@ -0,0 +1,15 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+with Files('**'):
+    BUG_COMPONENT = ('Core', 'Widget: Cocoa')
+
+BROWSER_CHROME_MANIFESTS += ['tests/browser/browser.ini']
+
+EXTRA_COMPONENTS += [
+    'MacTouchBar.js',
+    'MacTouchBar.manifest',
+]
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/tests/.eslintrc.js
@@ -0,0 +1,7 @@
+"use strict";
+
+module.exports = {
+  "extends": [
+    "plugin:mozilla/browser-test"
+  ]
+};
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/tests/browser/browser.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+support-files =
+  readerModeArticle.html
+
+[browser_touchbar_tests.js]
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/tests/browser/browser_touchbar_tests.js
@@ -0,0 +1,156 @@
+/**
+ * Tests implementations of TouchBarHelper and TouchBarInput
+ * in MacTouchBar.js.
+ */
+
+const PREF_NAME = "ui.touchbar.layout";
+
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "TouchBarHelper",
+                                   "@mozilla.org/widget/touchbarhelper;1",
+                                   "nsITouchBarHelper");
+XPCOMUtils.defineLazyServiceGetter(this, "TouchBarInput",
+                                   "@mozilla.org/widget/touchbarinput;1",
+                                   "nsITouchBarInput");
+
+function is_element_visible(aElement, aMsg) {
+  isnot(aElement, null, "Element should not be null when checking visibility");
+  ok(!BrowserTestUtils.is_hidden(aElement), aMsg);
+}
+
+function is_element_hidden(aElement, aMsg) {
+  isnot(aElement, null, "Element should not be null when checking visibility");
+  ok(BrowserTestUtils.is_hidden(aElement), aMsg);
+}
+
+function waitForCondition(condition, nextTest, errorMsg, retryTimes) {
+  retryTimes = typeof retryTimes !== "undefined" ? retryTimes : 30;
+  var tries = 0;
+  var interval = setInterval(function() {
+    if (tries >= retryTimes) {
+      ok(false, errorMsg);
+      moveOn();
+    }
+    var conditionPassed;
+    try {
+      conditionPassed = condition();
+    } catch (e) {
+      ok(false, e + "\n" + e.stack);
+      conditionPassed = false;
+    }
+    if (conditionPassed) {
+      moveOn();
+    }
+    tries++;
+  }, 100);
+  var moveOn = function() { clearInterval(interval); nextTest(); };
+}
+
+function promiseWaitForCondition(aConditionFn) {
+  return new Promise(resolve => {
+    waitForCondition(aConditionFn, resolve, "Condition didn't pass.");
+  });
+}
+
+/**
+ * Sets the pref to contain errors. .layout should contain only the
+ * non-erroneous elements.
+ */
+add_task(async function setWrongPref() {
+  registerCleanupFunction(function() {
+    Services.prefs.deleteBranch(PREF_NAME);
+  });
+
+  let wrongValue   = "Back, Back, Forwrd, NewTab, Unimplemented,";
+  let correctValue = ["back", "newTab"];
+  let testValue = [];
+  Services.prefs.setStringPref(PREF_NAME, wrongValue);
+
+  let layoutItems = Cc["@mozilla.org/array;1"]
+                      .createInstance(Ci.nsIMutableArray);
+  layoutItems = TouchBarHelper.layout;
+  for (let i = 0; i < layoutItems.length; i++) {
+    let input = layoutItems.queryElementAt(i, Ci.nsITouchBarInput);
+    testValue.push(input.key);
+  }
+  Assert.equal(testValue.toString(),
+               correctValue.toString(),
+               "Pref should filter out incorrect inputs.");
+});
+
+/**
+ * Tests if our bookmark button updates with our event.
+ */
+add_task(async function updateBookmarkButton() {
+  Services.obs.notifyObservers(null, "bookmark-icon-updated", "starred");
+  Assert.equal(TouchBarHelper.getTouchBarInput("AddBookmark").image,
+    "bookmark-filled.pdf",
+    "AddBookmark image should be filled bookmark after event.");
+
+  Services.obs.notifyObservers(null, "bookmark-icon-updated", "unstarred");
+  Assert.equal(TouchBarHelper.getTouchBarInput("AddBookmark").image,
+    "bookmark.pdf",
+    "AddBookmark image should be unfilled bookmark after event.");
+});
+
+const TEST_PREFS = [
+  ["reader.parse-on-load.enabled", true]
+];
+
+/**
+ * Tests if our Reader View button updates when a page can be reader viewed.
+ */
+add_task(async function updateReaderView() {
+  registerCleanupFunction(function() {
+    // Reset test prefs.
+    TEST_PREFS.forEach(([name, value]) => {
+      Services.prefs.clearUserPref(name);
+    });
+    while (gBrowser.tabs.length > 1) {
+      gBrowser.removeCurrentTab();
+    }
+  });
+
+  // Set required test prefs.
+  TEST_PREFS.forEach(([name, value]) => {
+    Services.prefs.setBoolPref(name, value);
+  });
+
+  // The page actions reader mode button
+  var readerButton = document.getElementById("reader-mode-button");
+  is_element_hidden(readerButton, "Reader Mode button should be hidden.");
+
+  Assert.equal(TouchBarHelper.getTouchBarInput("ReaderView").disabled,
+    true,
+    "ReaderView Touch Bar button should be disabled by default.");
+
+  const TEST_PATH = getRootDirectory(gTestPath)
+  .replace("chrome://mochitests/content", "http://example.com");
+  let url = TEST_PATH + "readerModeArticle.html";
+  await BrowserTestUtils.withNewTab(url, async function() {
+    await promiseWaitForCondition(() => !readerButton.hidden);
+
+    Assert.equal(TouchBarHelper.getTouchBarInput("ReaderView").disabled,
+    false,
+    "ReaderView Touch Bar button should be enabled on reader-able pages.");
+  });
+});
+
+/**
+ * Ensures that our event listeners are removed when quit-application fires.
+ */
+add_task(async function ensureUninit() {
+  Services.obs.notifyObservers(null, "bookmark-icon-updated", "starred");
+  Assert.equal(TouchBarHelper.getTouchBarInput("AddBookmark").image,
+    "bookmark-filled.pdf",
+    "AddBookmark image should be filled bookmark after event.");
+
+  Services.obs.notifyObservers(null, "quit-application");
+
+  Services.obs.notifyObservers(null, "bookmark-icon-updated", "unstarred");
+  Assert.equal(TouchBarHelper.getTouchBarInput("AddBookmark").image,
+    "bookmark-filled.pdf",
+    "AddBookmark image should be filled bookmark since listener is closed.");
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/touchbar/tests/browser/readerModeArticle.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Article title</title>
+<meta name="description" content="This is the article description." />
+</head>
+<body>
+<header>Site header</header>
+<div>
+<h1>Article title</h1>
+<ul>
+  <li><a id="foo-anchor" href="#foo">by John Doe</a></li>
+</ul>
+<h2 class="author">by Jane Doe</h2>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p id="foo">by John Doe</p>
+<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
+</div>
+</body>
+</html>
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -281,16 +281,18 @@
 @RESPATH@/browser/components/FirefoxProfileMigrator.js
 #ifdef XP_WIN
 @RESPATH@/browser/components/360seProfileMigrator.js
 @RESPATH@/browser/components/EdgeProfileMigrator.js
 @RESPATH@/browser/components/IEProfileMigrator.js
 #endif
 #ifdef XP_MACOSX
 @RESPATH@/browser/components/SafariProfileMigrator.js
+@RESPATH@/browser/components/MacTouchBar.manifest
+@RESPATH@/browser/components/MacTouchBar.js
 #endif
 @RESPATH@/components/nsINIProcessor.manifest
 @RESPATH@/components/nsINIProcessor.js
 @RESPATH@/components/nsPrompter.manifest
 @RESPATH@/components/nsPrompter.js
 @RESPATH@/components/SyncComponents.manifest
 @RESPATH@/components/Weave.js
 @RESPATH@/components/FxAccountsComponents.manifest
@@ -486,16 +488,17 @@
 @RESPATH@/res/table-remove-column-hover.gif
 @RESPATH@/res/table-remove-column.gif
 @RESPATH@/res/table-remove-row-active.gif
 @RESPATH@/res/table-remove-row-hover.gif
 @RESPATH@/res/table-remove-row.gif
 @RESPATH@/res/grabber.gif
 #ifdef XP_MACOSX
 @RESPATH@/res/cursors/*
+@RESPATH@/res/touchbar/*
 #endif
 @RESPATH@/res/fonts/*
 @RESPATH@/res/dtd/*
 @RESPATH@/res/language.properties
 #ifdef XP_MACOSX
 @RESPATH@/res/MainMenu.nib/
 #endif
 
--- a/browser/modules/ReaderParent.jsm
+++ b/browser/modules/ReaderParent.jsm
@@ -68,26 +68,28 @@ var ReaderParent = {
       button.setAttribute("readeractive", true);
       button.hidden = false;
       let closeText = gStringBundle.GetStringFromName("readerView.close");
       command.setAttribute("label", closeText);
       command.setAttribute("hidden", false);
       command.setAttribute("accesskey", gStringBundle.GetStringFromName("readerView.close.accesskey"));
       key.setAttribute("disabled", false);
       browser.setAttribute("aria-reader", "active");
+      Services.obs.notifyObservers(null, "reader-mode-available");
     } else {
       button.removeAttribute("readeractive");
       button.hidden = !browser.isArticle;
       let enterText = gStringBundle.GetStringFromName("readerView.enter");
       command.setAttribute("label", enterText);
       command.setAttribute("hidden", !browser.isArticle);
       command.setAttribute("accesskey", gStringBundle.GetStringFromName("readerView.enter.accesskey"));
       key.setAttribute("disabled", !browser.isArticle);
       if (browser.isArticle) {
         browser.setAttribute("aria-reader", "available");
+        Services.obs.notifyObservers(null, "reader-mode-available");
       } else {
         browser.removeAttribute("aria-reader");
       }
     }
   },
 
   forceShowReaderIcon(browser) {
     browser.isArticle = true;
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -272,16 +272,20 @@ pref("ui.click_hold_context_menus", fals
 // Pop up context menu on mouseup instead of mousedown, if that's the OS default.
 // Note: ignored on Windows (context menus always use mouseup)
 pref("ui.context_menus.after_mouseup", false);
 // Duration of timeout of incremental search in menus (ms).  0 means infinite.
 pref("ui.menu.incremental_search.timeout", 1000);
 // If true, all popups won't hide automatically on blur
 pref("ui.popup.disable_autohide", false);
 
+#ifdef XP_MACOSX
+pref("ui.touchbar.layout",    "Back,Reload,OpenOrFocus,AddBookmark,NewTab,Share");
+#endif
+
 pref("browser.display.use_document_fonts",  1);  // 0 = never, 1 = quick, 2 = always
 // 0 = default: always, except in high contrast mode
 // 1 = always
 // 2 = never
 pref("browser.display.document_color_use", 0);
 pref("browser.display.use_system_colors",   false);
 pref("browser.display.foreground_color",    "#000000");
 pref("browser.display.background_color",    "#FFFFFF");
--- a/python/mozbuild/mozpack/packager/formats.py
+++ b/python/mozbuild/mozpack/packager/formats.py
@@ -324,17 +324,19 @@ class OmniJarSubFormatter(PiecemealForma
             return False
         path = mozpath.split(path)
         if path[0] == 'chrome':
             return len(path) == 1 or path[1] != 'icons'
         if path[0] == 'components':
             return path[-1].endswith(('.js', '.xpt'))
         if path[0] == 'res':
             return len(path) == 1 or \
-                (path[1] != 'cursors' and path[1] != 'MainMenu.nib')
+                (path[1] != 'cursors' and \
+                 path[1] != 'touchbar' and \
+                 path[1] != 'MainMenu.nib')
         if path[0] == 'defaults':
             return len(path) != 3 or \
                 not (path[2] == 'channel-prefs.js' and
                      path[1] in ['pref', 'preferences'])
         return path[0] in [
             'modules',
             'dictionaries',
             'greprefs.js',
--- a/toolkit/library/moz.build
+++ b/toolkit/library/moz.build
@@ -68,20 +68,25 @@ def Libxul(name):
     if CONFIG['OS_TARGET'] not in ('OpenBSD', 'WINNT') and CONFIG['LD_IS_BFD']:
         LDFLAGS += [TOPSRCDIR + '/toolkit/library/StaticXULComponents.ld']
 
     Libxul_defines()
 
     if CONFIG['MOZ_NEEDS_LIBATOMIC']:
         OS_LIBS += ['atomic']
 
-    # This option should go away in bug 1290972, but we need to wait until
-    # Rust 1.12 has been released.
+    # TouchBar-related classes are only available in the 10.12.2 SDK and later.
+    # We need to weak link these classes until we've upgraded our SDK to at
+    # least 10.12.2.
     # We're also linking against libresolv to solve bug 1367932.
     if CONFIG['OS_ARCH'] == 'Darwin':
+        LDFLAGS += ['-Wl,-U,_OBJC_CLASS_$_NSTouchBar']
+        LDFLAGS += ['-Wl,-U,_OBJC_CLASS_$_NSSharingServicePickerTouchBarItem']
+        LDFLAGS += ['-Wl,-U,_OBJC_METACLASS_$_NSTouchBar']
+        LDFLAGS += ['-Wl,-U,_OBJC_CLASS_$_NSCustomTouchBarItem']
         LDFLAGS += ['-lresolv']
 
     if CONFIG['MOZ_DEBUG_SYMBOLS'] and CONFIG['CC_TYPE'] in ('msvc', 'clang-cl'):
         LDFLAGS += ['-NATVIS:%s/toolkit/library/gecko.natvis' % TOPSRCDIR]
 
 Libxul('xul')
 
 FORCE_STATIC_LIB = True
new file mode 100644
--- /dev/null
+++ b/toolkit/locales/en-US/chrome/global/touchbar.properties
@@ -0,0 +1,18 @@
+# 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/.
+
+
+back = Back
+forward = Forward
+reload = Reload
+home = Home
+fullScreen = Fullscreen
+find = Find
+newTab = New Tab
+addBookmark = Add Bookmark
+openBookmarksSidebar = Open Bookmarks Sidebar
+readerView = Reader View
+openLocation = Search or enter address
+share = Share
+focus = Close
--- a/toolkit/locales/jar.mn
+++ b/toolkit/locales/jar.mn
@@ -39,16 +39,19 @@
   locale/@AB_CD@/global/datetimebox.dtd                 (%chrome/global/datetimebox.dtd)
   locale/@AB_CD@/global/dialogOverlay.dtd               (%chrome/global/dialogOverlay.dtd)
 #ifndef MOZ_FENNEC
   locale/@AB_CD@/global/editMenuOverlay.dtd             (%chrome/global/editMenuOverlay.dtd)
 #endif
   locale/@AB_CD@/global/extensions.properties           (%chrome/global/extensions.properties)
   locale/@AB_CD@/global/fallbackMenubar.properties      (%chrome/global/fallbackMenubar.properties)
   locale/@AB_CD@/global/filepicker.properties           (%chrome/global/filepicker.properties)
+#ifdef XP_MACOSX
+  locale/@AB_CD@/global/touchbar.properties             (%chrome/global/touchbar.properties)
+#endif
 #ifndef MOZ_FENNEC
   locale/@AB_CD@/global/findbar.dtd                     (%chrome/global/findbar.dtd)
   locale/@AB_CD@/global/findbar.properties              (%chrome/global/findbar.properties)
 #endif
   locale/@AB_CD@/global/globalKeys.dtd                  (%chrome/global/globalKeys.dtd)
   locale/@AB_CD@/global/intl.css                        (%chrome/global/intl.css)
   locale/@AB_CD@/global/intl.properties                 (%chrome/global/intl.properties)
   locale/@AB_CD@/global/keys.properties                 (%chrome/global/keys.properties)
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -49,16 +49,18 @@ UNIFIED_SOURCES += [
     'nsMenuX.mm',
     'nsPrintDialogX.mm',
     'nsPrintSettingsServiceX.mm',
     'nsPrintSettingsX.mm',
     'nsSound.mm',
     'nsStandaloneNativeMenu.mm',
     'nsSystemStatusBarCocoa.mm',
     'nsToolkit.mm',
+    'nsTouchBar.mm',
+    'nsTouchBarUpdater.mm',
     'nsWidgetFactory.mm',
     'nsWindowMap.mm',
     'OSXNotificationCenter.mm',
     'RectTextureImage.mm',
     'ScreenHelperCocoa.mm',
     'SwipeTracker.mm',
     'TextInputHandler.mm',
     'VibrancyManager.mm',
@@ -132,16 +134,33 @@ RESOURCE_FILES.cursors += [
     'cursors/vtIBeam.png',
     'cursors/vtIBeam@2x.png',
     'cursors/zoomIn.png',
     'cursors/zoomIn@2x.png',
     'cursors/zoomOut.png',
     'cursors/zoomOut@2x.png',
 ]
 
+RESOURCE_FILES.touchbar += [
+    'touchbar/back.pdf',
+    'touchbar/bookmark-filled.pdf',
+    'touchbar/bookmark.pdf',
+    'touchbar/forward.pdf',
+    'touchbar/fullscreen.pdf',
+    'touchbar/home.pdf',
+    'touchbar/new.pdf',
+    'touchbar/private-browsing.pdf',
+    'touchbar/reader-mode.pdf',
+    'touchbar/refresh.pdf',
+    'touchbar/search.pdf',
+    'touchbar/share.pdf',
+    'touchbar/sidebar-left.pdf',
+    'touchbar/sidebar-right.pdf',
+]
+
 # These resources go in $(DIST)/bin/res/MainMenu.nib, but we can't use a magic
 # RESOURCE_FILES.MainMenu.nib attribute, since that would put the files in
 # $(DIST)/bin/res/MainMenu/nib. Instead, we call __setattr__ directly to create
 # an attribute with the correct name.
 RESOURCE_FILES.__setattr__('MainMenu.nib', [
     'resources/MainMenu.nib/classes.nib',
     'resources/MainMenu.nib/info.nib',
     'resources/MainMenu.nib/keyedobjects.nib',
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -30,16 +30,17 @@
 #include "nsNativeThemeColors.h"
 #include "nsNativeThemeCocoa.h"
 #include "nsChildView.h"
 #include "nsCocoaFeatures.h"
 #include "nsIScreenManager.h"
 #include "nsIWidgetListener.h"
 #include "nsIPresShell.h"
 #include "VibrancyManager.h"
+#include "nsTouchBar.h"
 
 #include "gfxPlatform.h"
 #include "gfxPrefs.h"
 #include "qcms.h"
 
 #include "mozilla/AutoRestore.h"
 #include "mozilla/BasicEvents.h"
 #include "mozilla/Preferences.h"
@@ -2983,16 +2984,23 @@ static NSMutableSet *gSwizzledFrameViewC
 @interface NSImage(ImageCreationWithDrawingHandler)
 + (NSImage *)imageWithSize:(NSSize)size
                    flipped:(BOOL)drawingHandlerShouldBeCalledWithFlippedContext
             drawingHandler:(BOOL (^)(NSRect dstRect))drawingHandler;
 @end
 
 #endif
 
+#if !defined(MAC_OS_X_VERSION_10_12_2) || \
+    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12_2
+@interface NSView(NSTouchBarProvider)
+- (NSTouchBar*)makeTouchBar;
+@end
+#endif
+
 @interface NSView(NSVisualEffectViewSetMaskImage)
 - (void)setMaskImage:(NSImage*)image;
 @end
 
 @interface BaseWindow(Private)
 - (void)removeTrackingArea;
 - (void)cursorUpdated:(NSEvent*)aEvent;
 - (void)updateContentViewSize;
@@ -3139,16 +3147,21 @@ GetMenuMaskImage()
     // Turn off rounded corner masking.
     NSView* wrapper = [[NSView alloc] initWithFrame:NSZeroRect];
     [self swapOutChildViewWrapper:wrapper];
     [wrapper release];
   }
   mUseMenuStyle = aValue;
 }
 
+- (NSTouchBar*)makeTouchBar
+{
+  return [[nsTouchBar alloc] init];
+}
+
 - (void)setBeingShown:(BOOL)aValue
 {
   mBeingShown = aValue;
 }
 
 - (BOOL)isBeingShown
 {
   return mBeingShown;
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsTouchBar.h
@@ -0,0 +1,171 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#ifndef nsTouchBar_h_
+#define nsTouchBar_h_
+
+#import <Cocoa/Cocoa.h>
+
+#include "nsITouchBarHelper.h"
+#include "nsITouchBarInput.h"
+#include "mozilla/RefPtr.h"
+#include "nsIDocument.h"
+
+#if !defined(MAC_OS_X_VERSION_10_12) || \
+    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12
+@interface NSButton(NewConstructors)
+@property (nonatomic) BOOL imageHugsTitle;
++ (NSButton*)buttonWithTitle:(NSString *)title
+                      target:(id)target
+                      action:(SEL)action;
+@end
+
+@interface NSColor(DisplayP3Colors)
++ (NSColor*)colorWithDisplayP3Red:(CGFloat)red
+                            green:(CGFloat)green
+                             blue:(CGFloat)blue
+                            alpha:(CGFloat)alpha;
+@end
+#endif
+
+#if !defined(MAC_OS_X_VERSION_10_12_2) || \
+    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12_2
+typedef NSString* NSTouchBarItemIdentifier;
+__attribute__((weak_import))
+@interface NSTouchBarItem : NSObject
+- (instancetype)initWithIdentifier:(NSTouchBarItemIdentifier)aIdentifier;
+@end
+ 
+__attribute__((weak_import))
+@interface NSCustomTouchBarItem : NSTouchBarItem
+@property (strong) NSView* view;
+@property (strong) NSString* customizationLabel;
+@end
+
+@protocol NSTouchBarDelegate
+@end
+ 
+__attribute__((weak_import))
+@interface NSTouchBar : NSObject
+@property (strong) NSArray<NSTouchBarItemIdentifier>* defaultItemIdentifiers;
+@property (strong) id<NSTouchBarDelegate> delegate;
+- (NSTouchBarItem*)itemForIdentifier:(NSTouchBarItemIdentifier)aIdentifier;
+@end
+
+@protocol NSSharingServicePickerTouchBarItemDelegate
+@end
+
+__attribute__((weak_import))
+@interface NSSharingServicePickerTouchBarItem : NSTouchBarItem
+@property (strong) id<NSSharingServicePickerTouchBarItemDelegate> delegate;
+@property (strong) NSImage* buttonImage;
+@end
+
+@interface NSButton(TouchBarButton)
+@property (strong) NSColor* bezelColor;
+@end
+#endif
+
+/**
+ * NSObject representation of nsITouchBarInput.
+ */
+@interface TouchBarInput : NSObject
+@property (strong) NSString* key;
+@property (strong) NSString* title;
+@property (strong) NSImage* image;
+@property (strong) NSString* type;
+@property (assign) nsCOMPtr<nsITouchBarInputCallback> callback;
+@property (strong) NSColor* color;
+@property (nonatomic) BOOL disabled;
+
+- (id)initWithKey:(NSString*)aKey
+        withTitle:(NSString*)aTitle
+        withImage:(NSString*)aImage
+         withType:(NSString*)aType
+     withCallback:(nsCOMPtr<nsITouchBarInputCallback>)aCallback
+        withColor:(uint32_t)aColor
+     withDisabled:(BOOL)aDisabled;
+
+- (TouchBarInput*)initWithXPCOM:(nsCOMPtr<nsITouchBarInput>)aInput;
+
+@end
+
+/**
+ * Our TouchBar is its own delegate. This is adequate for our purposes,
+ * since the currentimplementation only defines Touch Bar buttons for the
+ * main Firefox window. If modals and other windows were to have custom
+ * Touch Bar views, each window would have to be a NSTouchBarDelegate so
+ * they could define their own custom sets of buttons.
+ */
+@interface nsTouchBar : NSTouchBar<NSTouchBarDelegate,
+                                   NSSharingServicePickerTouchBarItemDelegate,
+                                   NSSharingServiceDelegate>
+/**
+ * Contains TouchBarInput representations of the inputs currently in
+ * the Touch Bar. Populated in `init` and updated by nsITouchBarUpdater.
+ */
+@property (strong) NSMutableDictionary
+  <NSTouchBarItemIdentifier, TouchBarInput*>* mappedLayoutItems;
+
+/**
+ * Returns an instance of nsTouchBar based on implementation details
+ * fetched from the frontend through nsTouchBarHelper.
+ */
+- (instancetype)init;
+
+/**
+ * Create new a new NSTouchBarItem and adds it to the Touch Bar.
+ * Reads the passed identifier and creates the
+ * appropriate item type (eg. NSCustomTouchBarItem).
+ * Required as a member of NSTouchBarDelegate.
+ */
+- (NSTouchBarItem*)touchBar:(NSTouchBar*)aTouchBar
+      makeItemForIdentifier:(NSTouchBarItemIdentifier)aIdentifier;
+
+/**
+ * Updates an input on the Touch Bar by redirecting to one of the specific
+ * TouchBarItem types updaters.
+ */
+- (void)updateItem:(TouchBarInput*)aInput;
+
+/**
+ * Update or create various subclasses of TouchBarItem.
+ */
+- (NSTouchBarItem*)updateButton:(NSCustomTouchBarItem*)aButton
+                  forIdentifier:(NSTouchBarItemIdentifier)aIdentifier;
+- (NSTouchBarItem*)updateMainButton:(NSCustomTouchBarItem*)aMainButton
+                      forIdentifier:(NSTouchBarItemIdentifier)aIdentifier;
+- (NSTouchBarItem*)makeShareScrubberForIdentifier:
+                        (NSTouchBarItemIdentifier)aIdentifier;
+
+// Redirects button actions to the appropriate handler and handles telemetry.
+- (void)touchBarAction:(id)aSender;
+
+- (NSArray*)itemsForSharingServicePickerTouchBarItem:
+                (NSSharingServicePickerTouchBarItem*)aPickerTouchBarItem;
+
+- (NSArray<NSSharingService*>*)sharingServicePicker:
+                           (NSSharingServicePicker*)aSharingServicePicker
+                            sharingServicesForItems:
+                                          (NSArray*)aItems
+                            proposedSharingServices:
+                       (NSArray<NSSharingService*>*)aProposedServices;
+
+
+/**
+ * Constructs a NSTouchBarItemIdentifiers based on the properties of
+ * a TouchBarInput object.
+ */
++ (NSTouchBarItemIdentifier)getIdentifierFromInput:(TouchBarInput*)aInput;
+
+/**
+ * Retrieves icons from widget/cocoa/touchbar
+ */
++ (NSImage*)getTouchBarIconNamed:(NSString*)aImageName;
+
+@end  // nsTouchBar
+
+#endif // nsTouchBar_h_
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsTouchBar.mm
@@ -0,0 +1,390 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 sw=2 et tw=80: */
+/* 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/. */
+
+#include "nsTouchBar.h"
+
+#include "nsDirectoryServiceDefs.h"
+#include "nsIArray.h"
+#include "nsArrayUtils.h"
+#include "mozilla/MacStringHelpers.h"
+
+@implementation nsTouchBar
+
+static NSTouchBarItemIdentifier CustomButtonIdentifier =
+    @"com.mozilla.firefox.touchbar.button";
+static NSTouchBarItemIdentifier CustomMainButtonIdentifier =
+    @"com.mozilla.firefox.touchbar.mainbutton";
+static NSTouchBarItemIdentifier ScrubberIdentifier =
+    @"com.mozilla.firefox.touchbar.scrubber";
+
+// Non-JS scrubber implemention for the Share Scrubber,
+// since it's defined by an Apple API.
+static NSTouchBarItemIdentifier ShareScrubberIdentifier =
+  [ScrubberIdentifier stringByAppendingPathExtension:@"Share"];
+
+// Used to tie action strings to buttons
+static char identifierAssociationKey;
+
+nsCOMPtr<nsITouchBarHelper> touchBarHelper;
+nsCOMPtr<nsIArray> layoutItems;
+
+#pragma mark - NSTouchBarDelegate
+
+- (instancetype)init
+{
+  if ((self = [super init])) {
+    touchBarHelper = do_GetService(NS_TOUCHBARHELPER_CID);
+    if (!touchBarHelper) {
+      return nil;
+    }
+
+    self.delegate = self;
+    self.mappedLayoutItems = [NSMutableDictionary dictionary];
+
+    nsresult rv = touchBarHelper->GetLayout(getter_AddRefs(layoutItems));
+    if (NS_FAILED(rv) || !layoutItems) {
+      return nil;
+    }
+
+    NSMutableArray<NSTouchBarItemIdentifier>* mutableDefaultItemIdentifiers =
+      [NSMutableArray array];
+    uint32_t itemCount = 0;
+    layoutItems->GetLength(&itemCount);
+    for (uint32_t j = 0; j < itemCount; ++j) {
+      nsCOMPtr<nsITouchBarInput> input = do_QueryElementAt(layoutItems, j);
+      if (!input) {
+        continue;
+      }
+
+      TouchBarInput* convertedInput =
+        [[TouchBarInput alloc] initWithXPCOM:input];
+
+      input = nil;
+
+      NSTouchBarItemIdentifier QueriedItemIdentifier =
+        [nsTouchBar getIdentifierFromInput:convertedInput];
+      [mutableDefaultItemIdentifiers addObject: QueriedItemIdentifier];
+
+      // Add new input to dictionary for lookup of properties in delegate
+      [self.mappedLayoutItems setObject:convertedInput
+                                 forKey:QueriedItemIdentifier];
+    }
+
+    layoutItems = nil;
+
+    self.defaultItemIdentifiers = [mutableDefaultItemIdentifiers copy];
+  }
+
+  return self;
+}
+
+- (NSTouchBarItem*)touchBar:(NSTouchBar*)aTouchBar
+      makeItemForIdentifier:(NSTouchBarItemIdentifier)aIdentifier
+{
+if ([aIdentifier hasPrefix:CustomButtonIdentifier]) {
+    NSButton* button = [NSButton buttonWithTitle:@""
+                                          target:self
+                                          action:@selector(touchBarAction:)];
+    NSCustomTouchBarItem* item = [[NSCustomTouchBarItem alloc]
+                                     initWithIdentifier:aIdentifier];
+    item.view = button;
+
+    return [self updateButton:item forIdentifier:aIdentifier];
+  } else if ([aIdentifier hasPrefix:CustomMainButtonIdentifier]) {
+    NSButton* button = [NSButton buttonWithTitle:@""
+                                          target:self
+                                          action:@selector(touchBarAction:)];
+    NSCustomTouchBarItem* item = [[NSCustomTouchBarItem alloc]
+                                     initWithIdentifier:aIdentifier];
+    item.view = button;
+
+    return [self updateMainButton:item forIdentifier:aIdentifier];
+  } else if ([aIdentifier hasPrefix:ScrubberIdentifier]) {
+    if (![aIdentifier isEqualToString:ShareScrubberIdentifier]) {
+      // We're only supporting the Share scrubber for now.
+      return nil;
+    }
+    return [self makeShareScrubberForIdentifier:aIdentifier];
+  }
+  return nil;
+}
+
+- (void)updateItem:(TouchBarInput*)aInput
+{
+  NSTouchBarItemIdentifier identifier =
+    [nsTouchBar getIdentifierFromInput:aInput];
+  if (!identifier) {
+    return;
+  }
+
+  [self.mappedLayoutItems setObject:aInput forKey:identifier];
+
+  NSTouchBarItem* item = [self itemForIdentifier:identifier];
+  if (!item) {
+    return;
+  }
+  if ([identifier hasPrefix:CustomButtonIdentifier]) {
+    [self updateButton:(NSCustomTouchBarItem*)item
+         forIdentifier:identifier];
+  } else if ([identifier hasPrefix:CustomMainButtonIdentifier]) {
+    [self updateMainButton:(NSCustomTouchBarItem*)item
+             forIdentifier:identifier];
+  }
+}
+
+- (NSTouchBarItem*)updateButton:(NSCustomTouchBarItem*)aButton
+                  forIdentifier:(NSTouchBarItemIdentifier)aIdentifier
+{
+  TouchBarInput* input = self.mappedLayoutItems[aIdentifier];
+  if (!input) {
+    return nil;
+  }
+
+  NSButton* button = (NSButton*)aButton.view;
+  if (!button) {
+    return nil;
+  }
+
+  button.title = input.title;
+  if (input.image) {
+    button.image = input.image;
+    [button setImagePosition:NSImageOnly];
+  }
+
+  // If the button was previously disabled, it might not get updated if it's
+  // lost its `disabled` field somehow. This force-resets it.
+  [button setEnabled: YES];
+  if (input.disabled) {
+    [button setEnabled: !input.disabled];
+  }
+
+  if (input.color) {
+    button.bezelColor = input.color;
+  }
+
+  objc_setAssociatedObject(button,
+    &identifierAssociationKey, aIdentifier, OBJC_ASSOCIATION_RETAIN);
+
+  aButton.customizationLabel = input.title;
+  aButton.view = button;
+  return aButton;
+}
+
+- (NSTouchBarItem*)updateMainButton:(NSCustomTouchBarItem*)aMainButton
+                      forIdentifier:(NSTouchBarItemIdentifier)aIdentifier
+{
+  aMainButton = (NSCustomTouchBarItem*)[self updateButton:aMainButton
+                                            forIdentifier:aIdentifier];
+  NSButton* button = (NSButton*)aMainButton.view;
+  button.imageHugsTitle = YES;
+  [button setImagePosition:NSImageLeft];
+  [button.widthAnchor
+    constraintGreaterThanOrEqualToConstant:252]
+    .active = YES;
+  [button setContentHuggingPriority:1.0
+                      forOrientation:NSLayoutConstraintOrientationHorizontal];
+  return aMainButton;
+}
+
+- (NSTouchBarItem*)makeShareScrubberForIdentifier:
+                        (NSTouchBarItemIdentifier)aIdentifier {
+  TouchBarInput* input = self.mappedLayoutItems[aIdentifier];
+  // System-default share menu
+  NSSharingServicePickerTouchBarItem* servicesItem =
+      [[NSSharingServicePickerTouchBarItem alloc]
+        initWithIdentifier:aIdentifier];
+  servicesItem.buttonImage = input.image;
+  servicesItem.delegate = self;
+  return servicesItem;
+}
+
+- (void)touchBarAction:(id)aSender
+{
+  NSTouchBarItemIdentifier identifier =
+    objc_getAssociatedObject(aSender, &identifierAssociationKey);
+  if (!identifier || [identifier isEqualToString: @""]) {
+    return;
+  }
+
+  TouchBarInput* input = self.mappedLayoutItems[identifier];
+  if (!input) {
+    return;
+  }
+
+  nsCOMPtr<nsITouchBarInputCallback> callback = input.callback;
+  callback->OnCommand();
+}
+
+#pragma mark - TouchBar Utilities
+
++ (NSTouchBarItemIdentifier)getIdentifierFromInput:(TouchBarInput*)aInput
+{
+  NSTouchBarItemIdentifier TypeIdentifier = @"";
+  if ([aInput.type isEqualToString:@"scrubber"]) {
+    TypeIdentifier = ScrubberIdentifier;
+  } else if ([aInput.type isEqualToString:@"mainButton"]) {
+    TypeIdentifier = CustomMainButtonIdentifier;
+  } else {
+    TypeIdentifier = CustomButtonIdentifier;
+  }
+
+  if (!aInput.key) {
+    return TypeIdentifier;
+  }
+
+  // Special case the sharing item.
+  if ([aInput.title isEqualToString:@"Share"]) {
+    return [TypeIdentifier stringByAppendingPathExtension:aInput.title];
+  }
+  return [TypeIdentifier stringByAppendingPathExtension:aInput.key];
+}
+
++ (NSImage*)getTouchBarIconNamed:(NSString*)aImageName
+{
+  nsCOMPtr<nsIFile> resDir;
+  nsAutoCString resPath;
+  NSString* pathToImage;
+
+  nsresult rv = NS_GetSpecialDirectory(NS_GRE_DIR, getter_AddRefs(resDir));
+  resDir->AppendNative(NS_LITERAL_CSTRING("res"));
+  resDir->AppendNative(NS_LITERAL_CSTRING("touchbar"));
+
+  rv = resDir->GetNativePath(resPath);
+  NS_ENSURE_SUCCESS(rv, nil);
+
+  pathToImage = [NSString stringWithUTF8String:(const char*)resPath.get()];
+  pathToImage = [pathToImage stringByAppendingPathComponent:aImageName];
+  NSImage* image = [[NSImage alloc] initWithContentsOfFile:pathToImage];
+  // A nil image will fail gracefully to a labelled button
+
+  return image;
+}
+
+#pragma mark - NSSharingServicePickerTouchBarItemDelegate
+
+- (NSArray*)itemsForSharingServicePickerTouchBarItem:
+                (NSSharingServicePickerTouchBarItem*)aPickerTouchBarItem
+{
+  NSURL* urlToShare = nil;
+  NSString* titleToShare = @"";
+  nsAutoString url;
+  nsAutoString title;
+  if (touchBarHelper) {
+    nsresult rv = touchBarHelper->GetActiveUrl(url);
+    nsresult rv2 = touchBarHelper->GetActiveTitle(title);
+    if (!NS_FAILED(rv)) {
+      urlToShare = [NSURL URLWithString:nsCocoaUtils::ToNSString(url)];
+    }
+    if (!NS_FAILED(rv2)) {
+      titleToShare = nsCocoaUtils::ToNSString(title);
+    }
+  }
+
+  return @[urlToShare, titleToShare];
+}
+
+- (NSArray<NSSharingService*>*)sharingServicePicker:
+                           (NSSharingServicePicker*)aSharingServicePicker
+                            sharingServicesForItems:
+                                          (NSArray*)aItems
+                            proposedSharingServices:
+                       (NSArray<NSSharingService*>*)aProposedServices
+{
+  // redundant services
+  NSArray* excludedServices = @[
+    @"com.apple.share.System.add-to-safari-reading-list",
+    @"com.apple.share.Mail.compose",
+  ];
+
+  NSArray* sharingServices = [aProposedServices
+    filteredArrayUsingPredicate:
+      [NSPredicate predicateWithFormat:@"NOT (name IN %@)", excludedServices]];
+
+  return sharingServices;
+}
+
+@end
+
+@implementation TouchBarInput
+- (id)initWithKey:(NSString*)aKey
+        withTitle:(NSString*)aTitle
+        withImage:(NSString*)aImage
+         withType:(NSString*)aType
+     withCallback:(nsCOMPtr<nsITouchBarInputCallback>)aCallback
+        withColor:(uint32_t)aColor
+     withDisabled:(BOOL)aDisabled
+{
+  if (self = [super init]) {
+    self.key      = aKey;
+    self.title    = aTitle;
+    self.image    = [nsTouchBar getTouchBarIconNamed:aImage];
+    self.type     = aType;
+    self.callback = aCallback;
+    if (aColor) {
+      self.color = [NSColor colorWithDisplayP3Red:((aColor>>16)&0xFF)/255.0
+                                            green:((aColor>>8)&0xFF)/255.0
+                                             blue:((aColor)&0xFF)/255.0
+                                            alpha:1.0];
+    }
+    self.disabled = aDisabled;
+  }
+
+  return self;
+}
+
+- (TouchBarInput*)initWithXPCOM:(nsCOMPtr<nsITouchBarInput>)aInput
+{
+  nsAutoString keyStr;
+  nsresult rv = aInput->GetKey(keyStr);
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  nsAutoString titleStr;
+  rv = aInput->GetTitle(titleStr);
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  nsAutoString imageStr;
+  rv = aInput->GetImage(imageStr);
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  nsAutoString typeStr;
+  rv = aInput->GetType(typeStr);
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  nsCOMPtr<nsITouchBarInputCallback> callback;
+  rv = aInput->GetCallback(getter_AddRefs(callback));
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  uint32_t colorInt;
+  rv = aInput->GetColor(&colorInt);
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  bool disabled = false;
+  rv = aInput->GetDisabled(&disabled);
+  if (NS_FAILED(rv)) {
+    return nil;
+  }
+
+  return [self initWithKey:nsCocoaUtils::ToNSString(keyStr)
+                 withTitle:nsCocoaUtils::ToNSString(titleStr)
+                 withImage:nsCocoaUtils::ToNSString(imageStr)
+                  withType:nsCocoaUtils::ToNSString(typeStr)
+              withCallback:callback
+                 withColor:colorInt
+              withDisabled:(BOOL)disabled];
+}
+@end
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsTouchBarUpdater.h
@@ -0,0 +1,22 @@
+/* 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/. */
+
+#ifndef nsTouchBarUpdater_h_
+#define nsTouchBarUpdater_h_
+
+#include "nsITouchBarUpdater.h"
+
+class nsTouchBarUpdater : public nsITouchBarUpdater
+{
+public:
+  nsTouchBarUpdater() {}
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSITOUCHBARUPDATER
+
+protected:
+  virtual ~nsTouchBarUpdater() {}
+};
+
+#endif // nsTouchBarUpdater_h_
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/widget/cocoa/nsTouchBarUpdater.mm
@@ -0,0 +1,85 @@
+/* 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/. */
+
+#import <Cocoa/Cocoa.h>
+
+#include "nsTouchBarUpdater.h"
+#include "nsITouchBarInput.h"
+#include "nsTouchBar.h"
+
+#include "nsIWebNavigation.h"
+#include "nsIWidget.h"
+#include "nsCocoaFeatures.h"
+#include "nsIDocShellTreeItem.h"
+#include "nsIDocShellTreeOwner.h"
+#include "nsIBaseWindow.h"
+#include "nsINativeAppSupport.h"
+#include "nsCOMPtr.h"
+#include "nsIDocShell.h"
+#include "nsCocoaWindow.h"
+
+#if !defined(MAC_OS_X_VERSION_10_12_2) || \
+    MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_12_2
+@interface BaseWindow(NSTouchBarProvider)
+@property (strong) NSTouchBar* touchBar;
+@end
+#endif
+
+NS_IMPL_ISUPPORTS(nsTouchBarUpdater, nsITouchBarUpdater);
+
+nsresult
+GetBaseWindow(nsIDocShell* aWindow, BaseWindow** aCocoaWindow)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  nsCOMPtr<nsIDocShellTreeOwner> dsto = nullptr;
+  aWindow->GetTreeOwner(getter_AddRefs(dsto));
+  if (!dsto) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsIBaseWindow> baseWindow(do_QueryInterface(dsto));
+  if (!baseWindow) {
+    return NS_ERROR_FAILURE;
+  }
+  nsCOMPtr<nsIWidget> widget = nullptr;
+  baseWindow->GetMainWidget(getter_AddRefs(widget));
+  if (!widget) {
+    return NS_ERROR_FAILURE;
+  }
+  *aCocoaWindow = (BaseWindow*)widget->GetNativeData(NS_NATIVE_WINDOW);
+
+  if (!*aCocoaWindow) {
+    return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
+
+NS_IMETHODIMP
+nsTouchBarUpdater::UpdateTouchBarInput(nsIDocShell* aWindow,
+                                       nsITouchBarInput* aInput)
+{
+  NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
+
+  BaseWindow* cocoaWin;
+  nsresult rv = GetBaseWindow(aWindow, &cocoaWin);
+  if (NS_FAILED(rv) || !cocoaWin) {
+    return NS_ERROR_FAILURE;
+  }
+
+  if (!cocoaWin.touchBar) {
+    return NS_ERROR_FAILURE;
+  }
+
+  TouchBarInput* convertedInput =
+        [[TouchBarInput alloc] initWithXPCOM:aInput];
+
+  [(nsTouchBar*)cocoaWin.touchBar updateItem:convertedInput];
+
+  return NS_OK;
+
+  NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
+}
--- a/widget/cocoa/nsWidgetFactory.mm
+++ b/widget/cocoa/nsWidgetFactory.mm
@@ -101,16 +101,19 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShar
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacWebAppUtils)
 
 #include "nsStandaloneNativeMenu.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsStandaloneNativeMenu)
 
 #include "nsSystemStatusBarCocoa.h"
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSystemStatusBarCocoa)
 
+#include "nsTouchBarUpdater.h"
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsTouchBarUpdater)
+
 #include "GfxInfo.h"
 namespace mozilla {
 namespace widget {
 // This constructor should really be shared with all platforms.
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(GfxInfo, Init)
 } // namespace widget
 } // namespace mozilla
 
@@ -136,16 +139,17 @@ NS_DEFINE_NAMED_CID(NS_PRINTDIALOGSERVIC
 NS_DEFINE_NAMED_CID(NS_IDLE_SERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_SYSTEMALERTSSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_NATIVEMENUSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MACDOCKSUPPORT_CID);
 NS_DEFINE_NAMED_CID(NS_MACSHARINGSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MACWEBAPPUTILS_CID);
 NS_DEFINE_NAMED_CID(NS_STANDALONENATIVEMENU_CID);
 NS_DEFINE_NAMED_CID(NS_MACSYSTEMSTATUSBAR_CID);
+NS_DEFINE_NAMED_CID(NS_TOUCHBARUPDATER_CID);
 NS_DEFINE_NAMED_CID(NS_GFXINFO_CID);
 
 static const mozilla::Module::CIDEntry kWidgetCIDs[] = {
   { &kNS_WINDOW_CID, false, NULL, nsCocoaWindowConstructor },
   { &kNS_POPUP_CID, false, NULL, nsCocoaWindowConstructor },
   { &kNS_CHILD_CID, false, NULL, nsChildViewConstructor },
   { &kNS_FILEPICKER_CID, false, NULL, nsFilePickerConstructor,
     mozilla::Module::MAIN_PROCESS_ONLY },
@@ -173,16 +177,17 @@ static const mozilla::Module::CIDEntry k
   { &kNS_IDLE_SERVICE_CID, false, NULL, nsIdleServiceXConstructor },
   { &kNS_SYSTEMALERTSSERVICE_CID, false, NULL, OSXNotificationCenterConstructor },
   { &kNS_NATIVEMENUSERVICE_CID, false, NULL, nsNativeMenuServiceXConstructor },
   { &kNS_MACDOCKSUPPORT_CID, false, NULL, nsMacDockSupportConstructor },
   { &kNS_MACSHARINGSERVICE_CID, false, NULL, nsMacSharingServiceConstructor },
   { &kNS_MACWEBAPPUTILS_CID, false, NULL, nsMacWebAppUtilsConstructor },
   { &kNS_STANDALONENATIVEMENU_CID, false, NULL, nsStandaloneNativeMenuConstructor },
   { &kNS_MACSYSTEMSTATUSBAR_CID, false, NULL, nsSystemStatusBarCocoaConstructor },
+  { &kNS_TOUCHBARUPDATER_CID, false, NULL, nsTouchBarUpdaterConstructor },
   { &kNS_GFXINFO_CID, false, NULL, mozilla::widget::GfxInfoConstructor },
   { NULL }
 };
 
 static const mozilla::Module::ContractIDEntry kWidgetContracts[] = {
   { "@mozilla.org/widgets/window/mac;1", &kNS_WINDOW_CID },
   { "@mozilla.org/widgets/popup/mac;1", &kNS_POPUP_CID },
   { "@mozilla.org/widgets/childwindow/mac;1", &kNS_CHILD_CID },
@@ -212,16 +217,17 @@ static const mozilla::Module::ContractID
   { "@mozilla.org/widget/idleservice;1", &kNS_IDLE_SERVICE_CID },
   { "@mozilla.org/system-alerts-service;1", &kNS_SYSTEMALERTSSERVICE_CID },
   { "@mozilla.org/widget/nativemenuservice;1", &kNS_NATIVEMENUSERVICE_CID },
   { "@mozilla.org/widget/macdocksupport;1", &kNS_MACDOCKSUPPORT_CID },
   { "@mozilla.org/widget/macsharingservice;1", &kNS_MACSHARINGSERVICE_CID },
   { "@mozilla.org/widget/mac-web-app-utils;1", &kNS_MACWEBAPPUTILS_CID },
   { "@mozilla.org/widget/standalonenativemenu;1", &kNS_STANDALONENATIVEMENU_CID },
   { "@mozilla.org/widget/macsystemstatusbar;1", &kNS_MACSYSTEMSTATUSBAR_CID },
+  { "@mozilla.org/widget/touchbarupdater;1", &kNS_TOUCHBARUPDATER_CID },
   { "@mozilla.org/gfx/info;1", &kNS_GFXINFO_CID },
   { NULL }
 };
 
 static void
 nsWidgetCocoaModuleDtor()
 {
   // Shutdown all XP level widget classes.
new file mode 100755
index 0000000000000000000000000000000000000000..16f70bc6ca0f865214f3baa8ef82e0f805bcbd67
GIT binary patch
literal 5738
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
Iq#Edd082icy#N3J
new file mode 100755
index 0000000000000000000000000000000000000000..ba0197323ae68f33d52a21a751f9478b50f41fbe
GIT binary patch
literal 5894
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
JR7Ysg{SV6Q^M(Kb
new file mode 100755
index 0000000000000000000000000000000000000000..1eace36cc3d0524330e57419736ecf7f4bbbadd0
GIT binary patch
literal 5981
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
new file mode 100755
index 0000000000000000000000000000000000000000..e59d485062c780085410e46c07fb46d828c82e84
GIT binary patch
literal 5768
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
new file mode 100755
index 0000000000000000000000000000000000000000..c0509e4f04399d2e04a1547246c53b98e27b9a7a
GIT binary patch
literal 5819
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
new file mode 100755
index 0000000000000000000000000000000000000000..d7aac17d464b61c6765dcca51b9a41e9adee794b
GIT binary patch
literal 5777
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
new file mode 100755
index 0000000000000000000000000000000000000000..8eb0188885ea03367ca231cbb4d16a266261d97f
GIT binary patch
literal 5668
zc$}qJcU)7;wx$XML{tO?ge`~AO9BZYD!oZFbm@>l=nxGZM2hqxT?7TBC?Zl6lp2Z@
zK}tlrND~k#f)we<Lk@bqm-F8J<0bpIGy9u0Yu0?TGFkb+nhHunP+>6;xN&NEYA$!>
z;k(9W5Db6-IE+2$@?}6o9qVl4Y74;kA#FfJ$<EOgi{JlrM7v@Yu$DM0EFdKXa&g6D
z(M}*wQVmTgeFMNS<P~fl`x?w;Ra9v+OP-~AK2?8aFZ9C&nWh=K2gHqm=N8Ig)a>_9
zO}JSI4m8=`h1hVpG(IckbZdZU*t5r(gz<=}#PmMvwJCo4y_maMD6cOEL<FxU#;RwX
zPD@nVED8WAnSHnME?y4wkj$@+r;Eng>e~^Fx~(Qp%@$*MeKlO$1=7nWq94NfYhoro
z;fKfyIRvG5Eal#Uu+CP8;qJG7t`dH@TBtbe7bN-z0lHq-v4Dss+UDSn$2z+LVt<pN
zjdj7f;VrQ)fcW2lJkHs5zuyIb9X#(7bLda}4}Y3?oTU!d6)@g!DkuS_fQSJKV~@3T
z1%CD_IY9x$;pjgcAdc>c#Q(k{hcW;1E286uaXmnkaCoP`?>{X-P(VaZ4(ACNLxKG_
zV*fJzb5+Q{XHdrD+^!!4r?c-Fk9Kys{*wkvul)t<08q$JE0Bl^;EH$KpF$0=MmxG-
z55xbR7y`P~y1cp&T?p)23*||fMDoY7j0}M)u?8V><#*-M15Yxrr21=WJ(ZKttdk+C
zU(k^qtr!Rss5twqNi$QzP_~~UD5_nC`iZE<1qPD(HfFk``zUe9k%ZVU1o?l`E{}7>
z;dQQ~EwKlSlXnpXpwOe#Lq(5r4?WC)tNW=SBKva#ocGxWL=>>@c9vLeWx4<UO$pXB
z4rA3j`y&C_3aaYt{?IFwBTsPUt5SP)X82KQs&PW81IvrSUMAU+gaoVhd9F_N_q4wJ
zfuADtYgA;b2}0C?@4f5$sJ6B9H1$2^IC-T?J!N@U70Z?`C0KDA+TX_#Z?5c)ZsMjh
z&SeF>lp_>wpUDC@h`Y2tS^n5%`L^!j=FA0_94!{XC;F1{9i69c$q5wh)*4I4q9E6J
z791C^;VM`K@oM1ZVX7Ma(jM^GX@!6i`{B~?V<Gh@j<PwjNVX6SF6y1Ex+(FH=n&?i
z4Y+awvFRa_Rxm$F?xZKB=gsG#BI{%B^qO_3c-D_Sx{9lu4t=Vro#*9!Dncuiy%6O&
z2+fj}p#Zm*r=91U-RNG{Y6~_}rc;<{(S{?(l>Lj~FN4*oMhl0!*uGgR{78$Qy-DGT
zxc=0N{Q*@7N3Ee<PUS|LPSQ@vSXsbcvq3xC%)F^i!C7yWOZB6L-%7vW!men;E~V|;
z&iEU)(MaNBRTbG$Br)W*W(DV&kafAMDZLL)SGU-F)dh1eGww_!gF;`_W!Kf>CHYpv
zz`Mp}C24F1E$_rQg)z@1${u)+hX&89N>Q@kNO8Wu*=hF5<URf4OIs*@Yt?U<#g~-}
z?Ywx}jSi)&J$DQOS_4zAkTuu<ZP8v`sDS&WV*(7hEJ7H))`uF}yviyOpNx1;-#ulQ
zb9=lP4`K5#?FcF%X7PJQr{3v!o$8kOHO;g@4qJT8)T5NYNsdE{Je_})Y9L}xC-dwA
z%h=n!iQKfd=sOuKtZ4Kr=DqC!!6D+~K{~#9zBSmTx=$8115*7SOg@!o!f!eQszb!K
zu$J?~WcIaTEKd9uyOa?uhJ~Rug@Q5S&6nHGtx#$ZmYYW<3Ga(bX8F0dE_zRzNuJnY
zDrYxns$?Iy?#mmHLB_gatc<HRvQH;;V{d4)TrKU(9r9)})uTw7?d$}*%F1_C=Y9@1
z<4C^hxA~CSDJjk8$LzaD-C#?v9!o{$jr<hja~H)Ho{w`h_=Q|+SPYh?+Y=@T`SSaM
z(~_l<g%dbUV}(`C)kal0)XdAbsybqQ*0@BOUBJss-Mt0HW&QUIko>r0j=K}f^qX2<
zeR_P$VVA+VlcvRv9>k9OxJPC9)hXUAw{4ecgHMKCCMXH=(cOC_9gzbF@|6~Y?1^u7
zS)-T{x{EYUiwXUCVZj58YPggIJLrn(XuSf2Ju3Fp$MX+pu2P<$`RIH1c9q5b`qVES
z$5+PrxA>>Tr7zU*Fy{B7QjIDw0zR+Dd6KB5d`(nXXD7?G-?=qG4I^5GoW;Fv#5a2A
z%>PxH;!+b@<8<wE=dBRiJ#)`>-^CkmSQG@9x>_dK5g{H^<cp`$eB_+&b-a>Z-mLlS
zg{sfG#ClC8?})i{nGs@%oz*kacBMmqE@R!epyR}t-|a7fKR6y{+|)aI=pCFy2Mq`U
z`5S~Bg8PS^ioCoW+68L`9Gqj?fa!0efB2P$!vEjrTH0L?U7bOuP$B_Acz22u0I#xm
z(*W-;T{%Oc6|Um1Nfr{s?XEzn#CVcV-%7WRR5_H>QjwANb|9voW|={=xn4^_acVfq
zfo8D)zA}=!`^Io|aJsC2&}PxMzmi0ACy?T`s{yG$EYpB-VXoff)akayb+WSzr1S=)
zb>r676v`V4WIa0s$&{2QSDH)K7KHt+s)ht>HMw2-_Wa^F5%OHeNI;6c;+Jo6Gf$Bv
z>XbB{6WybDyPCu&8Uht%%B0D9#yQbg<hYjmS)i)*UNZM&CW~R`xoTK?RF&pPDtJ6Q
ziXzkG9(c?q`z95ZpsSKfGPTaz-M#TZodm*|V%|Q@o#_}Zs>pb5A$*yPggUViS&gTU
z+(g=@lXyP1nT((aSHV0!*?-S&>Pw6D)>4ViCI%{y*q|{U=BZ9xEv35yVfHV=-Blz7
z8#<-f#(gbd`})<e@3ZY@?cgZ;EuCG-7VmAnCGL4*x@=Us;i%*MGZ6w4$r_i@{qrR?
zNqQuuPRC@X#-E`U0g`1(lG2d}E9@bTX7P=m=y+%&=jR<=NHZLS1->A*GXimMYeSIh
zDQyee`j;LvO9%X=az+fRIQ2O9v6@1AI~{#8(Q0>{VQ-=iY1h%(Aow7oj(I8gi=Nh(
zM4F&*+p6Hp0S2+cR-hoi-f_RP;yhI6ZlyUe+PayO_y!|2%T=gaaFQhQf01)JOM8>~
z&KWa6K`k}awgquTE-|9sKc=@hXiXxV$JJ#ybw01r#aQ9NS%T-XM}r*e$xg*mxjqEJ
z0)!!Cf)>Zw{Kc-5j{qb={#O{t?~)5&A+wXAcp)n_KmwA54v@Ovw!co&6X5-h;%cDy
z^<yR!*XoX6r={~(mH~y-t3gOd0_>;*zcHN2l6@M>lyf3Qu8)D$h}uhDR#SqJyh%Ph
zmLXnd^Bwn-v;4Q8X3A?yuKwl9Qb}!kd+Q<9I{<cUm((}t<UO)(^zi|bSN?;=m)NM4
zU$>1Zc%FGc#auTuu3F9{MPK%sd7SkdiD0n#>jY|<7HaY?B?D^KB?Y-y11{2&7aZa^
zbI9@(Q)B6KSSzBh#NC)AKNgyazIT?X`P@XPVbnNAAKiyhh4kLDyr-|u{8`+ZK`dZ1
z@DZl>`C|i~XVUI8;wSG%3pMIn#8?;?CqE}2K+j)dqkmI(?i1VfTjgg>M4jP<6lEv+
zqpJMp8jg>1FL_q;k1#F<o~U>EhPip62IR-)$37av(Ok<DOJhXg5P0IkU4YAxOP7I#
zdYXDS=;UjdR=^XKD`yCUSEC7r@A;hp*=iLw?yCumDj{6V+FX1or2)Ds_ME2NlH7y~
z39T2cl<{W`Wz0~8Tp55l_(Z(4W+E>)BTAJ`QEu=mQnf<HOU6t7k@oQ?&OHWC?^UK5
zp$H1Ts=gx131Z1B$rG&w3HfmjNps0QU{qp%vPZJHa0ZY01wYjvk9W$+wCZK*bpo=B
z^)r>mOJ7R{t0<;sC1JuashDug?N9I~EpT;wKz!LLRG!RC@q6&23oLTokG$TOmui$=
z{DA!cIj@Y!+3rr5X<Fs@LRh82g0aR^yi;sbEK?<KwU51qSZs)CpL-OQ5LFcwvjY2E
zL7X5Ci5J<K?N#$7ZSp(w-%R36vQ8pRig~K8hwEkRO?&F}6x9Q<=e9@N587|{3g<@?
zbBP}5#58l*-sDc`Y;k3{clnn6_l8-?*#wqUmKv6GEP5=-ux9wVROi&z)Tz{I*qc&Y
zBife~MpH)9FU=rHDGTko*5HyzWM)C(*Ic14shr__$pXtKB?dOxS4%oio5l+pBV@}=
z%5*&BP--FuBIZR}i<wed83h?RwaT@|esAmE0Us<PW$)KN$&ARXMW>^)$1VSQ8kgV2
zpKX+VsaeAE)s2WHsR?85;_x(;c$Mf@4V{6W5nYQ)Vkwc%;j=9_EFWI=Cad_Pq2V*7
zzK6($%Plvvz3y)c&`L%cM5ZwfGnos171R-$6XY=DGo&<dDxEFfYWUEY>R@W=`zFMG
z!m_0E@$l!D1$jcF?zLZiFQu9m4>MI=ts<_`uW@d3Z$qghLp?(Y^y>qz?z~k&zP%^s
zzKoZ5E=5gH@%ZpO?^ekjO*8D|>pb3>O-sl8jk!nYEWYc;csUzBPS{E~%G~pMW{=)b
z(uC36R=Y-j^t5}UQ{(V}<lt`kw!jIs6LHFsZxVA8rdf!zW?{)i*W#`fmBp`P7VQ^v
zr7lW^OGQhau5qu)_Z8Vd?~?7hZw;^Xf1BRw-$qeLP&}jg0?MIKqR^+3q7|h%Md?P-
zP)}N4704m--ki&%hlxyXN8Ua7G7X&0^vssaSz$rgGwyk>ay`#mo*ooJ7)1s7#;PkZ
zE$>^DBcqwrm^_qPm75fMl{FN76q6Ozk_`k6OD2_~jG}<Yl1v<|XMDKa@p<d-ht)zS
z=0AZZ7KFu2?v~7dz`vZzYa<rMn%5iN;Ady$I6um;7k>J6-jsUbs(FRS6h(hRRp@s7
zbhE&8^pfcYb|;P^Ip{@DmqK!*X}G0Ip~@MR2{M%I%Q3eX=F0(-d5N)!*?eMoU3ndL
zL8Tj|-Ev@bM6rOWm?RHDqyd%<k*|Df*Sny1I!mT2PMz1q(7Nj0ogeDouS9X(2j4cN
zEwO(wVxx@Bc&pWZ^7HCs>ZEhq`PP-z?OSkbxQClfjr)&~oqG6!1AReoU!loR#Z?c}
z`pWU|HFGgefYX)1Z*59#(OA||=ZKLWt%q90H5Rrdi=Uh2D&(}r2|}I5^o~uAXB@u{
zTbC5r4<&P&b$!RQeTw*m0)LF38#VO3wmICs7W9?yXzkIq$Cx{{$H(EB$`ykYjG@`!
zyTUQkf~of9tmU$*Yx6bwXyY3eC+uRZVoF7yydbC+*(>+v&gRSpu*9T(Cd~SjeNFrD
zW~je*)XA@#G@87LN{XG4t=g|;UDKgJ)~N~oar{{WaV~4Nvew4W+)v@_m8CeMa<KBF
zH?L#ddN1|#Bc31<#a~CqH$R`a@dmd$_FdlRbpDK{Sa!t*g~SEq(x*2Y9E<66mj}Hf
ze4ozn>}IUJdS?`2l-c*OFZ@-GxSfx>&*+SQciQ>R^Fq@1_inC6t)--vytPpy#&w=~
za37iBacfzwId~~DoH_L3HCL(1(#iK}g~f#<Z2`$eW=j?LydlE&j$U%UO(D|sl5d(X
z;cLilbRT<F`d#z+TXr)q7o7+**GqQqP88g!q4b^JGTjy#S*!G&y0e$YN*;M^YeBfi
zXV2`T<c#mgZWmSF2{Y+-Z;4&oUCa52EFKVwKmDn6!EWzHzjYpAb^c+$1+gT|CMKj@
zUSuz6vk28dNz5Y(D3vPBDi<gdqc)?4y`Qf(eQS$K?w$y)<@@n!J*g`{<Ce!Z!3NXX
z_|2hfE=5{(<Vg*3t8dL|+Um<>w};*0<J^dm{2J-CfZfb(%hfk=GxMkoR8mH?w8u@F
zon=pMC+p9n>p?5q|4`Kal4L~1p`yP*=sy*;uzxRV#r{#aaREd$uvT{H1Fhp{Z48yz
zzYZh-H)mG>3W%uLS-Aklz+s8}=f8jPBOc|^u4qS`%`ex7Qh+`d?_!5@21KC3us_HD
zQf_!P(3Sv72QUDj5Mij8FdWcwL*re&0Zj#^1Kr5emGAeUUs49I!bMRCR04v4ib7#9
z2?)dp0^!-e{$=^^3Wt@O<$i4rMI6de`<%M&$E5JHhKC;NMH)D(KcD{<sV5$54cey$
z34;870pf7D7#y$$4ly_czR$-&kMl1KB8ou%CkB&%9<_sriXI&+4mpB}!H@WZz(iq3
zFvLI1fe<@lCklZav4bIw#te~wi2Wx9MM}Vr`hy*@gCXD&M>#+uj$lY}=zn5x2=tGb
zUGZo;M=bteLv`%D_xA}2h-l+*`&oJ@GO9RR;{fPkTVX$GFN=#}MI|suh&VzNVl57p
sKtiBs7z`_cuoQ*DF&Kyx=)ar%o%AlQ`zd*l2ymzv6a)q<qLe`Y10Z{XssI20
new file mode 100644
index 0000000000000000000000000000000000000000..62f9dbf0e2fd236dd746913a0bbbbd022bc96657
GIT binary patch
literal 5797
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
S!$c4j7K4Hz5Ji*{_<sP=G`}_g
new file mode 100755
index 0000000000000000000000000000000000000000..ea6f6993f4ed7e298e9605aabe8c9dd674ffc397
GIT binary patch
literal 5892
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
HP^9=D4PN!_
new file mode 100755
index 0000000000000000000000000000000000000000..5e3d91477e2cf65a9b2fdd39667852dc194e0bca
GIT binary patch
literal 5934
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
new file mode 100755
index 0000000000000000000000000000000000000000..0547d4b480008422f1c784c14b970379d843a376
GIT binary patch
literal 5878
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
new file mode 100755
index 0000000000000000000000000000000000000000..d4d3faf7ec16820f7f5d49164b68b1eada2182a7
GIT binary patch
literal 5979
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
new file mode 100755
index 0000000000000000000000000000000000000000..c231c9427cc3bf041e02c5abef715607c4dc6604
GIT binary patch
literal 5898
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
MCI<o)VM^rx1I%soo&W#<
new file mode 100755
index 0000000000000000000000000000000000000000..cfbed6f9695817901452c2863d1f7409d3a8b07a
GIT binary patch
literal 5902
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
LB?zR9P@()UVPy6#
--- a/widget/moz.build
+++ b/widget/moz.build
@@ -59,16 +59,19 @@ if toolkit == 'windows':
 elif toolkit == 'cocoa':
     XPIDL_SOURCES += [
         'nsIMacDockSupport.idl',
         'nsIMacSharingService.idl',
         'nsIMacWebAppUtils.idl',
         'nsIStandaloneNativeMenu.idl',
         'nsISystemStatusBar.idl',
         'nsITaskbarProgress.idl',
+        'nsITouchBarHelper.idl',
+        'nsITouchBarInput.idl',
+        'nsITouchBarUpdater.idl',
     ]
     EXPORTS += [
         'nsINativeMenuService.h',
     ]
 
 TEST_DIRS += ['tests']
 
 DIRS += ['headless']
new file mode 100644
--- /dev/null
+++ b/widget/nsITouchBarHelper.idl
@@ -0,0 +1,38 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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/. */
+
+#include "nsISupports.idl"
+#include "nsIArray.idl"
+#include "nsITouchBarInput.idl"
+
+/**
+ * Back-to-frontend communication for the Touch Bar
+ */
+[scriptable, uuid(ea109912-3acc-48de-b679-c23b6a122da5)]
+interface nsITouchBarHelper : nsISupports
+{
+  /**
+   * Returns the active browser's URL.
+   */
+  readonly attribute AString activeUrl;
+
+  /**
+   * Return the active browser's page title.
+   */
+  readonly attribute AString activeTitle;
+
+  /**
+   * Returns the layout for the Touch Bar in an nsIArray
+   * of nsITouchBarInput objects.
+   */
+  attribute nsIArray layout;
+
+  /**
+   * Returns the requested TouchBarInput.
+   * Exposed for testing.
+   */
+  nsITouchBarInput getTouchBarInput(in string aInputName);
+};
new file mode 100644
--- /dev/null
+++ b/widget/nsITouchBarInput.idl
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#include "nsISupports.idl"
+#include "nsIArray.idl"
+
+[scriptable, function, uuid(001ab07c-1b3a-4dbf-a657-fada0065ff55)]
+interface nsITouchBarInputCallback : nsISupports
+{
+  void onCommand();
+};
+
+/**
+ * Implements an input to be registered on the Mac Touch Bar.
+ */
+
+[scriptable, uuid(77441d17-f29c-49d7-982f-f20a5ab5a900)]
+interface nsITouchBarInput : nsISupports
+{
+    readonly attribute AString key;
+
+    /**
+     * The lookup key for the button's localized text title.
+     *  Localizations are found in
+     *  /toolkit/locales/LOCALE/chrome/global/touchbar.properties.
+     */
+    attribute AString title;
+
+    /**
+     * The name of a icon file added to
+     * /widget/cocoa/touchbar.
+     */
+    attribute AString image;
+
+    /**
+     * The type of the input.
+     * Takes one of:
+     *   `button`: A standard button.
+     *             If an image is available, only the image is displayed.
+     *   `mainButton`: An extra-wide button. Displays both the image and title.
+     *   `scrubber`: A Scrubber element. Not yet implemented, except in the
+     *               exeception case of Apple's pre-built Share scrubber.
+     */
+    attribute AString type;
+
+    /**
+     * A callback function to be invoked when an element is touched.
+     */
+    attribute nsITouchBarInputCallback callback;
+
+    /**
+     * A hexadecimal uint32_t specifying the input's
+     * background color. If omitted, the default background color is used.
+     */
+    attribute uint32_t color;
+
+    /**
+     * If `true`, the Touch Bar input is greyed out and inoperable.
+     */
+    attribute boolean disabled;
+};
new file mode 100644
--- /dev/null
+++ b/widget/nsITouchBarUpdater.idl
@@ -0,0 +1,22 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ *
+ * 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/. */
+
+#include "nsISupports.idl"
+#include "nsITouchBarInput.idl"
+interface nsIDocShell;
+
+/**
+ * Front-to-backend communication to keep Touch Bar updated
+ */
+[scriptable, uuid(38f396e2-93c9-4a77-aaf7-2d50b9962186)]
+interface nsITouchBarUpdater : nsISupports
+{
+  /**
+   * Updates a Touch Bar input in the specified window with the properties in
+   * aInput.
+   */
+  void updateTouchBarInput(in nsIDocShell aWindow, in nsITouchBarInput aInput);
+};
--- a/widget/nsWidgetsCID.h
+++ b/widget/nsWidgetsCID.h
@@ -80,16 +80,31 @@
 { 0xde59fe1a, 0x46c8, 0x490f, \
   { 0xb0, 0x4d, 0x34, 0x54, 0x5a, 0xcb, 0x06, 0xc9 } }
 
 // {b6e1a890-b2b8-4883-a65f-9476f6185313}
 #define NS_MACSYSTEMSTATUSBAR_CID \
 { 0xb6e1a890, 0xb2b8, 0x4883, \
   { 0xa6, 0x5f, 0x94, 0x76, 0xf6, 0x18, 0x53, 0x13 } }
 
+// {ea109912-3acc-48de-b679-c23b6a122da5}
+#define NS_TOUCHBARHELPER_CID \
+{0xea109912, 0x3acc, 0x48de, \
+  {0xb6, 0x79, 0xc2, 0x3b, 0x6a, 0x12, 0x2d, 0xa5} }
+
+// {38f396e2-93c9-4a77-aaf7-2d50b9962186}
+#define NS_TOUCHBARUPDATER_CID \
+{0x38f396e2, 0x93c9, 0x4a77, \
+  {0xaa, 0xf7, 0x2d, 0x50, 0xb9, 0x96, 0x21, 0x86} }
+
+// {77441d17-f29c-49d7-982f-f20a5ab5a900}
+#define NS_TOUCHBARINPUT_CID \
+{0x77441d17, 0xf29c, 0x49d7, \
+  {0x98, 0x2f, 0xf2, 0x0a, 0x5a, 0xb5, 0xa9, 0x00} }
+
 //-----------------------------------------------------------
 //Drag & Drop & Clipboard
 //-----------------------------------------------------------
 // {8B5314BB-DB01-11d2-96CE-0060B0FB9956}
 #define NS_DRAGSERVICE_CID      \
 { 0x8b5314bb, 0xdb01, 0x11d2, { 0x96, 0xce, 0x0, 0x60, 0xb0, 0xfb, 0x99, 0x56 } }
 
 // {8B5314BC-DB01-11d2-96CE-0060B0FB9956}