Bug 1357005 - Create onboarding icon which toggles a first-time use dialog on net newtab. r=mossop
authorRex Lee <rexboy@mozilla.com>
Mon, 22 May 2017 17:00:16 +0800
changeset 409618 283ed0ad8bf47dff3bc1e62caedb37dd2a91c0a5
parent 409617 3c03b94342b95c9fdf8e7a2e36b1e30e051e8d5c
child 409619 169bd90857808c38bd675e612a6c2a35ffd6522a
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmossop
bugs1357005
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1357005 - Create onboarding icon which toggles a first-time use dialog on net newtab. r=mossop MozReview-Commit-ID: J4IAHyVKXAW
browser/app/permissions
browser/app/profile/firefox.js
browser/extensions/moz.build
browser/extensions/onboarding/bootstrap.js
browser/extensions/onboarding/content/img/overlay-icon.svg
browser/extensions/onboarding/content/onboarding.css
browser/extensions/onboarding/content/onboarding.js
browser/extensions/onboarding/install.rdf.in
browser/extensions/onboarding/jar.mn
browser/extensions/onboarding/moz.build
--- 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
@@ -1666,8 +1666,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']