Verified Commit 28647eb6 authored by Kathleen Brade's avatar Kathleen Brade Committed by ma1
Browse files

Bug 26961: New user onboarding.

Reuse the Firefox onboarding mechanism with minimal changes.
Localizable strings are pulled in from Torbutton (if Torbutton is
  not installed, we lack about:tor and no tour will be shown).
Replace SVG images with PNGs (see bug 27002),
For defense in depth, omit include OnboardingTelemetry.jsm entirely.
Added support for the following UITour page event:
  torBrowserOpenSecuritySettings

Also fix bug 27403: the onboarding bubble is not always displayed.

Arthur suggested to make the onboarding bubble visible on displays with
less than 960px width available, so we choose 200px instead.

Also fix bug 28628: Change onboarding Security panel to open new
Security Level panel.

Also fix bug 27484: Improve navigation within onboarding.

Bug 27082: enable a limited UITour

Disallow access to UITour functionality from all pages other than
  about:home, about:newtab, and about:tor.
Implement a whitelist mechanism for page actions.

Bug 26962 - implement new features onboarding (part 1).

Add an "Explore" button to the "Circuit Display" panel within new user
onboarding which opens the DuckDuckGo .onion and then guides users through
a short circuit display tutorial.

Allow a few additional UITour actions while limiting as much as possible
how it can be used.

Tweak the UITour styles to match the Tor Browser branding.

All user interface strings are retrieved from Torbutton's
browserOnboarding.properties file.

Bug 27486 Avoid about:blank tabs when opening onboarding pages.

Instead of using a simple <a href>, programmatically open onboarding
web pages by using tabBrowser.addTab(). The same technique is now
used for "See My Path", "See FAQs", and "Visit an Onion".

Bug 29768: Introduce new features to users

Add an "update" tour for the Tor Browser 8.5 release that contains two
panels: Toolbar and Security (with appropriate description text and
images).

Display an attention-grabbing dot on the onboarding text bubble when
the update tour is active. The animation lasts for 14 seconds.

Bug 31768: Introduce toolbar and network settings changes in onboarding

Update the "Tor Network" onboarding page to include a note that
settings can now be accessed via the application preferences and
add an "Adjust Your Tor Network Settings" action button which opens
about:preferences#tor.

Replace the Tor Browser 8.5 "update" onboarding tour with a 9.0 one
that includes the revised "Tor Network" page and a revised "Toolbar"
page. The latter explains that Torbutton's toolbar item has been
removed ("Goodbye Onion Button") and explains how to access the
New Identity feature using the hamburger menu and new toolbar item.

Bug 34321 - Add Learn More onboarding item

Bug 40429: Update Onboarding for 10.5
parent 74d4cead
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -6,3 +6,8 @@
# * permission is an integer between 1 and 15
# Permissions defined here will also be set for private browsing.
# See PermissionManager.cpp for more...

# UITour
# DuckDuckGo .onion (used for circuit display onboarding).
origin	uitour	1	https://duckduckgogg42xjoc72x3sjasowoarfbgcmvfimaftt6twagswzczad.onion/
origin	uitour	1	about:tor
+6 −0
Original line number Diff line number Diff line
@@ -507,6 +507,12 @@ pref("intl.multilingual.liveReload", false);
// readers, at least on Windows.
pref("accessibility.cache.enabled", true);

// Onboarding.
pref("browser.onboarding.tourset-version", 5);
pref("browser.onboarding.newtour", "welcome,privacy,tor-network-9.0,circuit-display,security,expect-differences,onion-services,learn-more");
pref("browser.onboarding.updatetour", "learn-more");
pref("browser.onboarding.skip-tour-button.hide", true);

#ifdef XP_WIN
// prefs to disable jump-list entries in the taskbar on Windows (see bug #12885)
// this pref changes the app's set AUMID to be dependent on the profile path, rather than
+1 −0
Original line number Diff line number Diff line
@@ -253,6 +253,7 @@
            <toolbarbutton id="UITourTooltipClose" class="close-icon"
                           data-l10n-id="ui-tour-info-panel-close"/>
          </hbox>
          <toolbarseparator id="UITourTooltipToolbarSeparator"/>
          <description id="UITourTooltipDescription" flex="1"/>
        </vbox>
      </hbox>
