Bug 925101 - Remove legacy signons.txt files. r?dolske draft
authorRay Lin <ralin@mozilla.com>
Tue, 19 Apr 2016 17:28:01 +0800
changeset 365189 63c59253f17b7e9cb6f091e1c954f6f549a233b0
parent 364815 043082cb7bd8490c60815f67fbd1f33323ad7663
child 520480 e6b62b6fe9ce7fbb5246aa7b5618c5c2fe97ead4
push id17662
push userbmo:ralin@mozilla.com
push dateTue, 10 May 2016 07:29:40 +0000
reviewersdolske
bugs925101
milestone49.0a1
Bug 925101 - Remove legacy signons.txt files. r?dolske MozReview-Commit-ID: ICZADhIeKiB
browser/components/nsBrowserGlue.js
toolkit/components/passwordmgr/LoginHelper.jsm
toolkit/components/passwordmgr/test/unit/test_removeLegacySignonFiles.js
toolkit/components/passwordmgr/test/unit/xpcshell.ini
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -103,16 +103,19 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource:///modules/BrowserUITelemetry.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "AsyncShutdown",
                                   "resource://gre/modules/AsyncShutdown.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "LoginManagerParent",
                                   "resource://gre/modules/LoginManagerParent.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
+                                  "resource://gre/modules/LoginHelper.jsm");
+
 XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
                                   "resource://gre/modules/SimpleServiceDiscovery.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
                                   "resource:///modules/ContentSearch.jsm");
 
 if (AppConstants.E10S_TESTING_ONLY) {
   XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
@@ -1826,17 +1829,17 @@ BrowserGlue.prototype = {
     var notifyBox = win.gBrowser.getNotificationBox();
     var notification = notifyBox.appendNotification(text, title, null,
                                                     notifyBox.PRIORITY_CRITICAL_MEDIUM,
                                                     buttons);
     notification.persistence = -1; // Until user closes it
   },
 
   _migrateUI: function BG__migrateUI() {
-    const UI_VERSION = 37;
+    const UI_VERSION = 38;
     const BROWSER_DOCURL = "chrome://browser/content/browser.xul";
 
     let currentUIVersion;
     if (Services.prefs.prefHasUserValue("browser.migration.version")) {
       currentUIVersion = Services.prefs.getIntPref("browser.migration.version");
     } else {
       // This is a new profile, nothing to migrate.
       Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
@@ -2192,16 +2195,19 @@ BrowserGlue.prototype = {
                            "passwordCol",
                            "hidden");
     }
 
     if (currentUIVersion < 37) {
       Services.prefs.clearUserPref("browser.sessionstore.restore_on_demand");
     }
 
+    if (currentUIVersion < 38) {
+      LoginHelper.removeLegacySignonFiles();
+    }
     // Update the migration version.
     Services.prefs.setIntPref("browser.migration.version", UI_VERSION);
   },
 
   _hasExistingNotificationPermission: function BG__hasExistingNotificationPermission() {
     let enumerator = Services.perms.enumerator;
     while (enumerator.hasMoreElements()) {
       let permission = enumerator.getNext().QueryInterface(Ci.nsIPermission);
--- a/toolkit/components/passwordmgr/LoginHelper.jsm
+++ b/toolkit/components/passwordmgr/LoginHelper.jsm
@@ -445,10 +445,37 @@ this.LoginHelper = {
     return formLogin;
   },
 
   /**
    * As above, but for an array of objects.
    */
   vanillaObjectsToLogins(logins) {
     return logins.map(this.vanillaObjectToLogin);
+  },
+
+  removeLegacySignonFiles() {
+    const {Constants, Path, File} = Cu.import("resource://gre/modules/osfile.jsm").OS;
+
+    const profileDir = Constants.Path.profileDir;
+    const defaultSignonFilePrefs = new Map([
+      ["signon.SignonFileName", "signons.txt"],
+      ["signon.SignonFileName2", "signons2.txt"],
+      ["signon.SignonFileName3", "signons3.txt"]
+    ]);
+    const toDeletes = new Set();
+
+    for (let [pref, val] of defaultSignonFilePrefs.entries()) {
+      toDeletes.add(Path.join(profileDir, val));
+
+      try {
+        let signonFile = Services.prefs.getCharPref(pref);
+
+        toDeletes.add(Path.join(profileDir, signonFile));
+        Services.prefs.clearUserPref(pref);
+      } catch (e) {}
+    }
+
+    for (let file of toDeletes) {
+      File.remove(file);
+    }
   }
 };
new file mode 100644
--- /dev/null
+++ b/toolkit/components/passwordmgr/test/unit/test_removeLegacySignonFiles.js
@@ -0,0 +1,69 @@
+/**
+ * Tests the LoginHelper object.
+ */
+
+"use strict";
+
+
+Cu.import("resource://gre/modules/Task.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "LoginHelper",
+                                  "resource://gre/modules/LoginHelper.jsm");
+
+
+function* createSignonFile(singon) {
+  let {file, pref}  = singon;
+
+  if (pref) {
+    Services.prefs.setCharPref(pref, file);
+  }
+
+  yield OS.File.writeAtomic(
+    OS.Path.join(OS.Constants.Path.profileDir, file), new Uint8Array(1));
+}
+
+function* isSignonClear(singon) {
+  const {file, pref} = singon;
+  const fileExists = yield OS.File.exists(
+    OS.Path.join(OS.Constants.Path.profileDir, file));
+
+  if (pref) {
+    try {
+      Services.prefs.getCharPref(pref);
+      return false;
+    } catch (e) {}
+  }
+
+  return !fileExists;
+}
+
+add_task(function* test_remove_lagecy_signonfile() {
+  // In the last test case, signons3.txt being deleted even when
+  // it doesn't exist.
+  const signonsSettings = [[
+    { file: "signons.txt" },
+    { file: "signons2.txt" },
+    { file: "signons3.txt" }
+  ], [
+    { file: "signons.txt", pref: "signon.SignonFileName" },
+    { file: "signons2.txt", pref: "signon.SignonFileName2" },
+    { file: "signons3.txt", pref: "signon.SignonFileName3" }
+  ], [
+    { file: "signons2.txt" },
+    { file: "singons.txt", pref: "signon.SignonFileName" },
+    { file: "customized2.txt", pref: "signon.SignonFileName2" },
+    { file: "customized3.txt", pref: "signon.SignonFileName3" }
+  ]];
+
+  for (let setting of signonsSettings) {
+    for (let singon of setting) {
+      yield createSignonFile(singon);
+    }
+
+    LoginHelper.removeLegacySignonFiles();
+
+    for (let singon of setting) {
+      equal(yield isSignonClear(singon), true);
+    }
+  }
+});
--- a/toolkit/components/passwordmgr/test/unit/xpcshell.ini
+++ b/toolkit/components/passwordmgr/test/unit/xpcshell.ini
@@ -4,16 +4,18 @@ tail =
 skip-if = toolkit == 'gonk'
 support-files = data/**
 
 # Test JSON file access and import from SQLite, not applicable to Android.
 [test_module_LoginImport.js]
 skip-if = os == "android"
 [test_module_LoginStore.js]
 skip-if = os == "android"
+[test_removeLegacySignonFiles.js]
+skip-if = os == "android"
 
 # Test SQLite database backup and migration, applicable to Android only.
 [test_storage_mozStorage.js]
 skip-if = true || os != "android" # Bug 1171687: Needs fixing on Android
 
 # The following tests apply to any storage back-end.
 [test_context_menu.js]
 skip-if = os == "android" # The context menu isn't used on Android.