Bug 1357005 - Create onboarding icon which toggles a first-time use dialog on net newtab.
MozReview-Commit-ID: J4IAHyVKXAW
--- a/browser/app/permissions
+++ b/browser/app/permissions
@@ -7,16 +7,17 @@
# See nsPermissionManager.cpp for more...
# UITour
origin uitour 1 https://www.mozilla.org
origin uitour 1 https://support.mozilla.org
origin uitour 1 https://addons.mozilla.org
origin uitour 1 https://discovery.addons.mozilla.org
origin uitour 1 about:home
+origin uitour 1 about:newtab
# XPInstall
origin install 1 https://addons.mozilla.org
origin install 1 https://testpilot.firefox.com
# Remote troubleshooting
origin remote-troubleshooting 1 https://input.mozilla.org
origin remote-troubleshooting 1 https://support.mozilla.org
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1658,8 +1658,11 @@ pref("browser.sessionstore.restore_tabs_
// Enable safebrowsing v4 tables (suffixed by "-proto") update.
#ifdef NIGHTLY_BUILD
pref("urlclassifier.malwareTable", "goog-malware-shavar,goog-unwanted-shavar,goog-malware-proto,goog-unwanted-proto,test-malware-simple,test-unwanted-simple");
pref("urlclassifier.phishTable", "goog-phish-shavar,goog-phish-proto,test-phish-simple");
#endif
pref("browser.suppress_first_window_animation", true);
+
+// Preferences for Photon onboarding system extension
+pref("browser.onboarding.disabled", false);
--- a/browser/extensions/moz.build
+++ b/browser/extensions/moz.build
@@ -28,9 +28,10 @@ if CONFIG['MOZ_MORTAR']:
DIRS += [
'mortar',
]
# Nightly-only system add-ons
if CONFIG['NIGHTLY_BUILD']:
DIRS += [
'activity-stream',
+ 'onboarding',
]
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/bootstrap.js
@@ -0,0 +1,18 @@
+/* -*- indent-tabs-mode: nil; js-indent-level: 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/. */
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+Cu.import("resource://gre/modules/Services.jsm");
+
+function install(aData, aReason) {}
+
+function uninstall(aData, aReason) {}
+
+function startup(aData, reason) {
+ Services.mm.loadFrameScript("resource://onboarding/onboarding.js", true);
+}
+
+function shutdown(aData, reason) {}
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/content/img/overlay-icon.svg
@@ -0,0 +1,2 @@
+
+<svg width="36" height="29" viewBox="0 0 36 29" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><title>overlayfox</title><defs><path id="a" d="M.002.058h35.953V27.94H.002z"/><path id="c" d="M0 17.39V.42h35.957v16.97H0z"/></defs><g fill="none" fill-rule="evenodd"><g transform="translate(0 .55)"><mask id="b" fill="#fff"><use xlink:href="#a"/></mask><path d="M35.953 16.593c.006-.19-.036-.386-.133-.562-1.02-1.884-2.052-3.65-3.17-5.243.773-.62 1.448-1.394 1.975-2.312 1.497-2.61 1.413-5.72.042-8.175-.063-.114-.176-.2-.294-.242.002.01-.006.016-.006.024-.008-.012-.018-.024-.03-.024-2.825-.03-5.558 1.46-7.112 4.09-.16.27-.3.572-.418.896-2.394-1.464-5.24-2.31-8.822-2.31-3.57 0-6.416.832-8.806 2.283v.007l-.02.014c-.12-.322-.257-.623-.416-.89C7.19 1.52 4.457.03 1.632.06c-.014 0-.028.014-.035.028 0-.007.007-.007.007-.014-.14.036-.267.12-.337.256-1.37 2.455-1.462 5.557.042 8.175.526.926 1.208 1.7 1.988 2.327-1.118 1.586-2.15 3.344-3.163 5.23-.092.166-.13.352-.13.533H.002c0 .007.002.013 0 .02v.016h.002c-.006.17.032.344.117.504 3.685 6.71 7.6 9.377 15 9.88.807.58 1.79.928 2.857.928 1.065 0 2.05-.347 2.857-.93 7.4-.5 11.323-3.168 15-9.878.09-.162.13-.35.12-.534v-.003-.004" fill="#F70" mask="url(#b)"/></g><g transform="translate(0 10.268)"><mask id="d" fill="#fff"><use xlink:href="#c"/></mask><path d="M17.978 17.39c9.31 0 13.732-2.447 17.857-9.975.09-.163.133-.356.12-.54h-4.238V5.23h-.014c.007-.113.014-.234.014-.348 0-2.462-1.975-4.46-4.407-4.46-2.43 0-4.406 1.998-4.406 4.46 0 .12.008.235.014.35h-9.88c.007-.1.014-.208.014-.314 0-2.462-1.974-4.462-4.406-4.462-2.43 0-4.406 2-4.406 4.462 0 .106.007.206.014.313h-.007v1.644H.002c-.013.185.03.37.12.54 4.132 7.53 8.545 9.976 17.856 9.976" fill="#FFC899" mask="url(#d)"/></g><path d="M35.954 17.15c.007-.192-.035-.39-.134-.57-1.018-1.885-2.05-3.65-3.17-5.243.774-.62 1.45-1.395 1.976-2.312 1.497-2.61 1.413-5.72.042-8.175-.063-.114-.175-.2-.295-.242.007.02.007.043-.014.057-.746.37-3.943 2.15-5.756 6.19-2.74-2.242-6.1-3.572-10.62-3.572-3.568 0-6.414.832-8.804 2.284v.007c-.632.384-1.23.81-1.8 1.28-1.474-3.28-3.85-5.065-5.1-5.82-.008 0-.008-.006-.015-.006C2.175.97 2.09.92 2.013.878c-.008 0-.015-.007-.015-.007C1.963.85 1.935.836 1.9.82c-.007 0-.007-.006-.014-.006-.035-.02-.064-.035-.098-.05-.008 0-.008-.006-.015-.006-.02-.015-.05-.03-.07-.036-.007 0-.014-.008-.02-.008C1.66.7 1.632.694 1.612.68 1.604.68 1.604.67 1.597.67L1.59.665V.65c0-.007 0-.007.008-.014 0-.007.007-.007.007-.014-.14.036-.267.12-.338.256-1.37 2.455-1.46 5.557.042 8.175.527.925 1.208 1.7 1.988 2.327-1.117 1.587-2.15 3.344-3.162 5.23-.098.177-.14.377-.133.57H4.24v-1.645h.007c-.007-.1-.014-.207-.014-.313 0-2.462 1.975-4.46 4.406-4.46 2.43 0 4.405 1.998 4.405 4.46 0 .106-.007.206-.014.313h.015v7.96c0 2.755 2.207 4.996 4.933 4.996 2.72 0 4.933-2.233 4.933-4.994v-7.99h.01c0-.042-.01-.085-.01-.128v-.47c.128-2.347 2.047-4.21 4.4-4.21 2.432 0 4.407 1.998 4.407 4.46 0 .12-.007.235-.015.348h.015v1.644h4.237z" fill="#F70"/><path d="M16.453 19.832s.05 0 .134.008c.084.006.204.014.345.014.14.007.31.007.49.014.177 0 .374.007.563.007.19 0 .38 0 .563-.007.175 0 .344-.007.492-.014.14-.008.26-.014.344-.014.084-.008.133-.008.133-.008.598-.057 1.132.39 1.18.996.03.3-.07.584-.245.804l-.942 1.146-.035.035c-.02.022-.056.058-.098.093-.043.036-.092.078-.148.114-.057.043-.127.078-.197.12-.07.036-.148.072-.233.107-.084.03-.168.057-.26.08-.175.042-.372.056-.56.048-.1-.006-.19-.014-.29-.028-.05-.007-.09-.014-.14-.02-.05-.008-.092-.023-.134-.03-.042-.007-.09-.028-.133-.035-.042-.015-.084-.03-.127-.043-.042-.015-.084-.03-.12-.05-.034-.015-.077-.036-.112-.05-.035-.022-.07-.036-.105-.057-.036-.022-.064-.036-.092-.058-.057-.035-.106-.07-.148-.106-.042-.03-.077-.065-.098-.08l-.036-.035-.906-.946c-.45-.47-.436-1.21.02-1.666.254-.25.577-.356.893-.342" fill="#994C00"/><path d="M8.407 19.398c-.618 0-1.243-.135-1.82-.412-.28-.136-.4-.477-.267-.762.134-.284.47-.405.752-.27.87.42 1.884.406 2.77-.043.28-.14.617-.027.75.258.14.284.03.625-.252.76-.612.314-1.272.47-1.933.47M26.938 19.398c-.618 0-1.244-.135-1.82-.412-.28-.136-.4-.477-.267-.762.135-.284.472-.405.753-.27.87.42 1.883.406 2.77-.043.28-.14.617-.027.75.258.134.284.03.625-.252.76-.61.314-1.27.47-1.932.47" fill="#F70"/><path d="M10.91 15.926c-.008-.064-.03-.12-.057-.178-.45-1.024-1.363-1.657-2.39-1.657-1.025 0-1.94.634-2.39 1.658-.027.057-.04.12-.055.178-.14.3-.077.67.183.904.31.277.788.25 1.07-.064.3-.342.736-.54 1.194-.54.456 0 .9.198 1.194.54.148.17.358.256.57.256.175 0 .358-.064.498-.192.26-.235.323-.605.183-.904M29.44 15.926c-.007-.064-.028-.12-.057-.178-.45-1.024-1.363-1.657-2.39-1.657-1.024 0-1.938.634-2.388 1.658-.028.057-.042.12-.056.178-.142.3-.078.67.182.904.14.128.323.192.5.192.21 0 .413-.086.568-.256.302-.342.737-.54 1.194-.54.457 0 .9.198 1.195.54.273.313.75.348 1.067.064.26-.235.323-.605.183-.904" fill="#363959"/><path d="M17.978 27.438c-1.405 0-2.122-.718-2.473-1.323-.373-.648-.415-1.288-.415-1.31-.007-.092.042-.184.12-.234.077-.05.175-.056.26-.014.007.008.934.456 2.48.456 1.553 0 2.53-.456 2.544-.456.085-.042.183-.028.26.022.078.05.12.142.112.235 0 .028-.042.67-.414 1.31-.352.597-1.068 1.315-2.474 1.315" fill="#994C00"/><path d="M28.597 6.855c1.468-3.28 3.843-5.066 5.094-5.82.008 0 .008-.007.016-.007.09-.057.175-.107.252-.15.007 0 .015-.007.015-.007.034-.02.063-.034.098-.05.008 0 .008-.006.015-.006.035-.02.063-.035.098-.05.007 0 .007-.007.015-.007.02-.014.05-.028.07-.035.006 0 .014-.008.02-.008.022-.014.05-.02.07-.035.008 0 .008-.008.015-.008l.007-.008V.65c0-.007 0-.007-.007-.013-.007-.015-.02-.03-.035-.03C31.513.58 28.78 2.068 27.226 4.7c-.16.27-.302.575-.42.902.617.356 1.215.783 1.79 1.253M7.374 6.855C5.906 3.575 3.53 1.79 2.28 1.035c-.008 0-.008-.007-.015-.007C2.175.97 2.09.92 2.013.878c-.008 0-.015-.007-.015-.007C1.963.85 1.935.837 1.9.82c-.007 0-.007-.006-.014-.006-.035-.02-.064-.035-.098-.05-.008 0-.008-.007-.015-.007-.02-.014-.05-.028-.07-.035-.007 0-.014-.008-.02-.008C1.66.7 1.632.694 1.612.68 1.604.68 1.604.67 1.597.67L1.59.664V.65c0-.007 0-.007.008-.013.007-.015.02-.03.035-.03C4.458.58 7.19 2.068 8.745 4.7c.16.27.302.575.42.902-.624.356-1.22.783-1.79 1.253" fill="#FF9F4D"/></g></svg>
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/content/onboarding.css
@@ -0,0 +1,88 @@
+/* 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/. */
+#onboarding-overlay * {
+ box-sizing: border-box;
+}
+
+#onboarding-overlay {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ /* Ensuring we can put the overlay over elements using
+ z-index on original page */
+ z-index: 999;
+ color: #4d4d4d;
+ background: rgb(54, 57, 89, 0.8); /* #363959, 0.8 opacity */
+ display: none;
+}
+
+#onboarding-overlay.opened {
+ display: block;
+}
+
+#onboarding-overlay-icon {
+ width: 52px;
+ height: 40px;
+ position: absolute;
+ cursor: pointer;
+ top: 30px;
+ offset-inline-start: 30px;
+ background: url("img/overlay-icon.svg") no-repeat;
+}
+
+#onboarding-overlay-dialog {
+ display: none;
+}
+
+#onboarding-tour-close-btn {
+ position: absolute;
+ top: 15px;
+ offset-inline-end: 15px;
+}
+
+#onboarding-overlay.opened > #onboarding-overlay-dialog {
+ width: 1200px;
+ height: 550px;
+ background: #f5f5f7;
+ border: 1px solid rgba(9, 6, 13, 0.1); /* #09060D, 0.1 opacity */
+ position: relative;
+ margin: 0 calc(50% - 600px);
+ top: calc(50% - 275px);
+ display: grid;
+ grid-template-rows: [dialog-start] 76px [page-start] 1fr [footer-start] 40px [dialog-end];
+ grid-template-columns: [dialog-start] 240px [page-start] 1fr [dialog-end];
+}
+
+@media (max-height: 550px) {
+ #onboarding-overlay.opened > #onboarding-overlay-dialog {
+ top: 0;
+ }
+}
+
+#onboarding-overlay-dialog > header {
+ grid-row: dialog-start / page-start;
+ grid-column: dialog-start / tour-end;
+ margin-top: 36px;
+ margin-bottom: 0;
+ margin-inline-end: 0;
+ margin-inline-start: 36px;
+ font-size: 22px;
+}
+
+#onboarding-overlay-dialog > nav {
+ grid-row: dialog-start / footer-start;
+ grid-column-start: dialog-start;
+ margin-top: 40px;
+ margin-bottom: 0;
+ margin-inline-end: 0;
+ margin-inline-start: 0;
+ padding: 0;
+}
+
+#onboarding-overlay-dialog > footer {
+ grid-row: footer-start;
+ grid-column: dialog-start / tour-end;
+}
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/content/onboarding.js
@@ -0,0 +1,113 @@
+/* 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/. */
+
+/* global content */
+
+"use strict";
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+Cu.import("resource://gre/modules/Services.jsm");
+
+const ONBOARDING_CSS_URL = "resource://onboarding/onboarding.css";
+const ABOUT_NEWTAB_URL = "about:newtab";
+
+/**
+ * The script won't be initialized if we turned off onboarding by
+ * setting "browser.onboarding.disabled" to true.
+ */
+class Onboarding {
+ constructor(contentWindow) {
+ this.init(contentWindow);
+ }
+
+ async init(contentWindow) {
+ this._window = contentWindow;
+ // 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._overlayIcon = this._renderOverlayIcon();
+ this._overlay = this._renderOverlay();
+ this._window.document.body.appendChild(this._overlayIcon);
+ this._window.document.body.appendChild(this._overlay);
+
+ this._overlayIcon.addEventListener("click", this);
+ this._overlay.addEventListener("click", this);
+ // Destroy on unload. This is to ensure we remove all the stuff we left.
+ // No any leak out there.
+ this._window.addEventListener("unload", () => this.destroy());
+ }
+
+ handleEvent(evt) {
+ switch (evt.target.id) {
+ case "onboarding-overlay-icon":
+ case "onboarding-tour-close-btn":
+ // If the clicking target is directly on the outer-most overlay,
+ // that means clicking outside the tour content area.
+ // Let's toggle the overlay.
+ case "onboarding-overlay":
+ this.toggleOverlay();
+ break;
+ }
+ }
+
+ destroy() {
+ this._overlayIcon.remove();
+ this._overlay.remove();
+ }
+
+ toggleOverlay() {
+ this._overlay.classList.toggle("opened");
+ }
+
+ _renderOverlay() {
+ let div = this._window.document.createElement("div");
+ div.id = "onboarding-overlay";
+ // Here we use `innerHTML` is for more friendly reading.
+ // The security should be fine because this is not from an external input.
+ // We're not shipping yet so l10n strings is going to be closed for now.
+ div.innerHTML = `
+ <div id="onboarding-overlay-dialog">
+ <button id="onboarding-tour-close-btn">X</button>
+ <header>Getting started?</header>
+ <nav>
+ <ul></ul>
+ </nav>
+ <footer>
+ </footer>
+ </div>
+ `;
+ return div;
+ }
+
+ _renderOverlayIcon() {
+ let img = this._window.document.createElement("div");
+ img.id = "onboarding-overlay-icon";
+ return img;
+ }
+
+ _loadCSS() {
+ // Returning a Promise so we can inform caller of loading complete
+ // by resolving it.
+ return new Promise(resolve => {
+ let doc = this._window.document;
+ let link = doc.createElement("link");
+ link.rel = "stylesheet";
+ link.type = "text/css";
+ link.href = ONBOARDING_CSS_URL;
+ link.addEventListener("load", resolve);
+ doc.head.appendChild(link);
+ });
+ }
+}
+
+addEventListener("load", function(evt) {
+ // Load onboarding module only when we enable it.
+ if (content.location.href == ABOUT_NEWTAB_URL &&
+ !Services.prefs.getBoolPref("browser.onboarding.disabled")) {
+
+ content.requestIdleCallback(() => {
+ new Onboarding(content);
+ });
+ }
+}, true);
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/install.rdf.in
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- 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/. -->
+
+#filter substitution
+
+<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:em="http://www.mozilla.org/2004/em-rdf#">
+ <Description about="urn:mozilla:install-manifest">
+ <em:id>onboarding@mozilla.org</em:id>
+ <em:name>Photon onboarding</em:name>
+ <em:description>Photon onboarding</em:description>
+ <em:version>0.1</em:version>
+ <em:bootstrap>true</em:bootstrap>
+ <em:type>2</em:type>
+ <em:multiprocessCompatible>true</em:multiprocessCompatible>
+
+ <em:targetApplication>
+ <Description>
+ <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!--Firefox-->
+ <em:minVersion>@MOZ_APP_VERSION@</em:minVersion>
+ <em:maxVersion>@MOZ_APP_MAXVERSION@</em:maxVersion>
+ </Description>
+ </em:targetApplication>
+ <em:strictCompatibility>false</em:strictCompatibility>
+ </Description>
+</RDF>
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/jar.mn
@@ -0,0 +1,7 @@
+# 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/.
+
+[features/onboarding@mozilla.org] chrome.jar:
+% resource onboarding %content/
+ content/ (content/*)
new file mode 100644
--- /dev/null
+++ b/browser/extensions/onboarding/moz.build
@@ -0,0 +1,18 @@
+# -*- 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/.
+
+DEFINES['MOZ_APP_VERSION'] = CONFIG['MOZ_APP_VERSION']
+DEFINES['MOZ_APP_MAXVERSION'] = CONFIG['MOZ_APP_MAXVERSION']
+
+FINAL_TARGET_PP_FILES.features['onboarding@mozilla.org'] += [
+ 'install.rdf.in'
+]
+
+FINAL_TARGET_FILES.features['onboarding@mozilla.org'] += [
+ 'bootstrap.js',
+]
+
+JAR_MANIFESTS += ['jar.mn']