+7 −0
Original line number Diff line number Diff line
@@ -820,6 +820,13 @@ if (typeof Mozilla == "undefined") {
  Mozilla.UITour.closeTab = function() {
    _sendEvent("closeTab");
  };

  /**
   * @summary Opens the Security Level Panel.
   */
  Mozilla.UITour.torBrowserOpenSecurityLevelPanel = function() {
    _sendEvent("torBrowserOpenSecurityLevelPanel");
  };
})();

// Make this library Require-able.
+121 −5
Original line number Diff line number Diff line
@@ -31,6 +31,26 @@ XPCOMUtils.defineLazyModuleGetters(this, {
// See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
const PREF_LOG_LEVEL = "browser.uitour.loglevel";

const TOR_BROWSER_PAGE_ACTIONS_ALLOWED = new Set([
  "showInfo", // restricted to TOR_BROWSER_TARGETS_ALLOWED
  "showMenu", // restricted to TOR_BROWSER_MENUS_ALLOWED
  "hideMenu", // restricted to TOR_BROWSER_MENUS_ALLOWED
  "showHighlight", // restricted to TOR_BROWSER_TARGETS_ALLOWED
  "hideHighlight", // restricted to TOR_BROWSER_TARGETS_ALLOWED
  "openPreferences",
  "closeTab",
  "torBrowserOpenSecurityLevelPanel",
]);

const TOR_BROWSER_TARGETS_ALLOWED = new Set([
  "torBrowser-newIdentityButton",
  "torBrowser-circuitDisplay",
  "torBrowser-circuitDisplay-diagram",
  "torBrowser-circuitDisplay-newCircuitButton",
]);

const TOR_BROWSER_MENUS_ALLOWED = new Set(["torCircuitPanel"]);

const BACKGROUND_PAGE_ACTIONS_ALLOWED = new Set([
  "forceShowReaderIcon",
  "getConfiguration",
@@ -81,6 +101,28 @@ var UITour = {

  highlightEffects: ["random", "wobble", "zoom", "color", "focus-outline"],
  targets: new Map([
    [
      "torBrowser-circuitDisplay",
      {
        query: aDocument =>
          aDocument.defaultView.gTorCircuitPanel.toolbarButton,
      },
    ],
    [
      "torBrowser-circuitDisplay-diagram",
      torBrowserCircuitDisplayTarget("tor-circuit-panel-body"),
    ],
    [
      "torBrowser-circuitDisplay-newCircuitButton",
      torBrowserCircuitDisplayTarget("tor-circuit-new-circuit"),
    ],
    [
      "torBrowser-newIdentityButton",
      {
        query: "#new-identity-button",
      },
    ],

    [
      "accountStatus",
      {
@@ -277,6 +319,11 @@ var UITour = {
      return false;
    }

    if (!TOR_BROWSER_PAGE_ACTIONS_ALLOWED.has(action)) {
      log.warn("Ignoring disallowed action:", action);
      return false;
    }

    switch (action) {
      case "registerPageID": {
        break;
@@ -615,6 +662,16 @@ var UITour = {
        this.showProtectionReport(window, browser);
        break;
      }

      case "torBrowserOpenSecurityLevelPanel": {
        let securityLevelButton = window.document.getElementById(
          "security-level-button"
        );
        if (securityLevelButton) {
          securityLevelButton.click();
        }
        break;
      }
    }

    // For performance reasons, only call initForBrowser if we did something
@@ -821,6 +878,14 @@ var UITour = {
          ["ViewShowing", this.onAppMenuSubviewShowing],
        ],
      },
      {
        name: "torCircuitPanel",
        node: aWindow.gTorCircuitPanel.panel,
        events: [
          ["popuphidden", this.onPanelHidden],
          ["popuphiding", this.onTorCircuitPanelHiding],
        ],
      },
    ];
    for (let panel of panels) {
      // Ensure the menu panel is hidden and clean up panel listeners after calling hideMenu.
@@ -849,10 +914,7 @@ var UITour = {

  // This function is copied to UITourListener.
  isSafeScheme(aURI) {
    let allowedSchemes = new Set(["https", "about"]);
    if (!Services.prefs.getBoolPref("browser.uitour.requireSecure")) {
      allowedSchemes.add("http");
    }
    let allowedSchemes = new Set(["about", "https"]);

    if (!allowedSchemes.has(aURI.scheme)) {
      log.error("Unsafe scheme:", aURI.scheme);
@@ -901,7 +963,10 @@ var UITour = {
      return Promise.reject("Invalid target name specified");
    }

    let targetObject = this.targets.get(aTargetName);
    let targetObject;
    if (TOR_BROWSER_TARGETS_ALLOWED.has(aTargetName)) {
      targetObject = this.targets.get(aTargetName);
    }
    if (!targetObject) {
      log.warn(
        "getTarget: The specified target name is not in the allowed set"
@@ -1368,6 +1433,10 @@ var UITour = {
  },

  showMenu(aWindow, aMenuName, aOpenCallback = null, aOptions = {}) {
    if (!TOR_BROWSER_MENUS_ALLOWED.has(aMenuName)) {
      return;
    }

    log.debug("showMenu:", aMenuName);
    function openMenuButton(aMenuBtn) {
      if (!aMenuBtn || !aMenuBtn.hasMenu() || aMenuBtn.open) {
@@ -1438,10 +1507,35 @@ var UITour = {
        searchString: SEARCH_STRING,
        allowAutofill: false,
      });
    } else if (aMenuName == "torCircuitPanel") {
      const panel = aWindow.gTorCircuitPanel.panel;

      // Add the listener even if the panel is already open since it will still
      // only get registered once even if it was UITour that opened it.
      panel.addEventListener("popuphiding", this.onTorCircuitPanelHiding);
      panel.addEventListener("popuphidden", this.onPanelHidden);

      panel.setAttribute("noautohide", "true");

      if (panel.state == "open") {
        aOpenCallback?.();
        return;
      }

      this.recreatePopup(panel);

      if (aOpenCallback) {
        panel.addEventListener("popupshown", aOpenCallback, { once: true });
      }
      aWindow.gTorCircuitPanel.toolbarButton.click();
    }
  },

  hideMenu(aWindow, aMenuName) {
    if (!TOR_BROWSER_MENUS_ALLOWED.has(aMenuName)) {
      return;
    }

    log.debug("hideMenu:", aMenuName);
    function closeMenuButton(aMenuBtn) {
      if (aMenuBtn && aMenuBtn.hasMenu()) {
@@ -1456,6 +1550,8 @@ var UITour = {
      closeMenuButton(menuBtn);
    } else if (aMenuName == "urlbar") {
      aWindow.gURLBar.view.close();
    } else if (aMenuName == "torCircuitPanel") {
      aWindow.gTorCircuitPanel.hide();
    }
  },

@@ -1532,6 +1628,12 @@ var UITour = {
    UITour._hideAnnotationsForPanel(aEvent, false, UITour.targetIsInAppMenu);
  },

  onTorCircuitPanelHiding(aEvent) {
    UITour._hideAnnotationsForPanel(aEvent, true, aTarget => {
      return aTarget.targetName.startsWith("torCircuitPanel-");
    });
  },

  onPanelHidden(aEvent) {
    aEvent.target.removeAttribute("noautohide");
    UITour.recreatePopup(aEvent.target);
@@ -1977,6 +2079,20 @@ var UITour = {
  },
};

function torBrowserCircuitDisplayTarget(aElemID) {
  return {
    infoPanelPosition: "rightcenter topleft",
    query(aDocument) {
      let popup = aDocument.defaultView.gTorCircuitPanel.panel;
      if (popup.state != "open") {
        return null;
      }
      let element = aDocument.getElementById(aElemID);
      return UITour.isElementVisible(element) ? element : null;
    },
  };
}

UITour.init();

/**
Loading