Commit 84419a8c authored by shindli's avatar shindli
Browse files

Merge mozilla-central to autoland. a=merge CLOSED TREE

parents 0eb439e9 083cbd8b
Loading
Loading
Loading
Loading
+47 −231
Original line number Diff line number Diff line
@@ -7,29 +7,13 @@ const { XPCOMUtils } = ChromeUtils.import(
);

XPCOMUtils.defineLazyModuleGetters(this, {
  AppConstants: "resource://gre/modules/AppConstants.jsm",
  BrowserWindowTracker: "resource:///modules/BrowserWindowTracker.jsm",
  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
  PrivateBrowsingUtils: "resource://gre/modules/PrivateBrowsingUtils.jsm",
  Services: "resource://gre/modules/Services.jsm",
  UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.jsm",
  AppConstants: "resource://gre/modules/AppConstants.jsm",
  PlacesUtils: "resource://gre/modules/PlacesUtils.jsm",
});

XPCOMUtils.defineLazyServiceGetter(
  this,
  "gTouchBarUpdater",
  "@mozilla.org/widget/touchbarupdater;1",
  "nsITouchBarUpdater"
);

// For accessing TouchBarHelper methods from static contexts in this file.
XPCOMUtils.defineLazyServiceGetter(
  this,
  "gTouchBarHelper",
  "@mozilla.org/widget/touchbarhelper;1",
  "nsITouchBarHelper"
);

/**
 * Executes a XUL command on the top window. Called by the callbacks in each
 * TouchBarInput.
@@ -40,7 +24,8 @@ XPCOMUtils.defineLazyServiceGetter(
 *        Intended to be shorter and more readable than the XUL command.
 */
