From ae933053fd94dca870bcc96b651466ded495eeb6 Mon Sep 17 00:00:00 2001 From: Kathy Brade Date: Tue, 7 Aug 2018 15:11:46 -0400 Subject: [PATCH] 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. --- browser/app/profile/000-tor-browser.js | 5 + browser/components/uitour/UITour-lib.js | 7 + browser/components/uitour/UITour.jsm | 13 +- browser/extensions/onboarding/bootstrap.js | 23 +- .../onboarding/content/Onboarding.jsm | 231 +++++- .../onboarding/content/img/close.png | Bin 0 -> 798 bytes .../onboarding/content/img/figure_addons.svg | 1 - .../content/img/figure_customize.svg | 561 -------------- .../onboarding/content/img/figure_default.svg | 1 - .../onboarding/content/img/figure_library.svg | 689 ------------------ .../content/img/figure_performance.svg | 1 - .../onboarding/content/img/figure_private.svg | 1 - .../content/img/figure_screenshots.svg | 191 ----- .../content/img/figure_singlesearch.svg | 1 - .../onboarding/content/img/figure_sync.svg | 1 - .../img/figure_tor-circuit-display.png | Bin 0 -> 26334 bytes .../img/figure_tor-expect-differences.png | Bin 0 -> 22290 bytes .../content/img/figure_tor-network.png | Bin 0 -> 27931 bytes .../content/img/figure_tor-onion-services.png | Bin 0 -> 40968 bytes .../content/img/figure_tor-privacy.png | Bin 0 -> 35527 bytes .../content/img/figure_tor-security.png | Bin 0 -> 24554 bytes .../content/img/figure_tor-welcome.png | Bin 0 -> 48405 bytes .../onboarding/content/img/icons_addons.svg | 1 - .../content/img/icons_customize.svg | 1 - .../onboarding/content/img/icons_default.svg | 1 - .../onboarding/content/img/icons_library.svg | 1 - .../onboarding/content/img/icons_no-icon.png | Bin 0 -> 673 bytes .../content/img/icons_performance.svg | 1 - .../onboarding/content/img/icons_private.svg | 1 - .../content/img/icons_screenshots.svg | 1 - .../content/img/icons_singlesearch.svg | 1 - .../onboarding/content/img/icons_sync.svg | 1 - .../content/img/icons_tour-complete.png | Bin 0 -> 694 bytes .../content/img/icons_tour-complete.svg | 4 +- .../onboarding/content/img/watermark.svg | 1 - .../content/onboarding-tour-agent.js | 10 + .../onboarding/content/onboarding.css | 84 ++- .../onboarding/content/onboarding.js | 4 +- browser/extensions/onboarding/jar.mn | 7 +- browser/extensions/onboarding/moz.build | 5 +- 40 files changed, 345 insertions(+), 1505 deletions(-) create mode 100644 browser/extensions/onboarding/content/img/close.png delete mode 100644 browser/extensions/onboarding/content/img/figure_addons.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_customize.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_default.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_library.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_performance.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_private.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_screenshots.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_singlesearch.svg delete mode 100644 browser/extensions/onboarding/content/img/figure_sync.svg create mode 100644 browser/extensions/onboarding/content/img/figure_tor-circuit-display.png create mode 100644 browser/extensions/onboarding/content/img/figure_tor-expect-differences.png create mode 100644 browser/extensions/onboarding/content/img/figure_tor-network.png create mode 100644 browser/extensions/onboarding/content/img/figure_tor-onion-services.png create mode 100644 browser/extensions/onboarding/content/img/figure_tor-privacy.png create mode 100644 browser/extensions/onboarding/content/img/figure_tor-security.png create mode 100644 browser/extensions/onboarding/content/img/figure_tor-welcome.png delete mode 100644 browser/extensions/onboarding/content/img/icons_addons.svg delete mode 100644 browser/extensions/onboarding/content/img/icons_customize.svg delete mode 100644 browser/extensions/onboarding/content/img/icons_default.svg delete mode 100644 browser/extensions/onboarding/content/img/icons_library.svg create mode 100644 browser/extensions/onboarding/content/img/icons_no-icon.png delete mode 100644 browser/extensions/onboarding/content/img/icons_performance.svg delete mode 100755 browser/extensions/onboarding/content/img/icons_private.svg delete mode 100644 browser/extensions/onboarding/content/img/icons_screenshots.svg delete mode 100644 browser/extensions/onboarding/content/img/icons_singlesearch.svg delete mode 100644 browser/extensions/onboarding/content/img/icons_sync.svg create mode 100644 browser/extensions/onboarding/content/img/icons_tour-complete.png delete mode 100644 browser/extensions/onboarding/content/img/watermark.svg diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js index 74c7f35b98cd5..35a534de05b00 100644 --- a/browser/app/profile/000-tor-browser.js +++ b/browser/app/profile/000-tor-browser.js @@ -295,6 +295,11 @@ pref("browser.download.panel.shown", true); // Treat .onions as secure pref("dom.securecontext.whitelist_onions", true); +// Onboarding. +pref("browser.onboarding.newtour", "welcome,privacy,tor-network,circuit-display,security,expect-differences,onion-services"); +pref("browser.onboarding.updatetour", "welcome,privacy,tor-network,circuit-display,security,expect-differences,onion-services"); +pref("browser.onboarding.skip-tour-button.hide", true); + // prefs to disable jump-list entries in the taskbar on Windows (see bug #12885) #ifdef XP_WIN // this pref changes the app's set AUMID to be dependent on the profile path, rather than diff --git a/browser/components/uitour/UITour-lib.js b/browser/components/uitour/UITour-lib.js index e1d4637da3f8e..27092013ac714 100644 --- a/browser/components/uitour/UITour-lib.js +++ b/browser/components/uitour/UITour-lib.js @@ -715,6 +715,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. diff --git a/browser/components/uitour/UITour.jsm b/browser/components/uitour/UITour.jsm index 1cbb861ccdf77..3c3fa00733f78 100644 --- a/browser/components/uitour/UITour.jsm +++ b/browser/components/uitour/UITour.jsm @@ -69,7 +69,11 @@ ChromeUtils.defineModuleGetter( const PREF_LOG_LEVEL = "browser.uitour.loglevel"; const TOR_BROWSER_PAGE_ACTIONS_ALLOWED = new Set([ - // Add page actions used by Tor Browser's new user/feature onboarding here. + "showInfo", // restricted to TOR_BROWSER_TARGETS_ALLOWED + "showMenu", // restricted to TOR_BROWSER_MENUS_ALLOWED + "hideMenu", // restricted to TOR_BROWSER_MENUS_ALLOWED + "closeTab", + "torBrowserOpenSecurityLevelPanel", ]); const BACKGROUND_PAGE_ACTIONS_ALLOWED = new Set([ @@ -762,6 +766,13 @@ var UITour = { } 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 diff --git a/browser/extensions/onboarding/bootstrap.js b/browser/extensions/onboarding/bootstrap.js index 9871954c9cbad..9fa1094d5eea3 100644 --- a/browser/extensions/onboarding/bootstrap.js +++ b/browser/extensions/onboarding/bootstrap.js @@ -8,7 +8,6 @@ ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); XPCOMUtils.defineLazyModuleGetters(this, { OnboardingTourType: "resource://onboarding/modules/OnboardingTourType.jsm", - OnboardingTelemetry: "resource://onboarding/modules/OnboardingTelemetry.jsm", Services: "resource://gre/modules/Services.jsm", UIState: "resource://services-sync/UIState.jsm", }); @@ -21,7 +20,11 @@ const RESOURCE_HOST = "onboarding"; const {PREF_STRING, PREF_BOOL, PREF_INT} = Ci.nsIPrefBranch; -const BROWSER_READY_NOTIFICATION = "browser-delayed-startup-finished"; +// In Tor Browser we initialize onboarding upon "final-ui-startup" instead +// of waiting for "browser-delayed-startup-finished"; otherwise, on first +// run the onboarding frame script's "onload" listener is installed too +// late to detect that about:tor is loaded. +const BROWSER_READY_NOTIFICATION = "final-ui-startup"; const BROWSER_SESSION_STORE_NOTIFICATION = "sessionstore-windows-restored"; const PREF_WHITELIST = [ ["browser.onboarding.enabled", PREF_BOOL], @@ -33,6 +36,17 @@ const PREF_WHITELIST = [ ]; [ + // Tor Browser tours: + "onboarding-tour-tor-welcome", + "onboarding-tour-tor-privacy", + "onboarding-tour-tor-network", + "onboarding-tour-tor-circuit-display", + "onboarding-tour-tor-security", + "onboarding-tour-tor-expect-differences", + "onboarding-tour-tor-onion-services", +#if 0 +// Firefox tours. To reduce conflicts when rebasing against newer Firefox +// code, we use the preprocessor to omit this code block. "onboarding-tour-addons", "onboarding-tour-customize", "onboarding-tour-default-browser", @@ -42,6 +56,7 @@ const PREF_WHITELIST = [ "onboarding-tour-screenshots", "onboarding-tour-singlesearch", "onboarding-tour-sync", +#endif ].forEach(tourId => PREF_WHITELIST.push([`browser.onboarding.tour.${tourId}.completed`, PREF_BOOL])); let waitingForBrowserReady = true; @@ -155,6 +170,8 @@ function initContentMessageListener() { isLoggedIn: syncTourChecker.isLoggedIn(), }); break; +#if 0 +// No telemetry in Tor Browser. case "ping-centre": try { OnboardingTelemetry.process(msg.data.params.data); @@ -162,6 +179,7 @@ function initContentMessageListener() { Cu.reportError(e); } break; +#endif } }); } @@ -173,7 +191,6 @@ function onBrowserReady() { waitingForBrowserReady = false; OnboardingTourType.check(); - OnboardingTelemetry.init(startupData); Services.mm.loadFrameScript("resource://onboarding/onboarding.js", true, true); initContentMessageListener(); } diff --git a/browser/extensions/onboarding/content/Onboarding.jsm b/browser/extensions/onboarding/content/Onboarding.jsm index 7636dcd41ebea..1c6529d06b464 100644 --- a/browser/extensions/onboarding/content/Onboarding.jsm +++ b/browser/extensions/onboarding/content/Onboarding.jsm @@ -11,6 +11,8 @@ var EXPORTED_SYMBOLS = ["Onboarding"]; ChromeUtils.import("resource://gre/modules/Services.jsm"); const ONBOARDING_CSS_URL = "resource://onboarding/onboarding.css"; +const TORBUTTON_BUNDLE_URI = "chrome://torbutton/locale/browserOnboarding.properties"; +const TORBROWSER_WELCOME_TOUR_NAME_KEY = "onboarding.tour-tor-welcome"; const BUNDLE_URI = "chrome://onboarding/locale/onboarding.properties"; const UITOUR_JS_URI = "resource://onboarding/lib/UITour-lib.js"; const TOUR_AGENT_JS_URI = "resource://onboarding/onboarding-tour-agent.js"; @@ -20,8 +22,8 @@ const BRAND_SHORT_NAME = Services.strings const PROMPT_COUNT_PREF = "browser.onboarding.notification.prompt-count"; const NOTIFICATION_FINISHED_PREF = "browser.onboarding.notification.finished"; const ONBOARDING_DIALOG_ID = "onboarding-overlay-dialog"; -const ONBOARDING_MIN_WIDTH_PX = 960; -const SPEECH_BUBBLE_MIN_WIDTH_PX = 1365; +const ONBOARDING_MIN_WIDTH_PX = 200; +const SPEECH_BUBBLE_MIN_WIDTH_PX = 200; const SPEECH_BUBBLE_NEWTOUR_STRING_ID = "onboarding.overlay-icon-tooltip2"; const SPEECH_BUBBLE_UPDATETOUR_STRING_ID = "onboarding.overlay-icon-tooltip-updated2"; const ICON_STATE_WATERMARK = "watermark"; @@ -82,6 +84,133 @@ function createOnboardingTourButton(div, buttonId, l10nId, buttonElementTagName return aside; } +// Tor Browser tours: +var onboardingTourset = { + "welcome": { + id: "onboarding-tour-tor-welcome", + tourNameId: TORBROWSER_WELCOME_TOUR_NAME_KEY, + instantComplete: true, + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-welcome.title", "onboarding.tour-tor-welcome.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-welcome.png"); + createOnboardingTourButton(div, + "onboarding-tour-tor-welcome-button", "onboarding.tour-tor-welcome.next-button"); + + return div; + }, + }, + "privacy": { + id: "onboarding-tour-tor-privacy", + tourNameId: "onboarding.tour-tor-privacy", + instantComplete: true, + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-privacy.title", "onboarding.tour-tor-privacy.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-privacy.png"); + createOnboardingTourButton(div, + "onboarding-tour-tor-privacy-button", "onboarding.tour-tor-privacy.button"); + + return div; + }, + }, + "tor-network": { + id: "onboarding-tour-tor-network", + tourNameId: "onboarding.tour-tor-network", + instantComplete: true, + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-network.title", "onboarding.tour-tor-network.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-network.png"); + createOnboardingTourButton(div, + "onboarding-tour-tor-network-button", "onboarding.tour-tor-network.button"); + + return div; + }, + }, + "circuit-display": { + id: "onboarding-tour-tor-circuit-display", + tourNameId: "onboarding.tour-tor-circuit-display", + instantComplete: true, + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-circuit-display.title", "onboarding.tour-tor-circuit-display.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-circuit-display.png"); + let btnContainer = createOnboardingTourButton(div, + "onboarding-tour-tor-circuit-display-button", "onboarding.tour-tor-circuit-display.button"); + btnContainer.className = "onboarding-tour-tor-action-button-container"; + createOnboardingTourButton(div, + "onboarding-tour-tor-circuit-display-next-button", "onboarding.tour-tor-circuit-display.next-button"); + + return div; + }, + }, + "security": { + id: "onboarding-tour-tor-security", + tourNameId: "onboarding.tour-tor-security", + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-security.title", "onboarding.tour-tor-security.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-security.png"); + let btnContainer = createOnboardingTourButton(div, + "onboarding-tour-tor-security-button", "onboarding.tour-tor-security-level.button"); + btnContainer.className = "onboarding-tour-tor-action-button-container"; + createOnboardingTourButton(div, + "onboarding-tour-tor-security-next-button", "onboarding.tour-tor-security-level.next-button"); + + return div; + }, + }, + "expect-differences": { + id: "onboarding-tour-tor-expect-differences", + tourNameId: "onboarding.tour-tor-expect-differences", + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-expect-differences.title", "onboarding.tour-tor-expect-differences.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-expect-differences.png"); + let btnContainer = createOnboardingTourButton(div, + "onboarding-tour-tor-expect-differences-button", "onboarding.tour-tor-expect-differences.button"); + btnContainer.className = "onboarding-tour-tor-action-button-container"; + createOnboardingTourButton(div, + "onboarding-tour-tor-expect-differences-next-button", "onboarding.tour-tor-expect-differences.next-button"); + + return div; + }, + }, + "onion-services": { + id: "onboarding-tour-tor-onion-services", + tourNameId: "onboarding.tour-tor-onion-services", + getPage(win) { + let div = win.document.createElement("div"); + + createOnboardingTourDescription(div, + "onboarding.tour-tor-onion-services.title", "onboarding.tour-tor-onion-services.description"); + createOnboardingTourContent(div, "resource://onboarding/img/figure_tor-onion-services.png"); + let btnContainer = createOnboardingTourButton(div, + "onboarding-tour-tor-onion-services-button", "onboarding.tour-tor-onion-services.button"); + btnContainer.className = "onboarding-tour-tor-action-button-container"; + createOnboardingTourButton(div, + "onboarding-tour-tor-onion-services-next-button", "onboarding.tour-tor-onion-services.next-button"); + + return div; + }, + }, +}; +#if 0 +// Firefox tours. To reduce conflicts when rebasing against newer Firefox +// code, we use the preprocessor to omit this code block. /** * Add any number of tours, key is the tourId, value should follow the format below * "tourId": { // The short tour id which could be saved in pref @@ -415,6 +544,7 @@ var onboardingTourset = { }, }, }; +#endif /** * The script won't be initialized if we turned off onboarding by @@ -473,7 +603,10 @@ class Onboarding { // We want to create and append elements after CSS is loaded so // no flash of style changes and no additional reflow. await this._loadCSS(); - this._bundle = Services.strings.createBundle(BUNDLE_URI); + this._bundle = new _TorOnboardingStringBundle(); + if (!this._bundle.inited) { + return; + } this._loadJS(UITOUR_JS_URI); @@ -515,7 +648,11 @@ class Onboarding { } _resizeUI() { - this._windowWidth = this._window.document.body.getBoundingClientRect().width; + // In Tor Browser we check against innerWidth instead of against the + // body's bounding rect because about:tor keeps its body hidden until + // the Tor status is known, and the bounding rect is zero while the + // body is hidden. + this._windowWidth = this._window.innerWidth; if (this._windowWidth < ONBOARDING_MIN_WIDTH_PX) { // Don't show the overlay UI before we get to a better, responsive design. this.destroy(); @@ -523,7 +660,13 @@ class Onboarding { } this._initUI(); - if (this._isFirstSession && this._windowWidth >= SPEECH_BUBBLE_MIN_WIDTH_PX) { + // For Tor Browser, show the "Let's get started" speech bubble until each + // tour item has been completed. + let isTourComplete = (ICON_STATE_WATERMARK == + Services.prefs.getStringPref("browser.onboarding.state", + ICON_STATE_DEFAULT)); + if ((!isTourComplete || this._isFirstSession) && + this._windowWidth >= SPEECH_BUBBLE_MIN_WIDTH_PX) { this._overlayIcon.classList.add("onboarding-speech-bubble"); } else { this._overlayIcon.classList.remove("onboarding-speech-bubble"); @@ -556,7 +699,8 @@ class Onboarding { this._onIconStateChange(Services.prefs.getStringPref("browser.onboarding.state", ICON_STATE_DEFAULT)); // Doing tour notification takes some effort. Let's do it on idle. - this._window.requestIdleCallback(() => this.showNotification()); +// For now, onboarding notifications are disabled in Tor Browser. +// this._window.requestIdleCallback(() => this.showNotification()); } _getTourIDList() { @@ -698,6 +842,7 @@ class Onboarding { ({ id, classList } = target.firstChild); } + let handledTourActionClick = false; switch (id) { case "onboarding-overlay-button": this.telemetry({ @@ -766,6 +911,16 @@ class Onboarding { this.gotoPage(tourId); this._removeTourFromNotificationQueue(tourId); break; + case "onboarding-tour-tor-welcome-button": + case "onboarding-tour-tor-privacy-button": + case "onboarding-tour-tor-network-button": + case "onboarding-tour-tor-circuit-display-next-button": + case "onboarding-tour-tor-security-next-button": + case "onboarding-tour-tor-expect-differences-next-button": + case "onboarding-tour-tor-onion-services-next-button": + this.gotoNextTourItem(); + handledTourActionClick = true; + break; } if (classList.contains("onboarding-tour-item")) { this.telemetry({ @@ -779,7 +934,8 @@ class Onboarding { // Keep focus (not visible) on current item for potential keyboard // navigation. target.focus(); - } else if (classList.contains("onboarding-tour-action-button")) { + } else if (!handledTourActionClick && + classList.contains("onboarding-tour-action-button")) { let activeTourId = this._activeTourId; this.setToursCompleted([ activeTourId ]); this.telemetry({ @@ -792,6 +948,21 @@ class Onboarding { } } + gotoNextTourItem() { + let activeTourID = this._activeTourId; + if (activeTourID) { + let idx = this._tourItems.findIndex(item => (item.id === activeTourID)); + if (idx >= 0) { + // If at the end of the list, close onboarding; otherwise, go to next. + if (++idx >= this._tourItems.length) { + this.hideOverlay(); + } else { + this.gotoPage(this._tourItems[idx].id); + } + } + } + } + /** * Wrap keyboard focus within the dialog. * When moving forward, focus on the first element when the current focused @@ -1421,7 +1592,8 @@ class Onboarding { let header = this._window.document.createElement("header"); header.id = "onboarding-header"; - header.textContent = this._bundle.GetStringFromName("onboarding.overlay-title2"); +// In Tor Browser, we do not want header text. +// header.textContent = this._bundle.GetStringFromName("onboarding.overlay-title2"); this._dialog.appendChild(header); let nav = this._window.document.createElement("nav"); @@ -1490,7 +1662,7 @@ class Onboarding { watermarkImg.id = "onboarding-overlay-button-watermark-icon"; watermarkImg.setAttribute("role", "presentation"); watermarkImg.src = Services.prefs.getStringPref("browser.onboarding.watermark-icon-src", - "resource://onboarding/img/watermark.svg"); + "resource://onboarding/img/tor-watermark.png"); button.appendChild(watermarkImg); return button; } @@ -1578,3 +1750,44 @@ class Onboarding { doc.head.appendChild(script); } } + +// _TorOnboardingStringBundle implements the subset of the nsIStringBundle +// that is used by the code in this file. It checks first for strings inside +// Torbutton's browserOnboarding.properties file and secondarily in Firefox's +// onboarding.properties file. +class _TorOnboardingStringBundle { + constructor() { + this._mFirefoxBundle = Services.strings.createBundle(BUNDLE_URI); + this._mTorButtonBundle = Services.strings.createBundle(TORBUTTON_BUNDLE_URI); + + // If the Tor Browser onboarding strings which ship inside Torbutton are + // not available, fail initialization so that no tours are shown. + try { + let result = this._mTorButtonBundle.GetStringFromName( + TORBROWSER_WELCOME_TOUR_NAME_KEY); + this.inited = true; + } catch (e) {} + } + + GetStringFromName(aName) { + let result; + try { + result = this._mTorButtonBundle.GetStringFromName(aName); + } catch (e) { + result = this._mFirefoxBundle.GetStringFromName(aName); + } + return result; + } + + formatStringFromName(aName, aParams, aLength) { + let result; + try { + result = this._mTorButtonBundle.formatStringFromName(aName, aParams, + aLength); + } catch (e) { + result = this._mFirefoxBundle.formatStringFromName(aName, aParams, + aLength); + } + return result; + } +} \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/close.png b/browser/extensions/onboarding/content/img/close.png new file mode 100644 index 0000000000000000000000000000000000000000..8a637de879ec7c425bb41de7c991736e9b593aa1 GIT binary patch literal 798 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>eb7e?3y(dC?< zTTql*TnyA^X9(4TEQYS$zbG>m=s%D(aP`Py=;{M9@=Nl8VO^A&?3q`RS_HHVsvG7& z+$x}E+316U3n};@aRU|wMvfhqjXpf0?YQ_|wI&1Oev+q)V~B-da)JbFvmVQg!W|my z8t=G{v=^QTXF7Vd@rMmxCC|gG1t;ni-W{LN*wOgJp=}b&t;SUsdEXvTa+|cUHh|f| z#AvpP^99kvF4oed%QtnirmG6ehUuhE7UO_5x=17{addons \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/figure_customize.svg b/browser/extensions/onboarding/content/img/figure_customize.svg deleted file mode 100644 index 0c0cb30df5dc7..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_customize.svg +++ /dev/null @@ -1,561 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/extensions/onboarding/content/img/figure_default.svg b/browser/extensions/onboarding/content/img/figure_default.svg deleted file mode 100644 index c52e4b8500f7b..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_default.svg +++ /dev/null @@ -1 +0,0 @@ -default-browser \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/figure_library.svg b/browser/extensions/onboarding/content/img/figure_library.svg deleted file mode 100644 index aad20181b9964..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_library.svg +++ /dev/null @@ -1,689 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/extensions/onboarding/content/img/figure_performance.svg b/browser/extensions/onboarding/content/img/figure_performance.svg deleted file mode 100644 index f7c5c219aada8..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_performance.svg +++ /dev/null @@ -1 +0,0 @@ -performance \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/figure_private.svg b/browser/extensions/onboarding/content/img/figure_private.svg deleted file mode 100644 index f90163e4b4d77..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_private.svg +++ /dev/null @@ -1 +0,0 @@ -private-browsing \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/figure_screenshots.svg b/browser/extensions/onboarding/content/img/figure_screenshots.svg deleted file mode 100644 index f4930d09f7af5..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_screenshots.svg +++ /dev/null @@ -1,191 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/browser/extensions/onboarding/content/img/figure_singlesearch.svg b/browser/extensions/onboarding/content/img/figure_singlesearch.svg deleted file mode 100644 index 9be029397ccfe..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_singlesearch.svg +++ /dev/null @@ -1 +0,0 @@ -search \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/figure_sync.svg b/browser/extensions/onboarding/content/img/figure_sync.svg deleted file mode 100644 index 74562d37236da..0000000000000 --- a/browser/extensions/onboarding/content/img/figure_sync.svg +++ /dev/null @@ -1 +0,0 @@ -sync \ No newline at end of file diff --git a/browser/extensions/onboarding/content/img/figure_tor-circuit-display.png b/browser/extensions/onboarding/content/img/figure_tor-circuit-display.png new file mode 100644 index 0000000000000000000000000000000000000000..ea6ecb7f82a32327661387aa3011ec37e2844111 GIT binary patch literal 26334 zcmdSBhgVZU*DriRAVFF{xHy%&2>_@N06520q1FJvLl^)y%m6_0 z0|3yvWHf0@0{|Yeot~k)p}Lx+g|n03OG{^SD?x837aRuwNPA1-E}g90Un0Dn9ACLf zddsl>he8r}{jXYx74aVucLy0(Lv<~Lg0rg?LR9d+pfIZ}5dwjbcD1yY)KOIaZ+2Ws zhSk>H-9=JJ$ji%1(CeO{v#X8JT?q*ZAz=|A5fK3#g@BvSEBBY)09qL|1B0yK%swkgzgFo3;j>q zI9BO@wURnkZqAM#|C-l-W#=v{BK;rY|F`=8^!8s|3eHY0u2ybtI5ye4|IPA$*Zsfr znyz+MIQjl{^FQ?ecisO>uVw4(?u;92S38SGuiUL%ah?4)_y2yt|8I)_ZcAF|-*Ek3 z!}njh`A;oQIkH63LjR*^St6JcZz2F7fk%q+dfuSz%v%}R`W`2{TTc>tEg#Z6^hDg! zepp60LS6CX!j5mO-Y6v*uVU1E)1a$9uTrOCfRBd*Mb4`3`e^Hw#2`C5C;PcQ_upWbrLp8S5-^{Q<8 zDF$psV7QTA`LvfZs|YUcG#TYRH9DG2n!>>PBbW&-z1h?XE3hBH1ezV_>S8{Nz*xDshOZdWRlG1K;;Q@Pl&_k$z__f z80Fz3)&BUZntC3`&25tCpF6r0%o8pHTh9%~sV=Hozwq%_OP;RBa<`iv(!Q~AHuXx1 z-?m9JiIDZWnL--sk28urPq(`%DQ2FSvkQQ*R@b%hPD>zzstNMicvgqIiu}IRL3^$H z;uD3;3$I)PqmBrg2cUEQQsGtVPB}LNT!D8Ujujg2%B`%Rqh55Hqq6no?v*=ypza8f z|BA92P#|%IZ~(}xgZ!6fVLq&>|yNV*`+p8&5tcYcQc{&AbD@W~$zGHAN=S@3={c z31;-&r$0C(t$GMw^ndB3aCj>aBZdWp0jKe61&gSte32WTM=-q?Azk{cM&=l=Ni&3f z55$}%QrLy=zIrYv*&d-@tIR_D&W?E8Jcqd%`CVH&{t5uiq^OKyzyNp6B2{bF5MTk+ zLhepyFtR46h-E5xc16tW!E?pBswS2VyDy$B5J?XxiRHj|1jm#G<{_rsuG9wrzsbiU)>K zVBX!8A(tlqbu=y?x zjz<4Nfg|YL0V1=nK$O$r;dc-jIRG@D$8@`)-Vv&<011T6;wo~Adh+mepd-{;^CMcH zajjd$kHphfBO@u)mN>w^MvP@j*504osZ0ht|J*`y@C)X=Q)0y43@n6in5&?xdQJq2 zLzNfR>{$?-5yG0*?)jia=LrcD@B%-7yeG^F(^l~-0BGk!qyxzZ;RmPWcvRI+HZ_7g zCYnFKgB9FT4%UZX`+db&%-maQu7ElN23>oKXuem$KkYq*BH zLTxzXDll{QuHt1Xsqg48jnjZwz+~^p*txP?6~osDcbRO zX5J&2AJi$4kpx@6x-JlQ51nwdQ3b`@r8_W9lHR7 z)gj1KDeyBG?jKA#K@e0sIK={!`~EmRuTor#I_(Q%OwF}!7QCc^hb1Lm9*anIHXATU z)eb;LuT)^&NAbQ4J&GczC*h<-WT&7oF$OJugL}v+M}$*tPd?j8ipe0jhQtIJVn?w$ z0BSaE=r2MuCXG)6mho+)r}smn{3QaX;`&y_`XZg~o<=^-34kQj(V%mj)dSp4~D)4#z3p_?F;)od2gDf7WnNDYm%S-p* z%o70!%@W_Tassypl;D}CLep;pq zvghWdH%T9%ynRVITt@=A)N70 z3KBESJj5kmb`uKD;>OP;KT>2R@y&xd7HMihu#Uk!Meh&OJ>y~#_5mOSV(J&`=c%>y zGwTQSpuj_V#5a{g=)(tMc`(*k6UzamY+G6c*ndq9h}=b-_c0S}6$zb&1!~2T3^K^R z5ih$os?UGAW(fE?ALf~jgh(jwHs{M^@7z7F<(WqAt z-eWnX&megm!L5kDTiN%4Su;{>D1yA|XVH^-yAg=w!QDI6^&s=9@G4E<3DGTE+Z5mB zNy^X|aRCD1pPm3^J2&rFv7&DB<0S?V34k}is=!V(0cJ;0I|*khht=>)el9ImPqm`l zo+pl=x>z8X5S!AAEqyRgY#~9~nFcAq*A+ zhw&#&exHiE3boN?-&7%?f>2^QQDcWTHbQVNNhv(3{t2oFp;MhTt{gp*uKksK-f8v$?uA*9iwej9hWz5^a&%&^H8$Qsg;(e55M%o|XLn-@puE4qcH-eYxD8k?5 z*J1OZvd3R5S>G?3*tLs&>dfv6|kgox^M8*#;OrC#pKvz6Kt5H zBBdx%8~y4~o{yA!0D4!8APL2X!RrxLjWn`l-a`z5=;$wd2AH?3e@F6gU)B;M?v~gw z7#U4F29(A^G0If*Y?aqr+8pYpsdyrz-wf(~fdpEyFI`76=T{HYiyorbTP7mf+(>84 z3oNg~;=Xe#WllVqdnWf|BPJ|71|H)%2&HK2@H(WvSSJoZw*7DiTRd7MX?hermXL$D!3vO6vsNM$3?WG)>kAmlsJiDbj?IpI|V>43zca1Z@AyF)w_ zfHx6ATH66aI&N=Ah-5^sQ4R|Ov~w7h0;LdD`uZGVRs!+$d-Wjiy@!e=sQUrU}$um#pf82!Gu= z99eM0j#`m@E?txXqP%gPW)j5^;}y{9kq;vvg5a=@?s-dLus6xT`=nG^2t7C!t>~^m z4<^ndqh}SFGBQlB>qLZRmk(>Ikujq8UZO<(XXOhmLD?>EWh^B)p{gL*M-E@YtO)H(YlX8bLyR$`qHr8&U){8#+#t6V0u z!3(Z?0Jxwb1`w|q*eY)Be9KiMRa{EepAriVyVgt5%#N9+M1$WtUN6hFKqSE<-RZxn zH)BysRCssIfcQ@vThv^RK8CY#+igWLQc*KwbM|1pVWDLp>dzEOi?|I&yZf4dYzP2h z-gIa%#gpOpfNoEFGlYP*(qU!~6?p;UTweS1&`+CR5MF(;-`j7m zAXQZia>LB-I^83h2S|EJ#1`mVNoOGIgUfJd_h1F5e*4~?2CSIokAASi&EIlof7IcQ z^W;Uy={Ae!g{JlE;bw7VnW4}Ux z^rf@P@rPS##fM}Bxn;VO{q`51eG?n|EzNy20#&lM%z_P=*Ujor-}ND7xlXiVD2%1t zJp3w{B5E#dKR5DRa#!Ewa#eH19yBgwOgiQ6Gft!I!HmN1E;=10o2yu+0qk$Jh!W_$ z_e#dVOy+cONpWmBo;LiHE`iq)@RQ1ls8uhAY%V{9Dw=aIt zpd#1V=fgFWd=Al)r>t7^goCdfn7o7qrtV=@7$r8HXtwXb@KL#LR-@#$-9$G$Qm_#` z1LuITi_UmY;tMBX=b)pg0U!IburV2@quf6(&THwZ1SuXDBzooLl4l8zgDgCj7wlmp zMs4{I4%Rk`4-yoV73o(C^joj01?t?SpSfeeFZ11Be`?Xe>gY61*`E3M8Sd?Bh6#Ad zQMCCUePOc|a875+XMo5BXDD1?-=GNqd;nk^kzWQ0k+HH_rgA2T$OHq@gj&JSs-ZDh zQJ|s=9v>^~l%gDi?7~w&N3&n7wT{fR9*QptYWvB8;QcQJ-mQ@gY}Rm-rGm!-x8oNa z%m%q{co<+Kx1WIwrh~kcy!RAVlhwbsupOWOy=NWHC1ga?H)A%p@B=+IEqm@4JdcV6 zNLcTnA2q+EaxlXaz~U4w1#` z0$#0-uV1h=ugkjpBb z>kr$p@g0Jfv1Eq|i=jfJzgT594MK5NSq{W(?7>tzwc`(@%ta;%x95~>S!lf|x`}3* zpnY^KwKhkC3Dq@dpwHaF`bmY}1t~2EM#ST>@7>A(_>p90>_JuE$0}TR5L0jPWoJNd zos49(sV_6Yu4{m5b*k&u2&e88cpxjoiNPX(l<&OuMUXN;b~8QZP{_CcfYuioVR+x@bJL_W4qsJnmZB0~e+!nIp!($9I~O+R^FwLj%iIBWY3i!UBPCSn$)A|WlLl;2+)IAc z`?SP26bP2bKlGJ(U9gq?aw%^yy_~bvgmJf>r{M1wSqOwddhytUqul5we`7qWUOyuf zINbxY_fJn+AB0LHTpn$z@IKib_Lp^*ttx1-lQoTLipT2E_dkt+h6&x)(`auk#zp&) zw|p_6kN84q>09s;J(#$e{>J;0z-H*<0Wg^%hxg!&NT6j-+gaZ}-X*mXrf!ta`kc*Vwy*etd)@ zDKzof{o`=dNh?=B-t$4Im>k%R%z^pc(K12OGYy4y<;g|<$5(#WqyU-`_b;>`C(Ly z&Ch1Amzz;(4CFwy>OI=)2jrZ8D|`^f1)uRfz;>792CU9vv?H3xoNxJMaqDfaEFA%+ zvu|G6W>U1Bc07m9o}!yxLuiQzb z72wchXO6X`t71b7X&>*n;+~(YS3-- zjqGroU?ROSySK9<#$Wsik#X7Rj&V73IZpZV^3Pk!v86X%E9l}eG0jMMGDF=(YiE2| zM&nBh!`FX1gH3Jz1lQf8<#%08LPK9&VmEl!L&0N74U-J<&>>i6)C3D?$A|&5GirvuDl)R&f<(iGhPFepV5-29AXg!*yZQ9)2c$lITT6gab#jPay zfPjG9((1eJCx?nzeV;ycxNU6Q*?8DLn5Ctg7@$@^)pnX06!Ym*-zP0oW2Q2O4d_u0 z^Y7NiN=vsGe#!VpN8g)v;0Xg0BXpa#iN}gPYm72l_Oz?5Dov1!9tk~$c1Tu0DFf5# z;(Uif@b=bhjnw7l_)hPK;`woq15w77`r9qEP5b=i-WF}9XnD=lwaW1cgyF@r>VpE- zeV43*cX~qb^@SHrIx?Y_`m#nw!-mulUuaCV-+lTG%jQ$%8f}k7+Sv0rTrMTHFuR7s zwB1r)lfgc{=4SmDrd(^9(s&0YItcd&usBBU4({}%lR=2wKcVC0B9s^9mHp3->?Azm zrnJ)DTesV#I%)+N71zXLh-B+N>Rk?{CO>^p#p8b}`=eICTO~o4zDYN*uJC@v6Ax_@ z{pZx@O*QqpvZxOSwfv*uS!B^<#R-g6MMKlGV|U?Z!h6i7JS2Azk3}&!HhaTT>QMD6%&nTT9~8M__(-t`o$(@oP4YC978>oU<|UcfzI@?Cm^S9OL8? zH#U|2h>oP1Uzsr#2)0d;sXF<5yd}ovn-^K$xkfT2y<}!LIWV$L zkj0Kb&K|Ne71+tHq`;4~J$T0(mpwFi;Yaj04<}O5j@|jPU5_u~1(zk3b&VNL=W|~f zY>&(^B{`899)uJRZ-A~u$1&`S136!XArTOrwEoH`Q0jvrmdV;glKI*!+(?ZUioD)S zH<`Q@yF65{%g{T{?(`_zojWvET2fc4K+d%Iko$e>V}kn$x>Vtr*y3$f7|+TOxV>j= z{`0j_neV8&l0Dt}GW-J^=I+VJ$as3bSqUmglF#i3eV=sCmYY(O|4U8T9h^VNn@oa@ z6k;;#DfR^sAPaX@A#_n`s=5pXPwKTaQ&GyE>ofKi#zBJbTacjR_DH;2@WihdlPCklzFUPUl90cJN{Fz22&O1bmyn`9H?)zJ*%p1 zP6r(nhA;z*lYN*${$Ui}kV`8CztCx{jW+=^0ptLs)qD~<6AR?kk{&AU_0|dP<^JBV zM6n4yJD9L;PZb2?tIpG1piQU1xU2;SrNdqAb2^l!L zX;J}`F9|77b(MTt+wB99oJ1)aw2(a3#z$w6?varC7b(%3A-IftUJIJ^z3)e%6W)rn zl?yDhpz%GhPfU(@p*d{AE2vQ4UXVzS{2~`Y$(kvV!CsH`zKY2a->O4zCs?W3^(Coi z32bEWI@w98M}vMvEw$#jh2;bz46_{o?(h@_tvriU@^KSGN_P?H`14i$(o~V{7v(Dk!rLr8TPq-dV%$0o!F|P zZ@*@HY~cf#AtdSnnK%Pg!5z#QkJ%_LX*G}5@!7W)ea2)ZIUfqZRmHxwjNYQshsxDN z9kWLK!9*Q*3AOgf+bQPRDoGb~#xRmwB|KyDSq45Qu|p#W8}JP#O6%DbQl|(abn;%* zEa$fro+}{dMogA}^%7%rj1x1xFlmmk=4)-495jLxk_ch6BI$k^{B1*mR>@~cUK#2! z^knkxWuqAP(?eyr7K-^XRMbN<+|*~^p^7bK&g42Lxm>3%d<)@itV#q0Tx2^ z=C+kG)oEhmr@|QVd!D3B{j{$!J>w7VZNPXL~ zP~jXm0E>ytdX-eN2NS%)i!Y8IJJ?tYbiiJQyC*)qQRSgU#HXlnrd|z=sjmDrGSaDk z)GuYG-W1)6eh9a@FqsQafk93lu_N z-R(lKq+#Q-C3JPqUMoLb#JyClY2YI_Nt?d}Hpc?>4XZO<5H2!VO!aKNki_JD@AZW0 z4%cX|SV@BH!3LjCykk-e&Se!#Pjmgk!y(*TD*9hr63Nf<*qe2FZ|Q}>Y#CyvcY`_R zxa6w4hE*CfV?m>!aKwElx~eZ2%t!PGEXaB!TCW)NQ^K<}qm~zXd#{Ai=TuMG$e}5G z(yAuTJu#(4rtpZXE%w4hy_Ql_b_HIO_mOfkw3=l?Q|4-!nT=BL z+aH$o#yu0#UmxwDEo8Jj8l>Lb3Vvj!B+F6JC5$YI1`E+j6t?ivdb?=ICazp^`XY&kD+abWD#kMJ~Fy*`P9OIRbJJY29p!-9$G%Q}BCB^{612 zhs=zj$G1D#4M2l9-ekK%#3bpo5`x2hW73Ms1=gd2hfXN?(t!sU;S z_e-5X;1zOT#pO{NtHrLsN$%FQ5KA|E*h-DkWzsvvy+KYM$$3quMM*8_%h?dH|V4^tlz3zjV8zWL{OZv4%{W4W9 zY^s{6;GF?BsWS^wrlecqgU^j^eASa(>uCQ<06Ne2q6Wa?ihH#k6`snAN)VG#(!*+s z5dgb$5Z@j6oL4xRv|4k-BBfB$QelMHdleHJ7-1P}$+Ien+#?=IdMe?Btl=T}U2c64 z@b9}TI_{zpK0&?Adv6B1{kL2L>JXd|5Tz%&VdCsq148sq%oCq@R`cyEyu0nEM z!vm2o8?X83%3!Xw5Yoi$y_V*w9<24eG^~02dq=g^n=)6r?ErK zRdSHvZsyxdi3@JZT~(i{h-*--YhbvkCkt5HvzE$zn1I_a1Y%|Z*dS?(wfDY(Qlldv{q(lNj}xD{9B59+ZRnO4bRLTIbZ1DoTf(SNdK*%`ge^f zqV;w?VaxMoe_qp)3PKW1;KerUL-)ye8Mb)z#~FI)<5o7w8zP^AjlcnG(o0&Fo%9HW zW?qE{;FK>9ZH?8ya&w#@^x=;{5PB=gn75dDu}c|s8+$0+)d|ONEhWP1*i5!Sj08Uy zqp^E__-ATDR`ex9W8}bBwllR?JzSF6Ww`ZLCT+~VExkWK##+sOFPQLSw~3*kmMSy@ zLg~y#?ZQ%s<`?e4)^u>0CCEbVvm5WTOB6Gj=&XlArPx2Zp4Lc$iSp#q^B(PLrIA{1 z(cvZjv|hG2tBT-tcyeIZY{y)Mmc-dBZwZds+Dp~MCqpFn~_*%kuo?6Zh zt6*Za82|RvGI~Qd@O`9Bfu3|iV&Hz6tW&JWe(}ng$a>>B>s5xEyNB9#z66vj#46h>w49Y5YU*#G-mk95`mck1I0|2%;{q%1dbNPY($}u0 z4o^a+JiP7Ysw9f~G;b$DUY7+H)YQuU(xh>o>NY&6QCK&$EK2*1n|m^{zqVWVnc8W` zvYLH$D$FE}KT&KHNcO#F9tYPeboTxSFqstgFS@ZL+4%k+Y|;k<`f+Ye(@ zRW9)Jc{RV|`TE#DRN?*pv>9kn^i|MT+R8K6>h!haMktYQ&K4*-OK$i5$Igmzr&~A2 zUAv)kfj{_&CG&6d*5B+z4b+*r%KP;`WhN%|b7kKBh+pi>T>KME4Kl23Kge^r5V)ak z!(|>GPUq=U*Av5APi)G0toJSN;-|!~h3yA7k6J7r zyztRIJ-2Cl#+lOJyZ|rZhv_MXba4dCD%pg4`5*sU2=nr1Q8t=8|GK>((Ox6SZ&;g? z_vtj1ArSsGtatlhD|c5-J9L7BB`LxUU zw7R9ZY%ybzNsu0+d>QgNDz zTg4Tm!%s{9X{qI3>?|{2A#HK{-Sa; zjj`SD1LgRNpx>LVV_#gqeH4`JQqHVX@gaJVDO30#O?cl2rk%@nA(+R-R{D&F(k=)S z=Bk` zZJb!J$!us&Yri$OcfzMgwuupCO;>N3O}IP1NufD7`SwdbF{ zgP(K{F775gU;8Kef4Ah@J_E*~(8M{UmxkqFj2iy|2j_f{5q2bX*mg6Z{ao>C`j)TR zl8nNf<%>4o-dpys@8YafKQlVBebCPnW87rC@tiv}O^&QHTWW=cw_p6#4FA;0wBS5@ z>4gi-*qJl*3?H8gao$)|_^6-Tg?j(v%$Q%PY+!xi^OySNN?I57;+uorKT~c`zdM}6 zp8lq~d^T{nOBTKF_vu3^!G`s%99wR!Cl#Om92yq!&^Msbnm&>7o) zp76*gp(C4v|I3X`*Kjt)?rl7y>#MfKMpa6yM}N!zxU8t}-g1PmI1#m9PTdd||E{;n z8)=50U<&-q6frs<{dvxAUiet7iI3#6YW~20gM3Gs!yg!XJj1W>*lm^i7s#SN#5QZ) zf{R-}{xE0P_WR4#K2sZA_U?z0neXAn*JmbxoJR!3i;n{lfF@T zTT9ozxK+p%KpWp2!p|q(2<4mtTj25EIqEu%^bB~t_QUjT&_-k{S3t^X*^f_=#1~zI z3SaUvq=h%`7zC;W+?AbUTX~%&*u4oGK5@R#_Hpm?(>8#Y1P*^Ud9XuvW`5aVY=9H@ z?TMTk$LmJkp`ML7-wVF7>vM)(l6yurZ-0RJyFWWj?IL1+I4Sl2G{1cRpq=Y}pCj3I zc+J;K~!e^4&_6}pOP)zK zI+-)z#09iG=HXd+J-vRxxQXj9=H%5G%jDhoG3n#&35LK6fl9{2xA&;qp@wg7erUEz z&A4x`;@vQRYQ0SCa;|-DI0mPK7;daL%lbVVJ>aWkpxcEK8~&ZB-Cx+NkA1P@>>qdU z2cmV$IEc<5tD0B#laiM=*?!~`;`S)p|Jo&+usN%wQ@|O+}f_h2y>G*bG`p8~BB32@a}6 zX2`W>L(A|R{QcVb$G-D=okv89AQ>!hfqJ3*!Oca(HMoZE2L058w!7)i-KI#B=W1}X zii5vTgCzJHu6nh+=KHGlv8HKB4`iuyvwtTq?jz+f36U~3U&5GgHY-CtQs(HVc4qSz zmx?Z_k40mbno0}kPjB`zp4{BS<%%5)<*aWUZ>rqnUc=OqptxkwpR%-py92b=KVOl> z2JEloE>#9m(cJu{T(Z9y{32`d;=fFUP{={@X>fdzXs7IS4b578Cec z2!VGbnQ6;$2+b15ZmAyIaLbE-<%lp&>T3*vsk~ow42Bp-jPV;OVPWN!Ys!si7tU6_G zo4ylQEgds1yTd9|^_RLhG;8w6)9dbq+(?a?ywZ7xRKOyfo6xY_RGx|Er5)1~v%)_b z)^|-Lr7IX=jFJ}h&ghbiA2K{L0;jV4=#hh_B8)E$RdMj6vYPMLe=hf;+pjq^aPt$l z?O_UhaKa6;0$sInM|?;=WB;czRW;sA=H?4T5v6R$O z7k;n@N;~r{%~$ixRghlR3|jJ9VpG03j-Cq@y*;;LLCNkswY=iNT(78>hYw72?N)#81Tw6a8-bo=`T@MsqGRSn;St*oz~SpcG_#_oiiuSd>e0u za()F9fSw?f*zQ~|KMQ$U&?SMnM<}UJ?^2qP)YLPVqGXMN#xo2*0u+%PX1WqJTKM(X zFYH%)2+K=UvP4b`6yjNq@c0fiI%NQ@gUR!N)nE67vl>)NaO3j#RHZ|1Kyqg8y}Q^_ zq(b7*Z`?F-xU&Vk;ePY9W)$s;CPU&;oT+ju+jGkGV<%`pyAq@V3%#?SmA+xCRu`%x0)yS(P3DOe`?hJv-z#S9c+cpd$&+-h4u}8>D zjc;v{+d=Y}+XLLbL^LY^H-H+eq>{Onp@WD|Ed!Uwh2tA+?GGK^ZlfvzI1hMcYJCpqH&XH4{O<%sU+qb<4@hNZf&(Yz|hKFzduboI(zabO#O>9 z!~D@ErPX73j1CwGDKffqibvoL-02&ZMs|1-qLY^K#r7P=Taa;7vhg@rnhLMXV!Ui0 zK^{+#yQKzz&@^CET|t2575^{wr4Pr|q4Qq55D=xJF2Tfku2r|KxlR8o+)3yWOa#c zf#&EO?tQzkukwJvr}_LExZY7rzYQe55LT7c;#`Z#*+i`^hh8cPZ9;fAa0AhkmVqtEW{0W z^%ZGa_Y$}YHGm{$($Zgazv$)sqw)sSC44!uH`p{KRN71|GmFN+Gw+u(Z>|M?lpbBU z*ChvhIEkXG{tMlVq78CK_20@Wks$zm9EM1;qgaIY@NxhWvavk;#{k_bo)k*?U~QPC z6-9W|gItW|>Wy{Ry5HO+cn~jFA$Fk*KkhNXTEWhHi1$j|(gI<7eK#KkTP3S1zLs9f zU>*oQ@L%1)g!`PSlFrHgJ{)%9!Z#uS5yz3oLqqV%`(J%v>fiiW28QCpP~9N!i z3W>(BSi<7R-X2@o7*H9U?m6t0hL4^~V677MNSS zuRNQggTNSoSnzv*p;vey1+~Ag7n#sF$f_nl-w*`$_nx*eks`3~-I)D&Kobz(v-f3=%Xg~2g zPcn?-7p6@V0e+8`pl`v2>f5LR4koCxaa<_AHNCf$83cG8 zqmd`QJl|=stjaTPE_I}lxQnh^{Y3A@)7GCQ`7Q7M~voQy4}b0Qe|(8=Lw$ zI0{4p5Fizze^+!vy;;Dp9M>`>?F`nQE@N6?In z3M>S7nkqiF9$&l`EKu$gfhrc`4u-kl*CsPyWUS(uk>BMr^U95{R9SptpF_69a3^1NFKu;KF zj|Gt)0d)9U@;%YCsAsxz_mc0C&e#o-1LJn6)Vf48sqes}$yQ^idGmzQ^ZxrjSeC5` zM{VlWkw{w@`7z-WcV-(G$qS1Ce1o{%@8&Ng&EhA<2^>k2} z=|p#TlIQls`z+tU47k=rzqNLe{}Kz$Qub{1oL6`3cRP-s7n{!hc7|1sCKE1Qav=<} zXDbw5-L!A3aCqyMygUL?QgrZvAow03>ZLD4JPyyEn3R8>B@g5R$escSvUniY7fF0( zkf^U0PR1>m_Z;4eB6H%CWP6i`TZO$(;BZ!fsXyJIkW4luL#Ak(Z@!S8aap(Ns$h}g z#J|WUs7*_n|J}eAIG@us?i^!GtLopV0UV?T(|0N-vwGF(`R`HI#DH&9&bbqaZ@2+uGz85FZv|GCt z?ursgSV_@;FxjN%lmQVr0*_P?Jj0z5V#VH$%LThw7!lgO6oT2)=KaIrk;&$Zj%+hT zjeMJ~Sx1WFJmLynP0a!DRB%4j{CmD~^#1Pk^7B|9wk_{Nac4VkRLSL3We`I4Ygb+S zrNsER%>9<4BC`;s@xF2gvgUIUri8MzGl4 zBoCRm%*WTBZ(jkhy!ZUrm+~@TI+LTXAaRhZ(H!dlPRDVtOy3d{5_ZzDal9~xceF-pbQ-WMijlZsy*Z$Rh|oc|17+f8T_E0~RtXP9W8fB#m1d6?S}yipYwHxGuhk z+qaH~SvB1w%mIuZg9L!h*V7OXMQF#5LrSFHAr<=VafJ->V^@rEkxBhN4#$R`55NKx zGEj?0gzcVVa;vUcYT;1A3%S!@UqUzMjtePqo@!m!dV~G&oHfoQ{yIrJjxHm;?+Yn* z`tWn)G4W(Zdx>3)jM)sOCtV4EXg+srf3Mze*v@(z&mG_x`;25SrDrz zYWzLGT#XXMd$=FxRv(uoFl#}(E&p6#Bbws6g^dOS^aChi{JmE1#dTU zzx%Te6UuFox~6%<_+?h!o+7tAg6ddgyX3NH8a$y{5;oGTea|8P%n6o+r5oWnu8rNNlvs`|5p+yrkSDvUC8h)U;t4L# z59?7kk4@_(^^ol04N%eB6A^u=dl_6O^+hbYWOje@!LXy5{O;Z-rn|dx!>b^Z%%9+D zjUDu$v=(`ld5Bf?_}}db8=%Ae?NZ~rXLNmsLW|t z01qP~{FBq#sa`w=&Wb>-2KwniwODV1%?zeu{45bP!(GvgV&uIqO6y?)@ZV04lNZ#dR20nM-|Z{a1JiC>))OT^gNnZ4-1MN+Y+1VO z#q0z~Ykb0AoTH_q*(C4=MD@YEItw3B#ffi5{#$s3btS`&L7QSeN9p9~c#5v?^T8)V zm%s05wT6@8)*Rx|+H9y4Fb9gfnI*O@dxw+g@C+K`eKI1eavmvMFq0f3207y znXJfUe`>!Gqin!j_+mP_4|`6)rWjN}!X`~ep!=`qW3Cfq8)tb( zH5L?M>Mt2Js2}tPhzo$kS^7T0hpw4X`m!KlQsT~^Rm*=Mspr{wm%;##wU8dl*AxPO z{#SA5{m=%PYvlp!g1FkvGnM4@bv0AHE^?zUU_f0wAmD3Bl3EPOUV&j~+eGoFHPu^dJ()YIQ(`qMfD9rOlu~k~k zO1rdg$a@I2y79J@5SZWnZC$Gm5*fIE4J<;O{m>B5R?4a3=1wgLT%jm4t37anGLuJ= zqRZJ-fAr(ExK}Wm9>Yh=bg+rok8cWJ&T3>+Q3?SxXpvpIGP9OR;*)@NiYcJ{TAKr} zE72*aXQLMOJ73R1P_f?}p+>-L?C2h$%+ODl4F&6^*{f}Ne#Lb;Ao}G-6rB5cQbaYI zR|h?IQ%@r))QJwKWS<(<^z_VcvPAI=VGCT6_H<8$_THZSPAj%vuNHz*mZZMw;Z|Qe;@G^_w%BNn zv6%p;Wr*^ce!A8Tj_WF+kBABC5I5l((%F;wnYLzr<>ps|uRoe*pU#@Bt+CmjghlGD zL|yFZ`$^vX=^`8bSI#IkouY>OmvVp@D;x95LF)ZUN5r2YTL#yUtfkY2WwNnN`WRAp%T5U!Q-mj zrrPMo*YQPw6?Kvhv(pgu*S!&k_uGSf(bAF9k(bwHNpn2q|71sdELp!`whpvzwH`D2 z{Ck*1Sr6OzDMZcg@l0N}_@F}*xm=2N7Mm&ar03#2?TOdn02)qANk;|Ne;Gv z&^T9|CN-=z<;_`h6>PyqM14l6}z|aGUlegY))d)U`bRbR}DjrxqWNb25jY zSemiaT%rnPDPe&^X8~3;2f0V5H3oG}L@@YzCMSmjk6e?LlB5Wap99^CrHy9_K&$lkMh`Fvw}HLILZv-m7*_j8aWChTHI52WHEmBarc$8usZQ7*fh1A zLChl6@ngQBvqk#r!TzHB37$H%nFK=Y4|UrX#wK65>yuB(%KWQP2r#z0+#4OP;o9_>JUG9gOhN(eG(PNF>^| zT;tt;F!+3-n;_iG=L*1mIPQ@q-Q{)tvhWZgZG~^BE(c&sTE-ZpGM2nCD#^w&spZEF z_E{eU4>rbrBx$3big?1~97_cGT+=Hhck>YofS{_ykCfEE)NlPPPbOS+CDEM4{Bd_k zDO3kvVknr%&wKGupoW4Sc&tKSKTeGWk0^~&1A6FD(gUsoPoH$`{_wn!KI~hP;4|yV zLwyyXI=Z%*duUH*d1bTiS?&&UyA@3Ab@!mNQrcjm=j=~DecflxKbevyx-BQa`X?c8 zR8hZ1nAc$vw04^X%9h?F&zA&MaZ8~>lS@A9Zwr3W-B$u#oIjFN;J9l^uF2P7B%;Cq7WZ}cBs7(4 zuho?5Ed^)bG4TeVzo)|!=xW=j4zbgYUU{{CWoUru)8B{A6jzT-)zLyTRO!O1d#&kx zkye#_5*$;Q_B?lUU@3G8$GM<(tu00E7b6kiGHd}vk)Z7^;h68161hP42|B7~UOa3TRbfh8~^ngzXFLh#t4}EnN8t zM(fV6U)yzyIj)JtH1muhSB4iPX9;raRN!39;`nD2-fP=w#z}gWpn4?K4Z0e8%ca80 zuP(d~RP_<>*+H2B^39Q$qu`#!Fh47IkxDvtH6?QK@pKw#5mScL`KE-4Leo3-?8YE= z06JO#upra8jexW)L)TWh#gNB%3pciWJT+8Aq6 zVuQ7i&A;_Ez8kBK2ljqTzF*D+84%aoHs*H_9c+x-f`>%*P#}ZCJgIUb#Nw`#9VN&N z&AG28*q`f|l$F#WhGAF8)c;&ttJ=LEG)Yf&i`f}qyUv15WXNPI>te!YN!@XJckU2E zS;PJtN8*m5qu@l=bR5X9a7ZnSgbTSlkSe~yxiVa81KAX|+X5tHQ(&3~>eoz3QzKoT`sT?&(L6RIG0IfYF zDxNud-Lql;)vu$zH4)d=fU>9~;bS$Q&+^-1%)hsWQ@po}g?9mX`wNX&1zaDXafd^}Ix)Zh{&FmiCuf-uZo`a$_|{jvnbGhNqZkE&igdKpCH#>Fbu zA^zr@-G$DXKCX}3Zvk7NfkXwVJ%_aUOds*hb}Xs$dpB=>id|wDl4M3)i#k4DnANF1 zcZ#gwEcpFU(vp9H{%rXZCULcSN?isD%YQdj^z3JlG6fZqRSQ2bn&F~^d8|3j*-9rv zp}Z*RMthR>&MVeS(0x6rDTrF8t2Lfs|7QPlpHqBkxvX(Zh1!WWStElv-|VkjimQt5 z6p0W)+II>?3;-sUjv~-JFSurYl*cUU*g~ewVIx_q*KV;20%YJlP;#itXdX1>j%yk| z6HPIsvnqs)?@A1J0;vka$pJ(@QO?^C%PxaB z0qSiyMLc_^3AMC`J|PxSodv3aqZ6)^F&E8?7=yur3I9B=yS-@n6ZBOttaPJo-uUYu zy>N(_vsX>J#N=mCDCnWihBLE&@gb&#zc1`yW%fAFnoB89!|!4~en^YKLAFRq^R(9| z=G9Cm`_ZO-Nk~S$(EjPCt)!?w__+bT;EZ`eV-kt(SE33vlaQuTZVk>yAjEqo_~l`xMW4Sgb0nV_}FNuL+{ zirLo0zBICx#6dZcR5Z|bSHR`(`jE}A+!@&QZaT=V=#w9Co3i=AS1{W1p`~jbg=#3k zh7+2w1HshCGn-Q^2H3H2Oiu4jXK?l#( z^@YXu1A`z;!ooD$?ry!vqyS{1QXXRdL(g1b`gJrd5`1d#5<>!)(5nwa%b^YS^kn2f zrm)nDbOlLnduZ%7hz2JRTp>;1z|kP6Id3>7IFM0ImWQmIgWm^mUz3IfRzeyxhcJ7kyT3n&-#+@wTD%JL;GFLVTv#M5<~v zx`*oAJf-PxP3|;B*vT^&1|Lt=L|6rLv1kBg12!oJdqabk9I^T{lo?{o(pYdMNY5JM zNgo%>zK>=mQnFO3#5j)~lWx!V2shF=ncb%AKfN4)V_HW-P&{Gl$ctoSEu#B7gLr{i zh$Iy^oVo!gg`{Lb8-<15m6l;OFo6hxV@lP<1uEk41%Gnp?hfzmK8uJI^e@;5>MeZ7 zX-~EXkT3yr{lmIdZ6x_AUqrH0fHcw|8|Mpk^?Bs!L!@mG;gZ_!Q z-`mO*gwLZ4o8Rzp=wxj;k~U?4)x%t+Cc!6LeX!JZ)30afEwQc#&GIv{mDinMutsLw zTzYUJQT!OYKNe**$7^dqwE?sMr zZ_3ehZ|xJy0oA zu8!rpre&6Fj!|^liW9(lAi4ug6sx;qotE*P`p7MwJx;07E%5o*c>q z-JR3?hXMpLl4cyxeyh8UG`ugBv1R_DR*Qv2{17|x6#~*w8RgB zM11q&5UVT8(##T@L`HL9F4xE1JL#W@$j@(^w{17kk+BkQz2Iixw-D z-qu-e<9q?O+t!QffRqUSyrm!xi7aI#xFPr}zCYuTI^Qg&hNZ!12^uHM3i0VXN1|VG zR%b3L2*7~GbCu64B3*#R89h+=cU*AjRJ9Kz4PptWG|m!DTuR#?kNY&CRn63mE8?H| z&!`h*72o%?#HES6c?b9mPbjZPUQMmMfy_{cY|v!}YlZ;L4BM~4j4^11_oyPg6oYqT15($F@HA?amUYRhAR#Y%5q(|@ zTI>MkMHk&NPTi~iOTp(qF0&u1BityfdWr)KL)|@sT{6XmCj~;&Fk(G|^8+0FfmabS zG0BnyK4t#MiD|n*XK7h;`N>UIMQU7Oss2Xo2mT}zr7sT|hFh&B?IL(UlG!7mt(OuL z!s!4+!{m28S)KMc-}R)WY1CUlu`YtNy>+#Dbefs;Q`t0b!T02&~gfjN?ziEw5Mfa9kRa(36QE;Hk zOMGQcva58Qo9!s4(gP6J1T{9W0($bY)C-++0Ne~EK`L)NDxl1m$Yel2O1HTf|CO?@ zdAxh*@JbMws)nJ@?Ps(-o~hcAg-st3U%M5OePRnBqT6BP0gVg*%{1H^D5BA0WK@9G zxbl%e<_B9EtYIK7V%l|G`(cn1%L4GE4F zW6%EM$JWcHDw9IE7iN048LdXkiRXKNs%d-o^&wlZI(&KJky6uz@JUa-%+&T1X%xvJ z%A>DtsI>6n{Xa{fpD{6%{5|83`a0SPn(JcZ~SFBhPL7tA2t4ncxpv4*K2 zs(8LT1Wwy9&n1BNlEp5CgsvuV=@tt|FR&m^hL3# zlV#BR=aPbNs+V<`qCHpW#*cYaseg>z;@n2P6*+w4nD(7v#wO+qUt2#c;`(~ipB=}~ zQTfr@X`kYvn$sVRmftj1zZ!KW_X~lK?rdDY*VuVCG&X{W0L;J3`>x1hUDX;c4=WAd z+n*dd{~7FEYh2lwZp^Rlz^6a|p}DIc_lh$@;8wh(7f*5dzU)&()3DBO(DiS3rX6>w z9qw7{e}qijt`huhlA{#kSI~U6SJ~_^UL<g4S9qB{dhW74kz`Kq!D39#)pQ3*mx;<{X#$bc99G95``D|@<_MCy~el>#(<#%0wz ze1!o9Hj%QH*Jomlhzw|2yJU)QY`R+8VmOLZIFkNEj0=1A^ZqZ`^jRHaBYuBd7TfNK zxYiMHKQl3$bDqzINjKHRZL`89c#$5KAMDSZ)(IYIP=My}`uk|hVtHjUUeztTVEb@| zmJfBPZv%#unPgAHX;l6ByHj1bKjKxuZ(D7P@XX10t$dU%iHGpp;ZcAbnK6K(O-XFd%zkWuCg;oC8_exf~t{e=$h54ztQ@` zI#o#0Oz#iTun}+?P}pty?5^3V_%HL_FD9ay06%wO8T;YhWY_mhB1RRR0;VYIGL?#^ zmL*rKOCpO0Yam{z6^SN59Q*X7mmIGEf5xH_)qN>xGV#Vh3jSw zn|6Gda9mQe(=VejFF&QQ7nT{n8Ic1Xge;CGyxxqkZPHO5%!NpHw9JCX3*b1}Fio=F zU3YE!5e8wV8N{5n4B|`qLUcsoAJ}X7oU3?>JS|uK(|Yx(N|EQQ3ggdkJ0Tz`gW@`% z9eqP!L6!1Ojt)b#Q&;KDup=tZGJp<^RB75a>C<}FH_!>HMpD6`L1Tb{FoZdi9r3#y zqdHMmc=rsI-u+Zm;H6}D@+d%HADg{Aq1GI&=XueqWR0M)%q!d}+U|;)gbG~ZoZlBF zwrcnPOC^YeV`p-FQJeGZbiQ^HIeBy=66O3g11fHG=&N~=-4Ygej@TJN#^Qod%g;6- z7!qtQ6b}o`xc_{D0@+%