Bug 1482836 Remove deprecated Snippets code r=jchen
authorAndrei Lazar <andrei.a.lazar@softvision.ro>
Thu, 16 Aug 2018 19:59:15 +0000
changeset 491049 917e36757da91e807aa0034fa2fe280eec5e32fd
parent 491048 5c420838bf5229f08145ac9a8c0f4b06cfbc2925
child 491050 624a0fcb6618d573f54dc9b38b95e2cb5ff4df6a
push id1815
push userffxbld-merge
push dateMon, 15 Oct 2018 10:40:45 +0000
treeherdermozilla-release@18d4c09e9378 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjchen
bugs1482836
milestone63.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 1482836 Remove deprecated Snippets code r=jchen Removed unused Snippets code since now we're using Leanplum. Differential Revision: https://phabricator.services.mozilla.com/D3521
.eslintignore
mobile/android/components/MobileComponents.manifest
mobile/android/components/Snippets.js
mobile/android/components/moz.build
mobile/android/installer/package-manifest.in
--- a/.eslintignore
+++ b/.eslintignore
@@ -308,17 +308,16 @@ mobile/android/app/geckoview-prefs.js
 mobile/android/chrome/content/about.js
 
 # Not much JS to lint and non-standard at that
 mobile/android/installer/
 mobile/android/locales/
 
 # Non-standard `(catch ex if ...)`
 mobile/android/chrome/content/browser.js
