Bug 1162205 - Don't import encrypted cookies from Chrome. r=mak a=lmandel GECKO380_2015050320_RELBRANCH
authorMatthew Noorenberghe <mozilla@noorenberghe.ca>
Fri, 08 May 2015 11:41:10 -0700
branchGECKO380_2015050320_RELBRANCH
changeset 260468 7bf6c9a78588
parent 260432 ff5ce9fad044
child 260469 d204dd3fd48b
push id791
push usermozilla@noorenberghe.ca
push date2015-05-13 20:12 +0000
treeherdermozilla-release@7bf6c9a78588 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmak, lmandel
bugs1162205
milestone38.0
Bug 1162205 - Don't import encrypted cookies from Chrome. r=mak a=lmandel Includes https://hg.mozilla.org/mozilla-central/raw-diff/0ac453f0a1f6/browser/components/migration/tests/unit/head_migration.js
browser/components/migration/ChromeProfileMigrator.js
browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Default/Cookies
browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State
browser/components/migration/tests/unit/head_migration.js
browser/components/migration/tests/unit/test_Chrome_cookies.js
browser/components/migration/tests/unit/xpcshell.ini
--- a/browser/components/migration/ChromeProfileMigrator.js
+++ b/browser/components/migration/ChromeProfileMigrator.js
@@ -302,18 +302,21 @@ function GetCookiesResource(aProfileFold
   if (!cookiesFile.exists())
     return null;
 
   return {
     type: MigrationUtils.resourceTypes.COOKIES,
 
     migrate: function(aCallback) {
       let dbConn = Services.storage.openUnsharedDatabase(cookiesFile);
-      let stmt = dbConn.createAsyncStatement(
-          "SELECT host_key, path, name, value, secure, httponly, expires_utc FROM cookies");
+      // We don't support decrypting cookies yet so only import plaintext ones.
+      let stmt = dbConn.createAsyncStatement(`
+        SELECT host_key, name, value, path, expires_utc, secure, httponly, encrypted_value
+        FROM cookies
+        WHERE length(encrypted_value) = 0`);
 
       stmt.executeAsync({
         handleResult : function(aResults) {
           for (let row = aResults.getNextRow(); row; row = aResults.getNextRow()) {
             let host_key = row.getResultByName("host_key");
             if (host_key.match(/^\./)) {
               // 1st character of host_key may be ".", so we have to remove it
               host_key = host_key.substr(1);
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..83d855cb339e298dd3d8b7fa298b30175df501c4
GIT binary patch
literal 10240
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
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/tests/unit/Library/Application Support/Google/Chrome/Local State	
@@ -0,0 +1,22 @@
+{
+  "profile" : {
+    "info_cache" : {
+      "Default" : {
+        "active_time" : 1430950755.65137,
+        "is_using_default_name" : true,
+        "is_ephemeral" : false,
+        "is_omitted_from_profile_list" : false,
+        "user_name" : "",
+        "background_apps" : false,
+        "is_using_default_avatar" : true,
+        "avatar_icon" : "chrome://theme/IDR_PROFILE_AVATAR_0",
+        "name" : "Person 1"
+      }
+    },
+    "profiles_created" : 1,
+    "last_used" : "Default",
+    "last_active_profiles" : [
+      "Default"
+    ]
+  }
+}
--- a/browser/components/migration/tests/unit/head_migration.js
+++ b/browser/components/migration/tests/unit/head_migration.js
@@ -16,22 +16,45 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 let gProfD = do_get_profile();
 
 Cu.import("resource://testing-common/AppInfo.jsm");
 updateAppInfo();
 
 /**
  * Migrates the requested resource and waits for the migration to be complete.
  */
-function promiseMigration(migrator, resourceType) {
+function promiseMigration(migrator, resourceType, aProfile = null) {
   // Ensure resource migration is available.
-  let availableSources = migrator.getMigrateData(null, false);
-  Assert.ok((availableSources & resourceType) > 0);
+  let availableSources = migrator.getMigrateData(aProfile, false);
+  Assert.ok((availableSources & resourceType) > 0, "Resource supported by migrator");
 
   return new Promise (resolve => {
     Services.obs.addObserver(function onMigrationEnded() {
       Services.obs.removeObserver(onMigrationEnded, "Migration:Ended");
       resolve();
     }, "Migration:Ended", false);
 
-    migrator.migrate(resourceType, null, null);
+    migrator.migrate(resourceType, null, aProfile);
   });
 }
+
+/**
+ * Replaces a directory service entry with a given nsIFile.
+ */
+function registerFakePath(key, file) {
+   // Register our own provider for the Library directory.
+  let provider = {
+    getFile(prop, persistent) {
+      persistent.value = true;
+      if (prop == key) {
+        return file;
+      }
+      throw Cr.NS_ERROR_FAILURE;
+    },
+    QueryInterface: XPCOMUtils.generateQI([ Ci.nsIDirectoryServiceProvider ])
+  };
+  Services.dirsvc.QueryInterface(Ci.nsIDirectoryService)
+                 .registerProvider(provider);
+  do_register_cleanup(() => {
+    Services.dirsvc.QueryInterface(Ci.nsIDirectoryService)
+                   .unregisterProvider(provider);
+  });
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/tests/unit/test_Chrome_cookies.js
@@ -0,0 +1,49 @@
+Cu.import("resource://gre/modules/ForgetAboutSite.jsm");
+
+add_task(function* () {
+  registerFakePath("ULibDir", do_get_file("Library/"));
+  let migrator = MigrationUtils.getMigrator("chrome");
+
+  Assert.ok(migrator.sourceExists, "Sanity check the source exists");
+
+  const COOKIE = {
+    expiry: 2145934800,
+    host: "unencryptedcookie.invalid",
+    isHttpOnly: false,
+    isSession: false,
+    name: "testcookie",
+    path: "/",
+    value: "testvalue",
+  };
+
+  // Sanity check.
+  Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0,
+               "There are no cookies initially");
+
+  const PROFILE = {
+    id: "Default",
+    name: "Person 1",
+  };
+
+  // Migrate unencrypted cookies.
+  yield promiseMigration(migrator, MigrationUtils.resourceTypes.COOKIES, PROFILE);
+
+  do_register_cleanup(() => {
+    ForgetAboutSite.removeDataFromDomain(COOKIE.host);
+    Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 0,
+                 "There are no cookies after cleanup");
+  });
+  Assert.equal(Services.cookies.countCookiesFromHost(COOKIE.host), 1,
+               "Migrated the expected number of unencrypted cookies");
+  Assert.equal(Services.cookies.countCookiesFromHost("encryptedcookie.invalid"), 0,
+               "Migrated the expected number of encrypted cookies");
+
+  // Now check the cookie details.
+  let enumerator = Services.cookies.getCookiesFromHost(COOKIE.host);
+  Assert.ok(enumerator.hasMoreElements(), "Cookies available");
+  let foundCookie = enumerator.getNext().QueryInterface(Ci.nsICookie2);
+
+  for (let prop of Object.keys(COOKIE)) {
+    Assert.equal(foundCookie[prop], COOKIE[prop], "Check cookie " + prop);
+  }
+});
--- a/browser/components/migration/tests/unit/xpcshell.ini
+++ b/browser/components/migration/tests/unit/xpcshell.ini
@@ -1,11 +1,15 @@
 [DEFAULT]
 head = head_migration.js
 tail =
 firefox-appdir = browser
 skip-if = toolkit == 'android' || toolkit == 'gonk'
+support-files =
+  Library/**
 
+[test_Chrome_cookies.js]
+skip-if = os != "mac" # Relies on ULibDir
 [test_fx_fhr.js]
 [test_IE_bookmarks.js]
 skip-if = os != "win"
 [test_IE_cookies.js]
 skip-if = os != "win"