function execCommand(commandName, telemetryKey) {
  let command = TouchBarHelper.window.document.getElementById(commandName);
  let win = BrowserWindowTracker.getTopWindow();
  let command = win.document.getElementById(commandName);
  if (command) {
    command.doCommand();
  }
@@ -67,15 +52,6 @@ function hexToInt(hexString) {
  return isNaN(val) ? null : val;
}

const kInputTypes = {
  BUTTON: "button",
  LABEL: "label",
  MAIN_BUTTON: "mainButton",
  POPOVER: "popover",
  SCROLLVIEW: "scrollView",
  SCRUBBER: "scrubber",
};

/**
 * An object containing all implemented TouchBarInput objects.
 */
@@ -83,25 +59,25 @@ const kBuiltInInputs = {
  Back: {
    title: "back",
    image: "chrome://browser/skin/back.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("Browser:Back", "Back"),
  },
  Forward: {
    title: "forward",
    image: "chrome://browser/skin/forward.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("Browser:Forward", "Forward"),
  },
  Reload: {
    title: "reload",
    image: "chrome://browser/skin/reload.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("Browser:Reload", "Reload"),
  },
  Home: {
    title: "home",
    image: "chrome://browser/skin/home.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => {
      let win = BrowserWindowTracker.getTopWindow();
      win.BrowserHome();
@@ -114,25 +90,25 @@ const kBuiltInInputs = {
  Fullscreen: {
    title: "fullscreen",
    image: "chrome://browser/skin/fullscreen.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("View:FullScreen", "Fullscreen"),
  },
  Find: {
    title: "find",
    image: "chrome://browser/skin/search-glass.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("cmd_find", "Find"),
  },
  NewTab: {
    title: "new-tab",
    image: "chrome://browser/skin/add.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("cmd_newNavigatorTabNoEvent", "NewTab"),
  },
  Sidebar: {
    title: "open-sidebar",
    image: "chrome://browser/skin/sidebars.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => {
      let win = BrowserWindowTracker.getTopWindow();
      win.SidebarUI.toggle();
@@ -145,88 +121,31 @@ const kBuiltInInputs = {
  AddBookmark: {
    title: "add-bookmark",
    image: "chrome://browser/skin/bookmark-hollow.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("Browser:AddBookmarkAs", "AddBookmark"),
  },
  ReaderView: {
    title: "reader-view",
    image: "chrome://browser/skin/readerMode.svg",
    type: kInputTypes.BUTTON,
    type: "button",
    callback: () => execCommand("View:ReaderView", "ReaderView"),
    disabled: true, // Updated when the page is found to be Reader View-able.
  },
  OpenLocation: {
    title: "open-location",
    image: "chrome://browser/skin/search-glass.svg",
    type: kInputTypes.MAIN_BUTTON,
    type: "mainButton",
    callback: () => execCommand("Browser:OpenLocation", "OpenLocation"),
  },
  // This is a special-case `type: kInputTypes.SCRUBBER` element.
  // This is a special-case `type: "scrubber"` element.
  // Scrubbers are not yet generally implemented.
  // See follow-up bug 1502539.
  Share: {
    title: "share",
    type: "scrubber",
    image: "chrome://browser/skin/share.svg",
    type: kInputTypes.SCRUBBER,
    callback: () => execCommand("cmd_share", "Share"),
  },
  SearchPopover: {
    title: "search-popover",
    image: "chrome://browser/skin/search-glass.svg",
    type: kInputTypes.POPOVER,
    children: {
      SearchScrollViewLabel: {
        title: "search-search-in",
        type: kInputTypes.LABEL,
      },
      SearchScrollView: {
        key: "search-scrollview",
        type: kInputTypes.SCROLLVIEW,
        children: {
          Bookmarks: {
            title: "search-bookmarks",
            type: kInputTypes.BUTTON,
            callback: () =>
              gTouchBarHelper.insertRestrictionInUrlbar(
                UrlbarTokenizer.RESTRICT.BOOKMARK
              ),
          },
          History: {
            title: "search-history",
            type: kInputTypes.BUTTON,
            callback: () =>
              gTouchBarHelper.insertRestrictionInUrlbar(
                UrlbarTokenizer.RESTRICT.HISTORY
              ),
          },
          OpenTabs: {
            title: "search-opentabs",
            type: kInputTypes.BUTTON,
            callback: () =>
              gTouchBarHelper.insertRestrictionInUrlbar(
                UrlbarTokenizer.RESTRICT.OPENPAGE
              ),
          },
          Tags: {
            title: "search-tags",
            type: kInputTypes.BUTTON,
            callback: () =>
              gTouchBarHelper.insertRestrictionInUrlbar(
                UrlbarTokenizer.RESTRICT.TAG
              ),
          },
          Titles: {
            title: "search-titles",
            type: kInputTypes.BUTTON,
            callback: () =>
              gTouchBarHelper.insertRestrictionInUrlbar(
                UrlbarTokenizer.RESTRICT.TITLE
              ),
          },
        },
      },
    },
  },
};

const kHelperObservers = new Set([
@@ -235,8 +154,6 @@ const kHelperObservers = new Set([
  "touchbar-location-change",
  "quit-application",
  "intl:app-locales-changed",
  "urlbar-focus",
  "urlbar-blur",
]);

/**
@@ -248,20 +165,16 @@ class TouchBarHelper {
    for (let topic of kHelperObservers) {
      Services.obs.addObserver(this, topic);
    }
    // We cache our search popover since otherwise it is frequently
    // created/destroyed for the urlbar-focus/blur events.
    this._searchPopover = this.getTouchBarInput("SearchPopover");
  }

  destructor() {
    this._searchPopover = null;
    for (let topic of kHelperObservers) {
      Services.obs.removeObserver(this, topic);
    }
  }

  get activeTitle() {
    let tabbrowser = TouchBarHelper.window.ownerGlobal.gBrowser;
    let tabbrowser = this.window.ownerGlobal.gBrowser;
    let activeTitle;
    if (tabbrowser) {
      activeTitle = tabbrowser.selectedBrowser.contentTitle;
@@ -288,25 +201,15 @@ class TouchBarHelper {
    return layoutItems;
  }

  static get window() {
  get window() {
    return BrowserWindowTracker.getTopWindow();
  }

  get isUrlbarFocused() {
    return TouchBarHelper.window.gURLBar.focused;
  }

  static get baseWindow() {
    return TouchBarHelper.window.docShell.treeOwner.QueryInterface(
      Ci.nsIBaseWindow
    );
  get bookmarkingUI() {
    return this.window.BookmarkingUI;
  }

  getTouchBarInput(inputName) {
    if (inputName == "SearchPopover" && this._searchPopover) {
      return this._searchPopover;
    }

    // inputName might be undefined if an input's context() returns undefined.
    if (!inputName || !kBuiltInInputs.hasOwnProperty(inputName)) {
      return null;
@@ -324,13 +227,8 @@ class TouchBarHelper {
    let inputData = kBuiltInInputs[inputName];

    let item = new TouchBarInput(inputData);

    // Skip localization if there is already a cached localized title or if
    // no title is needed.
    if (
      kBuiltInInputs[inputName].hasOwnProperty("localTitle") ||
      !kBuiltInInputs[inputName].hasOwnProperty("title")
    ) {
    // Skip localization if there is already a cached localized title.
    if (kBuiltInInputs[inputName].hasOwnProperty("localTitle")) {
      return item;
    }

@@ -338,11 +236,15 @@ class TouchBarHelper {
    this._l10n.formatValue(item.key).then(result => {
      item.title = result;
      kBuiltInInputs[inputName].localTitle = result; // Cache result.
      // Checking TouchBarHelper.window since this callback can fire after all windows are closed.
      if (TouchBarHelper.window) {
        gTouchBarUpdater.updateTouchBarInputs(TouchBarHelper.baseWindow, [
          item,
        ]);
      // Checking this.window since this callback can fire after all windows are closed.
      if (this.window) {
        let baseWindow = this.window.docShell.treeOwner.QueryInterface(
          Ci.nsIBaseWindow
        );
        let updater = Cc["@mozilla.org/widget/touchbarupdater;1"].getService(
          Ci.nsITouchBarUpdater
        );
        updater.updateTouchBarInputs(baseWindow, [item]);
      }
    });

@@ -357,7 +259,7 @@ class TouchBarHelper {
   *        Additional keys to values in the kBuiltInInputs object in this file.
   */
  _updateTouchBarInputs(...inputNames) {
    if (!TouchBarHelper.window) {
    if (!this.window) {
      return;
    }

@@ -370,23 +272,13 @@ class TouchBarHelper {
      inputs.push(input);
    }

    gTouchBarUpdater.updateTouchBarInputs(TouchBarHelper.baseWindow, inputs);
  }

  /**
   * Inserts a restriction token into the Urlbar ahead of the current typed
   * search term.
   * @param {string} restrictionToken
   *        The restriction token to be inserted into the Urlbar. Preferably
   *        sourced from UrlbarTokenizer.RESTRICT.
   */
  insertRestrictionInUrlbar(restrictionToken) {
    let searchString = TouchBarHelper.window.gURLBar.lastSearchString.trimStart();
    if (Object.values(UrlbarTokenizer.RESTRICT).includes(searchString[0])) {
      searchString = searchString.substring(1).trimStart();
    }

    TouchBarHelper.window.gURLBar.search(`${restrictionToken} ${searchString}`);
    let baseWindow = this.window.docShell.treeOwner.QueryInterface(
      Ci.nsIBaseWindow
    );
    let updater = Cc["@mozilla.org/widget/touchbarupdater;1"].getService(
      Ci.nsITouchBarUpdater
    );
    updater.updateTouchBarInputs(baseWindow, inputs);
  }

  observe(subject, topic, data) {
@@ -396,10 +288,8 @@ class TouchBarHelper {
        // ReaderView button is disabled on every location change since
        // Reader View must determine if the new page can be Reader Viewed.
        kBuiltInInputs.ReaderView.disabled = !data.startsWith("about:reader");
        kBuiltInInputs.Back.disabled = !TouchBarHelper.window.gBrowser
          .canGoBack;
        kBuiltInInputs.Forward.disabled = !TouchBarHelper.window.gBrowser
          .canGoForward;
        kBuiltInInputs.Back.disabled = !this.window.gBrowser.canGoBack;
        kBuiltInInputs.Forward.disabled = !this.window.gBrowser.canGoForward;
        this._updateTouchBarInputs("ReaderView", "Back", "Forward");
        break;
      case "bookmark-icon-updated":
@@ -414,29 +304,8 @@ class TouchBarHelper {
        kBuiltInInputs.ReaderView.disabled = false;
        this._updateTouchBarInputs("ReaderView");
        break;
      case "urlbar-focus":
        if (!this._searchPopover) {
          this._searchPopover = this.getTouchBarInput("SearchPopover");
        }
        gTouchBarUpdater.showPopover(
          TouchBarHelper.baseWindow,
          this._searchPopover,
          true
        );
        break;
      case "urlbar-blur":
        if (!this._searchPopover) {
          this._searchPopover = this.getTouchBarInput("SearchPopover");
        }
        gTouchBarUpdater.showPopover(
          TouchBarHelper.baseWindow,
          this._searchPopover,
          false
        );
        break;
      case "intl:app-locales-changed":
        // On locale change, refresh all inputs after loading new localTitle.
        this._searchPopover = null;
        for (let input in kBuiltInInputs) {
          delete input.localTitle;
        }
@@ -458,6 +327,7 @@ helperProto._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);

/**
 * A representation of a Touch Bar input.
 * Uses async update() in lieu of a constructor to accomodate async l10n code.
 *     @param {object} input
 *            An object representing a Touch Bar Input.
 *            Contains listed properties.
@@ -471,46 +341,21 @@ helperProto._l10n = new Localization(["browser/touchbar/touchbar.ftl"]);
 *            One of `button`, `mainButton`.
 *     @param {Function} input.callback
 *            A callback invoked when a touchbar item is touched.
 *     @param {string} [input.color]
 *     @param {string} input.color (optional)
 *            A string in hex format specifying the button's background color.
 *            If omitted, the default background color is used.
 *     @param {bool} [input.disabled]
 *     @param {bool} input.disabled (optional)
 *            If `true`, the Touch Bar input is greyed out and inoperable.
 *     @param {Array} [input.children]
 *            An array of input objects that will be displayed as children of
 *            this input. Available only for types KInputTypes.POPOVER and
 *            kInputTypes.SCROLLVIEW.
 */
class TouchBarInput {
  constructor(input) {
    this._key = input.key || input.title;
    this._key = input.title;
    this._title = input.hasOwnProperty("localTitle") ? input.localTitle : "";
    this._image = input.image;
    this._type = input.type;
    this._callback = input.callback;
    this._color = hexToInt(input.color);
    this._disabled = input.hasOwnProperty("disabled") ? input.disabled : false;
    if (input.children) {
      this._children = [];
      let toLocalize = [];
      for (let childData of Object.values(input.children)) {
        let initializedChild = new TouchBarInput(childData);
        if (!initializedChild) {
          continue;
        }
        // Children's types are prepended by the parent's type. This is so we
        // can uniquely identify a child input from a standalone input with
        // the same name. (e.g. a button called "back" in a popover would be a
        // "popover-button.back" vs. a "button.back").
        initializedChild.type = input.type + "-" + initializedChild.type;
        this._children.push(initializedChild);
        // Skip l10n for inputs without a title or those already localized.
        if (childData.title && childData.title != "") {
          toLocalize.push(initializedChild);
        }
      }
      this._localizeChildren(toLocalize);
    }
  }

  get key() {
@@ -523,7 +368,7 @@ class TouchBarInput {
    this._title = title;
  }
  get image() {
    return this._image ? PlacesUtils.toURI(this._image) : null;
    return PlacesUtils.toURI(this._image);
  }
  set image(image) {
    this._image = image;
@@ -556,35 +401,6 @@ class TouchBarInput {
  set disabled(disabled) {
    this._disabled = disabled;
  }
  get children() {
    if (!this._children) {
      return null;
    }
    let children = Cc["@mozilla.org/array;1"].createInstance(
      Ci.nsIMutableArray
    );
    for (let child of this._children) {
      children.appendElement(child);
    }
    return children;
  }

  /**
   * Apply Fluent l10n to child inputs.
   * @param {Array} children An array of initialized TouchBarInputs.
   */
  async _localizeChildren(children) {
    let titles = await helperProto._l10n.formatValues(
      children.map(child => ({ id: child.key }))
    );
    // In the TouchBarInput constuctor, we filtered so children contains only
    // those inputs with titles to be localized. We can be confident that the
    // results in titles match up with the inputs to be localized.
    children.forEach(function(child, index) {
      child.title = titles[index];
    });
    gTouchBarUpdater.updateTouchBarInputs(TouchBarHelper.baseWindow, children);
  }
}

const inputProto = TouchBarInput.prototype;
+1 −2
Original line number Diff line number Diff line
@@ -2,5 +2,4 @@
support-files =
  readerModeArticle.html

[browser_touchbar_searchrestrictions.js]
[browser_touchbar_tests.js]
 No newline at end of file
+0 −129
Original line number Diff line number Diff line
/* 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/. */

const { XPCOMUtils } = ChromeUtils.import(
  "resource://gre/modules/XPCOMUtils.jsm"
);

XPCOMUtils.defineLazyModuleGetters(this, {
  UrlbarTokenizer: "resource:///modules/UrlbarTokenizer.jsm",
});

XPCOMUtils.defineLazyServiceGetter(
  this,
  "TouchBarHelper",
  "@mozilla.org/widget/touchbarhelper;1",
  "nsITouchBarHelper"
);

add_task(async function insertTokens() {
  const tests = [
    {
      input: "",
      token: UrlbarTokenizer.RESTRICT.HISTORY,
      expected: "^ ",
    },
    {
      input: "mozilla",
      token: UrlbarTokenizer.RESTRICT.HISTORY,
      expected: "^ mozilla",
    },
    {
      input: "mozilla",
      token: UrlbarTokenizer.RESTRICT.BOOKMARK,
      expected: "* mozilla",
    },
    {
      input: "mozilla",
      token: UrlbarTokenizer.RESTRICT.TAG,
      expected: "+ mozilla",
    },
    {
      input: "mozilla",
      token: UrlbarTokenizer.RESTRICT.OPENPAGE,
      expected: "% mozilla",
    },
    {
      input: "mozilla",
      token: UrlbarTokenizer.RESTRICT.TITLE,
      expected: "# mozilla",
    },
  ];
  let win = BrowserWindowTracker.getTopWindow();
  for (let { input, token, expected } of tests) {
    win.gURLBar.search(input);
    TouchBarHelper.insertRestrictionInUrlbar(token);
    Assert.equal(
      win.gURLBar.value,
      expected,
      "The search restriction token should have been entered."
    );
  }
});

add_task(async function existingTokens() {
  const tests = [
    {
      input: "* mozilla",
      token: UrlbarTokenizer.RESTRICT.HISTORY,
      expected: "^ mozilla",
    },
    {
      input: "+ mozilla",
      token: UrlbarTokenizer.RESTRICT.BOOKMARK,
      expected: "* mozilla",
    },
    {
      input: "( $ ^ mozilla",
      token: UrlbarTokenizer.RESTRICT.TAG,
      expected: "+ ( $ ^ mozilla",
    },
    {
      input: "^*+%?#$ mozilla",
      token: UrlbarTokenizer.RESTRICT.TAG,
      expected: "+ *+%?#$ mozilla",
    },
  ];
  let win = BrowserWindowTracker.getTopWindow();
  for (let { input, token, expected } of tests) {
    win.gURLBar.search(input);
    TouchBarHelper.insertRestrictionInUrlbar(token);
    Assert.equal(
      win.gURLBar.value,
      expected,
      "The search restriction token should have been replaced."
    );
  }
});

add_task(async function stripSpaces() {
  const tests = [
    {
      input: "     ^     mozilla",
      token: UrlbarTokenizer.RESTRICT.HISTORY,
      expected: "^ mozilla",
    },
    {
      input: "     +         mozilla   ",
      token: UrlbarTokenizer.RESTRICT.BOOKMARK,
      expected: "* mozilla   ",
    },
    {
      input: "  moz    illa  ",
      token: UrlbarTokenizer.RESTRICT.TAG,
      expected: "+ moz    illa  ",
    },
  ];
  let win = BrowserWindowTracker.getTopWindow();
  for (let { input, token, expected } of tests) {
    win.gURLBar.search(input);
    TouchBarHelper.insertRestrictionInUrlbar(token);
    Assert.equal(
      win.gURLBar.value,
      expected,
      "The search restriction token should have been entered " +
        "with stripped whitespace."
    );
  }
});
+0 −12
Original line number Diff line number Diff line
@@ -983,14 +983,6 @@ class UrlbarInput {
    return this._setValue(val, true);
  }

  get lastSearchString() {
    return this._lastSearchString;
  }

  get openViewOnFocus() {
    return this._openViewOnFocus;
  }

  get openViewOnFocusForCurrentTab() {
    return (
      this._openViewOnFocusAndSearchString ||
@@ -1782,8 +1774,6 @@ class UrlbarInput {
    if (this.getAttribute("pageproxystate") != "valid") {
      this.window.UpdatePopupNotificationsVisibility();
    }

    Services.obs.notifyObservers(null, "urlbar-blur");
  }

  _on_click(event) {
@@ -1824,8 +1814,6 @@ class UrlbarInput {
    if (this.getAttribute("pageproxystate") != "valid") {
      this.window.UpdatePopupNotificationsVisibility();
    }

    Services.obs.notifyObservers(null, "urlbar-focus");
  }

  _on_mouseover(event) {
+0 −14
Original line number Diff line number Diff line
@@ -18,17 +18,3 @@ open-location = Search or enter address
share = Share
close-window = Close Window
open-sidebar = Sidebars

# This string describes shortcuts for search.
search-popover = Search shortcuts
# Describes searches limited to a specific scope
# (e.g. searching only in history).
search-search-in = Search in:
## Various categories of shortcuts for search.

search-bookmarks = Bookmarks
search-history = History
search-opentabs = Open Tabs
search-tags = Tags
search-titles = Titles
##
Loading