-mobile/android/components/Snippets.js
 
 # Only contains non-standard test files.
 python/**
 
 # security/ exclusions (pref files).
 security/manager/ssl/security-prefs.js
 
 # NSS / taskcluster only.
--- a/mobile/android/components/MobileComponents.manifest
+++ b/mobile/android/components/MobileComponents.manifest
@@ -98,22 +98,16 @@ contract @mozilla.org/fxa-push;1 {d1bbb0
 category android-push-service FxAccountsPush @mozilla.org/fxa-push;1
 
 #ifndef RELEASE_OR_BETA
 # TabSource.js
 component {5850c76e-b916-4218-b99a-31f004e0a7e7} TabSource.js
 contract @mozilla.org/tab-source-service;1 {5850c76e-b916-4218-b99a-31f004e0a7e7}
 #endif
 
-# Snippets.js
-component {a78d7e59-b558-4321-a3d6-dffe2f1e76dd} Snippets.js
-contract @mozilla.org/snippets;1 {a78d7e59-b558-4321-a3d6-dffe2f1e76dd}
-category browser-delayed-startup-finished Snippets @mozilla.org/snippets;1
-category update-timer Snippets @mozilla.org/snippets;1,getService,snippets-update-timer,browser.snippets.updateInterval,86400
-
 # ColorPicker.js
 component {430b987f-bb9f-46a3-99a5-241749220b29} ColorPicker.js
 contract @mozilla.org/colorpicker;1 {430b987f-bb9f-46a3-99a5-241749220b29}
 
 # PersistentNotificationHandler.js
 component {75390fe7-f8a3-423a-b3b1-258d7eabed40} PersistentNotificationHandler.js
 contract @mozilla.org/persistent-notification-handler;1 {75390fe7-f8a3-423a-b3b1-258d7eabed40}
 category persistent-notification-click PersistentNotificationHandler @mozilla.org/persistent-notification-handler;1
deleted file mode 100644
--- a/mobile/android/components/Snippets.js
+++ /dev/null
@@ -1,449 +0,0 @@
-/* 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/. */
-
-ChromeUtils.import("resource://gre/modules/Accounts.jsm");
-ChromeUtils.import("resource://gre/modules/Services.jsm");
-ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-XPCOMUtils.defineLazyGlobalGetters(this, ["XMLHttpRequest"]);
-
-ChromeUtils.defineModuleGetter(this, "Home", "resource://gre/modules/Home.jsm");
-ChromeUtils.defineModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
-ChromeUtils.defineModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
-ChromeUtils.defineModuleGetter(this, "UITelemetry", "resource://gre/modules/UITelemetry.jsm");
-
-
-XPCOMUtils.defineLazyGetter(this, "gEncoder", function() { return new gChromeWin.TextEncoder(); });
-XPCOMUtils.defineLazyGetter(this, "gDecoder", function() { return new gChromeWin.TextDecoder(); });
-
-// URL to fetch snippets, in the urlFormatter service format.
-const SNIPPETS_UPDATE_URL_PREF = "browser.snippets.updateUrl";
-
-// URL to send stats data to metrics.
-const SNIPPETS_STATS_URL_PREF = "browser.snippets.statsUrl";
-
-// URL to fetch country code, a value that's cached and refreshed once per month.
-const SNIPPETS_GEO_URL_PREF = "browser.snippets.geoUrl";
-
-// Timestamp when we last updated the user's country code.
-const SNIPPETS_GEO_LAST_UPDATE_PREF = "browser.snippets.geoLastUpdate";
-
-// Pref where we'll cache the user's country.
-const SNIPPETS_COUNTRY_CODE_PREF = "browser.snippets.countryCode";
-
-// Pref where we store an array IDs of snippets that should not be shown again
-const SNIPPETS_REMOVED_IDS_PREF = "browser.snippets.removedIds";
-
-// How frequently we update the user's country code from the server (30 days).
-const SNIPPETS_GEO_UPDATE_INTERVAL_MS = 86400000*30;
-
-// Should be bumped up if the snippets content format changes.
-const SNIPPETS_VERSION = 1;
-
-XPCOMUtils.defineLazyGetter(this, "gSnippetsURL", function() {
-  let updateURL = Services.prefs.getCharPref(SNIPPETS_UPDATE_URL_PREF).replace("%SNIPPETS_VERSION%", SNIPPETS_VERSION);
-  return Services.urlFormatter.formatURL(updateURL);
-});
-
-// Where we cache snippets data
-XPCOMUtils.defineLazyGetter(this, "gSnippetsPath", function() {
-  return OS.Path.join(OS.Constants.Path.profileDir, "snippets.json");
-});
-
-XPCOMUtils.defineLazyGetter(this, "gStatsURL", function() {
-  return Services.prefs.getCharPref(SNIPPETS_STATS_URL_PREF);
-});
-
-// Where we store stats about which snippets have been shown
-XPCOMUtils.defineLazyGetter(this, "gStatsPath", function() {
-  return OS.Path.join(OS.Constants.Path.profileDir, "snippets-stats.txt");
-});
-
-XPCOMUtils.defineLazyGetter(this, "gGeoURL", function() {
-  return Services.prefs.getCharPref(SNIPPETS_GEO_URL_PREF);
-});
-
-XPCOMUtils.defineLazyGetter(this, "gCountryCode", function() {
-  try {
-    return Services.prefs.getCharPref(SNIPPETS_COUNTRY_CODE_PREF);
-  } catch (e) {
-    // Return an empty string if the country code pref isn't set yet.
-    return "";
-  }
-});
-
-XPCOMUtils.defineLazyGetter(this, "gChromeWin", function() {
-  return Services.wm.getMostRecentWindow("navigator:browser");
-});
-
-/**
- * Updates snippet data and country code (if necessary).
- */
-function update() {
-  // Check to see if we should update the user's country code from the geo server.
-  let lastUpdate = 0;
-  try {
-    lastUpdate = parseFloat(Services.prefs.getCharPref(SNIPPETS_GEO_LAST_UPDATE_PREF));
-  } catch (e) {}
-
-  if (Date.now() - lastUpdate > SNIPPETS_GEO_UPDATE_INTERVAL_MS) {
-    // We should update the snippets after updating the country code,
-    // so that we can filter snippets to add to the banner.
-    updateCountryCode(updateSnippets);
-  } else {
-    updateSnippets();
-  }
-}
-
-/**
- * Fetches the user's country code from the geo server and stores the value in a pref.
- *
- * @param callback function called once country code is updated
- */
-function updateCountryCode(callback) {
-  _httpGetRequest(gGeoURL, function(responseText) {
-    // Store the country code in a pref.
-    let data = JSON.parse(responseText);
-    Services.prefs.setCharPref(SNIPPETS_COUNTRY_CODE_PREF, data.country_code);
-
-    // Set last update time.
-    Services.prefs.setCharPref(SNIPPETS_GEO_LAST_UPDATE_PREF, Date.now());
-
-    callback();
-  });
-}
-
-/**
- * Loads snippets from snippets server, caches the response, and
- * updates the home banner with the new set of snippets.
- */
-function updateSnippets() {
-  _httpGetRequest(gSnippetsURL, function(responseText) {
-    try {
-      let messages = JSON.parse(responseText);
-      updateBanner(messages);
-
-      // Only cache the response if it is valid JSON.
-      cacheSnippets(responseText);
-    } catch (e) {
-      Cu.reportError("Error parsing snippets responseText: " + e);
-    }
-  });
-}
-
-/**
- * Caches snippets server response text to `snippets.json` in profile directory.
- *
- * @param response responseText returned from snippets server
- */
-function cacheSnippets(response) {
-  let data = gEncoder.encode(response);
-  let promise = OS.File.writeAtomic(gSnippetsPath, data, { tmpPath: gSnippetsPath + ".tmp" });
-  promise.catch(e => Cu.reportError("Error caching snippets: " + e));
-}
-
-/**
- * Loads snippets from cached `snippets.json`.
- */
-function loadSnippetsFromCache() {
-  let promise = OS.File.read(gSnippetsPath);
-  promise.then(array => {
-    let messages = JSON.parse(gDecoder.decode(array));
-    updateBanner(messages);
-  }, e => {
-    if (e instanceof OS.File.Error && e.becauseNoSuchFile) {
-      Services.console.logStringMessage("Couldn't show snippets because cache does not exist yet.");
-    } else {
-      Cu.reportError("Error loading snippets from cache: " + e);
-    }
-  });
-}
-
-// Array of the message ids added to the home banner, used to remove
-// older set of snippets when new ones are available.
-var gMessageIds = [];
-
-/**
- * Updates set of snippets in the home banner message rotation.
- *
- * @param messages JSON array of message data JSON objects.
- *   Each message object should have the following properties:
- *     - id (?): Unique identifier for this snippets message
- *     - text (string): Text to show as banner message
- *     - url (string): URL to open when banner is clicked
- *     - icon (data URI): Icon to appear in banner
- *     - countries (list of strings): Country codes for where this message should be shown (e.g. ["US", "GR"])
- */
-function updateBanner(messages) {
-  // Remove the current messages, if there are any.
-  gMessageIds.forEach(function(id) {
-    Home.banner.remove(id);
-  })
-  gMessageIds = [];
-
-  try {
-    let removedSnippetIds = JSON.parse(Services.prefs.getCharPref(SNIPPETS_REMOVED_IDS_PREF));
-    messages = messages.filter(function(message) {
-      // Only include the snippet if it has not been previously removed.
-      return !removedSnippetIds.includes(message.id);
-    });
-  } catch (e) {
-    // If the pref doesn't exist, there aren't any snippets to filter out.
-  }
-
-  messages.forEach(function(message) {
-    // Don't add this message to the banner if it's not supposed to be shown in this country.
-    if ("countries" in message && !message.countries.includes(gCountryCode)) {
-      return;
-    }
-
-    let id = Home.banner.add({
-      text: message.text,
-      icon: message.icon,
-      weight: message.weight,
-      onclick: function() {
-        gChromeWin.BrowserApp.loadURI(message.url);
-        removeSnippet(id, message.id);
-        UITelemetry.addEvent("action.1", "banner", null, message.id);
-      },
-      ondismiss: function() {
-        removeSnippet(id, message.id);
-        UITelemetry.addEvent("cancel.1", "banner", null, message.id);
-      },
-      onshown: function() {
-        // 10% of the time, record the snippet id and a timestamp
-        if (Math.random() < .1) {
-          writeStat(message.id, new Date().toISOString());
-        }
-      }
-    });
-    // Keep track of the message we added so that we can remove it later.
-    gMessageIds.push(id);
-  });
-}
-
-/**
- * Removes a snippet message from the home banner rotation, and stores its
- * snippet id in a pref so we'll never show it again.
- *
- * @param messageId unique id for home banner message, returned from Home.banner API
- * @param snippetId unique id for snippet, sent from snippets server
- */
-function removeSnippet(messageId, snippetId) {
-  // Remove the message from the home banner rotation.
-  Home.banner.remove(messageId);
-
-  // Remove the message from the stored message ids.
-  gMessageIds.splice(gMessageIds.indexOf(messageId), 1);
-
-  let removedSnippetIds;
-  try {
-    removedSnippetIds = JSON.parse(Services.prefs.getCharPref(SNIPPETS_REMOVED_IDS_PREF));
-  } catch (e) {
-    removedSnippetIds = [];
-  }
-
-  removedSnippetIds.push(snippetId);
-  Services.prefs.setCharPref(SNIPPETS_REMOVED_IDS_PREF, JSON.stringify(removedSnippetIds));
-}
-
-/**
- * Appends snippet id and timestamp to the end of `snippets-stats.txt`.
- *
- * @param snippetId unique id for snippet, sent from snippets server
- * @param timestamp in ISO8601
- */
-function writeStat(snippetId, timestamp) {
-  let data = gEncoder.encode(snippetId + "," + timestamp + ";");
-
-  Task.spawn(function*() {
-    try {
-      let file = yield OS.File.open(gStatsPath, { append: true, write: true });
-      try {
-        yield file.write(data);
-      } finally {
-        yield file.close();
-      }
-    } catch (ex) {
-      if (!(ex instanceof OS.File.Error && ex.becauseNoSuchFile)) {
-        throw ex;
-      }
-      // If the file doesn't exist yet, create it.
-      yield OS.File.writeAtomic(gStatsPath, data, { tmpPath: gStatsPath + ".tmp" });
-    }
-  }).catch(e => Cu.reportError("Error writing snippets stats: " + e));
-}
-
-/**
- * Reads snippets stats data from `snippets-stats.txt` and sends the data to metrics.
- */
-function sendStats() {
-  let promise = OS.File.read(gStatsPath);
-  promise.then(array => sendStatsRequest(gDecoder.decode(array)), e => {
-    if (e instanceof OS.File.Error && e.becauseNoSuchFile) {
-      // If the file doesn't exist, there aren't any stats to send.
-    } else {
-      Cu.reportError("Error eading snippets stats: " + e);
-    }
-  });
-}
-
-/**
- * Sends stats to metrics about which snippets have been shown.
- * Appends snippet ids and timestamps as parameters to a GET request.
- * e.g. https://snippets-stats.mozilla.org/mobile?s1=3825&t1=2013-11-17T18:27Z&s2=6326&t2=2013-11-18T18:27Z
- *
- * @param data contents of stats data file
- */
-function sendStatsRequest(data) {
-  let params = [];
-  let stats = data.split(";");
-
-  // The last item in the array will be an empty string, so stop before then.
-  for (let i = 0; i < stats.length - 1; i++) {
-    let stat = stats[i].split(",");
-    params.push("s" + i + "=" + encodeURIComponent(stat[0]));
-    params.push("t" + i + "=" + encodeURIComponent(stat[1]));
-  }
-
-  let url = gStatsURL + "?" + params.join("&");
-
-  // Remove the file after succesfully sending the data.
-  _httpGetRequest(url, removeStats);
-}
-
-/**
- * Removes text file where we store snippets stats.
- */
-function removeStats() {
-  let promise = OS.File.remove(gStatsPath);
-  promise.catch(e => Cu.reportError("Error removing snippets stats: " + e));
-}
-
-/**
- * Helper function to make HTTP GET requests.
- *
- * @param url where we send the request
- * @param callback function that is called with the xhr responseText
- */
-function _httpGetRequest(url, callback) {
-  let xhr = new XMLHttpRequest();
-  try {
-    xhr.open("GET", url, true);
-  } catch (e) {
-    Cu.reportError("Error opening request to " + url + ": " + e);
-    return;
-  }
-  xhr.onerror = function onerror(e) {
-    Cu.reportError("Error making request to " + url + ": " + e.error);
-  }
-  xhr.onload = function onload(event) {
-    if (xhr.status !== 200) {
-      Cu.reportError("Request to " + url + " returned status " + xhr.status);
-      return;
-    }
-    if (callback) {
-      callback(xhr.responseText);
-    }
-  }
-  xhr.send(null);
-}
-
-function loadSyncPromoBanner() {
-  Accounts.anySyncAccountsExist().then(
-    (exist) => {
-      // Don't show the banner if sync accounts exist.
-      if (exist) {
-        return;
-      }
-
-      let stringBundle = Services.strings.createBundle("chrome://browser/locale/sync.properties");
-      let text = stringBundle.GetStringFromName("promoBanner.message.text");
-      let link = stringBundle.GetStringFromName("promoBanner.message.link");
-
-      let id = Home.banner.add({
-        text: text + "<a href=\"#\">" + link + "</a>",
-        icon: "drawable://sync_promo",
-        onclick: function() {
-          // Remove the message, so that it won't show again for the rest of the app lifetime.
-          Home.banner.remove(id);
-          Accounts.launchSetup();
-
-          UITelemetry.addEvent("action.1", "banner", null, "syncpromo");
-        },
-        ondismiss: function() {
-          // Remove the sync promo message from the banner and never try to show it again.
-          Home.banner.remove(id);
-          Services.prefs.setBoolPref("browser.snippets.syncPromo.enabled", false);
-
-          UITelemetry.addEvent("cancel.1", "banner", null, "syncpromo");
-        }
-      });
-    },
-    (err) => {
-      Cu.reportError("Error checking whether sync account exists: " + err);
-    }
-  );
-}
-
-function loadHomePanelsBanner() {
-  let stringBundle = Services.strings.createBundle("chrome://browser/locale/aboutHome.properties");
-  let text = stringBundle.GetStringFromName("banner.firstrunHomepage.text");
-
-  let id = Home.banner.add({
-    text: text,
-    icon: "drawable://homepage_banner_firstrun",
-    onclick: function() {
-      // Remove the message, so that it won't show again for the rest of the app lifetime.
-      Home.banner.remove(id);
-      // User has interacted with this snippet so don't show it again.
-      Services.prefs.setBoolPref("browser.snippets.firstrunHomepage.enabled", false);
-
-      UITelemetry.addEvent("action.1", "banner", null, "firstrun-homepage");
-    },
-    ondismiss: function() {
-      Home.banner.remove(id);
-      Services.prefs.setBoolPref("browser.snippets.firstrunHomepage.enabled", false);
-
-      UITelemetry.addEvent("cancel.1", "banner", null, "firstrun-homepage");
-    }
-  });
-}
-
-function Snippets() {}
-
-Snippets.prototype = {
-  QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver, Ci.nsITimerCallback]),
-  classID: Components.ID("{a78d7e59-b558-4321-a3d6-dffe2f1e76dd}"),
-
-  observe: function(subject, topic, data) {
-    switch(topic) {
-      case "browser-delayed-startup-finished":
-        // Add snippets to be cycled through.
-        if (Services.prefs.getBoolPref("browser.snippets.firstrunHomepage.enabled")) {
-          loadHomePanelsBanner();
-        }
-
-        if (Services.prefs.getBoolPref("browser.snippets.syncPromo.enabled")) {
-          loadSyncPromoBanner();
-        }
-
-        if (Services.prefs.getBoolPref("browser.snippets.enabled")) {
-          loadSnippetsFromCache();
-        }
-        break;
-    }
-  },
-
-  // By default, this timer fires once every 24 hours. See the "browser.snippets.updateInterval" pref.
-  notify: function(timer) {
-    if (!Services.prefs.getBoolPref("browser.snippets.enabled")) {
-      return;
-    }
-    update();
-    sendStats();
-  }
-};
-
-this.NSGetFactory = XPCOMUtils.generateNSGetFactory([Snippets]);
--- a/mobile/android/components/moz.build
+++ b/mobile/android/components/moz.build
@@ -31,17 +31,16 @@ EXTRA_COMPONENTS += [
     'ImageBlockingPolicy.js',
     'LoginManagerPrompter.js',
     'NSSDialogService.js',
     'PersistentNotificationHandler.js',
     'PresentationDevicePrompt.js',
     'PresentationRequestUIGlue.js',
     'PromptService.js',
     'SessionStore.js',
-    'Snippets.js',
     'TabSource.js',
     'XPIDialogService.js',
 ]
 
 # Keep it this way if at all possible.  If you need preprocessing,
 # consider adding fields to AppConstants.jsm.
 EXTRA_PP_COMPONENTS += [
     'MobileComponents.manifest',
--- a/mobile/android/installer/package-manifest.in
+++ b/mobile/android/installer/package-manifest.in
@@ -368,17 +368,16 @@
 @BINPATH@/components/LoginManagerPrompter.js
 @BINPATH@/components/MobileComponents.manifest
 @BINPATH@/components/NSSDialogService.js
 @BINPATH@/components/PersistentNotificationHandler.js
 @BINPATH@/components/PresentationDevicePrompt.js
 @BINPATH@/components/PresentationRequestUIGlue.js
 @BINPATH@/components/PromptService.js
 @BINPATH@/components/SessionStore.js
-@BINPATH@/components/Snippets.js
 @BINPATH@/components/XPIDialogService.js
 #endif
 
 ; Remote control protocol
 #ifdef ENABLE_MARIONETTE
 @BINPATH@/chrome/marionette@JAREXT@
 @BINPATH@/chrome/marionette.manifest
 @BINPATH@/components/marionette.manifest