Bug 1320404 - Remove appId from origin attributes - part 3 - Permissionmanager, r=Ehsan
☠☠ backed out by 04557fa70ce8 ☠ ☠
authorAndrea Marchesini <amarchesini@mozilla.com>
Thu, 02 May 2019 17:24:59 +0000
changeset 531220 a7e7c02511798c661d48abedd7358f10e7efc507
parent 531219 dd741b25a24443f4c4298b46933eb21a603fc22f
child 531221 7c2f4e64d38e0405f9ff86d16f3d51d1e9f3306c
push id11265
push userffxbld-merge
push dateMon, 13 May 2019 10:53:39 +0000
treeherdermozilla-beta@77e0fe8dbdd3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersEhsan
bugs1320404
milestone68.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 1320404 - Remove appId from origin attributes - part 3 - Permissionmanager, r=Ehsan Differential Revision: https://phabricator.services.mozilla.com/D29355
extensions/permissions/nsPermissionManager.cpp
extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js
extensions/permissions/test/unit/test_permmanager_matches.js
extensions/permissions/test/unit/test_permmanager_migrate_5-7b.js
extensions/permissions/test/unit/test_permmanager_migrate_6-7b.js
extensions/permissions/test/unit/test_permmanager_migrate_9-10.js
extensions/permissions/test/unit/xpcshell.ini
testing/talos/talos/xtalos/xperf_whitelist.json
--- a/extensions/permissions/nsPermissionManager.cpp
+++ b/extensions/permissions/nsPermissionManager.cpp
@@ -882,17 +882,17 @@ void nsPermissionManager::Startup() {
   nsCOMPtr<nsIPermissionManager> permManager =
       do_GetService("@mozilla.org/permissionmanager;1");
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsPermissionManager Implementation
 
 #define PERMISSIONS_FILE_NAME "permissions.sqlite"
-#define HOSTS_SCHEMA_VERSION 9
+#define HOSTS_SCHEMA_VERSION 10
 
 #define HOSTPERM_FILE_NAME "hostperm.1"
 
 // Default permissions are read from a URL - this is the preference we read
 // to find that URL. If not set, don't use any default permissions.
 static const char kDefaultsUrlPrefName[] = "permissions.manager.defaultsUrl";
 
 static const char kPermissionChangeNotification[] = PERM_CHANGE_NOTIFICATION;
@@ -1298,27 +1298,26 @@ nsresult nsPermissionManager::InitDB(boo
                                  ",modificationTime INTEGER"
                                  ")"));
           NS_ENSURE_SUCCESS(rv, rv);
 
           nsCOMPtr<mozIStorageStatement> stmt;
           rv = mDBConn->CreateStatement(
               NS_LITERAL_CSTRING(
                   "SELECT host, type, permission, expireType, expireTime, "
-                  "modificationTime, appId, isInBrowserElement FROM moz_hosts"),
+                  "modificationTime, isInBrowserElement FROM moz_hosts"),
               getter_AddRefs(stmt));
           NS_ENSURE_SUCCESS(rv, rv);
 
           int64_t id = 0;
           nsAutoCString host, type;
           uint32_t permission;
           uint32_t expireType;
           int64_t expireTime;
           int64_t modificationTime;
-          uint32_t deprecatedAppId;
           bool isInBrowserElement;
           bool hasResult;
 
           while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
             // Read in the old row
             rv = stmt->GetUTF8String(0, host);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               migrationError = true;
@@ -1328,22 +1327,17 @@ nsresult nsPermissionManager::InitDB(boo
             if (NS_WARN_IF(NS_FAILED(rv))) {
               migrationError = true;
               continue;
             }
             permission = stmt->AsInt32(2);
             expireType = stmt->AsInt32(3);
             expireTime = stmt->AsInt64(4);
             modificationTime = stmt->AsInt64(5);
-            if (NS_WARN_IF(stmt->AsInt64(6) < 0)) {
-              migrationError = true;
-              continue;
-            }
-            deprecatedAppId = static_cast<uint32_t>(stmt->AsInt64(6));  // TODO
-            isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
+            isInBrowserElement = static_cast<bool>(stmt->AsInt32(6));
 
             // Perform the meat of the migration by deferring to the
             // UpgradeHostToOriginAndInsert function.
             UpgradeHostToOriginDBMigration upHelper(mDBConn, &id);
             rv = UpgradeHostToOriginAndInsert(
                 host, type, permission, expireType, expireTime,
                 modificationTime, isInBrowserElement, &upHelper);
             if (NS_FAILED(rv)) {
@@ -1477,17 +1471,17 @@ nsresult nsPermissionManager::InitDB(boo
 
         // Only perform this migration if the original schema version was 7, and
         // the moz_hosts table is a backup.
         if (dbSchemaVersion == 7 && hostsIsBackupExists) {
           nsCOMPtr<mozIStorageStatement> stmt;
           rv = mDBConn->CreateStatement(
               NS_LITERAL_CSTRING(
                   "SELECT host, type, permission, expireType, expireTime, "
-                  "modificationTime, appId, isInBrowserElement FROM moz_hosts"),
+                  "modificationTime, isInBrowserElement FROM moz_hosts"),
               getter_AddRefs(stmt));
           NS_ENSURE_SUCCESS(rv, rv);
 
           nsCOMPtr<mozIStorageStatement> idStmt;
           rv = mDBConn->CreateStatement(
               NS_LITERAL_CSTRING("SELECT MAX(id) FROM moz_hosts"),
               getter_AddRefs(idStmt));
           int64_t id = 0;
@@ -1497,17 +1491,16 @@ nsresult nsPermissionManager::InitDB(boo
             id = idStmt->AsInt32(0) + 1;
           }
 
           nsAutoCString host, type;
           uint32_t permission;
           uint32_t expireType;
           int64_t expireTime;
           int64_t modificationTime;
-          uint32_t deprecatedAppId;
           bool isInBrowserElement;
 
           while (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult)) && hasResult) {
             // Read in the old row
             rv = stmt->GetUTF8String(0, host);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
@@ -1523,21 +1516,17 @@ nsresult nsPermissionManager::InitDB(boo
             rv = stmt->GetUTF8String(1, type);
             if (NS_WARN_IF(NS_FAILED(rv))) {
               continue;
             }
             permission = stmt->AsInt32(2);
             expireType = stmt->AsInt32(3);
             expireTime = stmt->AsInt64(4);
             modificationTime = stmt->AsInt64(5);
-            if (NS_WARN_IF(stmt->AsInt64(6) < 0)) {
-              continue;
-            }
-            deprecatedAppId = static_cast<uint32_t>(stmt->AsInt64(6));  // TODO
-            isInBrowserElement = static_cast<bool>(stmt->AsInt32(7));
+            isInBrowserElement = static_cast<bool>(stmt->AsInt32(6));
 
             // Perform the meat of the migration by deferring to the
             // UpgradeHostToOriginAndInsert function.
             UpgradeIPHostToOriginDB upHelper(mDBConn, &id);
             rv = UpgradeHostToOriginAndInsert(
                 host, type, permission, expireType, expireTime,
                 modificationTime, isInBrowserElement, &upHelper);
             if (NS_FAILED(rv)) {
@@ -1581,16 +1570,74 @@ nsresult nsPermissionManager::InitDB(boo
 
         rv = mDBConn->SetSchemaVersion(9);
         NS_ENSURE_SUCCESS(rv, rv);
       }
 
         // fall through to the next upgrade
         MOZ_FALLTHROUGH;
 
+      // Version 10 removes appId from moz_hosts. SQLite doesn't support the
+      // dropping of columns from existing tables. We need to create a temporary
+      // table, copy the data, drop the old table, rename the new one.
+      case 9: {
+        rv = mDBConn->BeginTransaction();
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        bool tableExists = false;
+        mDBConn->TableExists(NS_LITERAL_CSTRING("moz_hosts_v9"), &tableExists);
+        if (tableExists) {
+          NS_WARNING(
+              "The temporary database moz_hosts_v9 already exists, dropping "
+              "it.");
+          rv = mDBConn->ExecuteSimpleSQL(
+              NS_LITERAL_CSTRING("DROP TABLE moz_hosts_v9"));
+          NS_ENSURE_SUCCESS(rv, rv);
+        }
+
+        rv = mDBConn->ExecuteSimpleSQL(
+            NS_LITERAL_CSTRING("CREATE TABLE moz_hosts_v9 ("
+                               " id INTEGER PRIMARY KEY"
+                               ",host TEXT"
+                               ",type TEXT"
+                               ",permission INTEGER"
+                               ",expireType INTEGER"
+                               ",expireTime INTEGER"
+                               ",modificationTime INTEGER"
+                               ",isInBrowserElement INTEGER"
+                               ")"));
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        rv = mDBConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+            "INSERT INTO moz_hosts_v9 "
+            "(id, host, type, permission, expireType, "
+            "expireTime, modificationTime, isInBrowserElement) "
+            "SELECT id, host, type, permission, expireType, expireTime, "
+            "modificationTime, isInBrowserElement FROM moz_hosts WHERE appId = "
+            "0"));
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        rv = mDBConn->ExecuteSimpleSQL(
+            NS_LITERAL_CSTRING("DROP TABLE moz_hosts"));
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        rv = mDBConn->ExecuteSimpleSQL(
+            NS_LITERAL_CSTRING("ALTER TABLE moz_hosts_v9 RENAME TO moz_hosts"));
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        rv = mDBConn->SetSchemaVersion(10);
+        NS_ENSURE_SUCCESS(rv, rv);
+
+        rv = mDBConn->CommitTransaction();
+        NS_ENSURE_SUCCESS(rv, rv);
+      }
+
+        // fall through to the next upgrade
+        MOZ_FALLTHROUGH;
+
       // current version.
       case HOSTS_SCHEMA_VERSION:
         break;
 
       // downgrading.
       // if columns have been added to the table, we can still use the ones we
       // understand safely. if columns have been deleted or altered, just
       // blow away the table and start from scratch! if you change the way
@@ -1673,17 +1720,16 @@ nsresult nsPermissionManager::CreateTabl
       NS_LITERAL_CSTRING("CREATE TABLE moz_hosts ("
                          " id INTEGER PRIMARY KEY"
                          ",host TEXT"
                          ",type TEXT"
                          ",permission INTEGER"
                          ",expireType INTEGER"
                          ",expireTime INTEGER"
                          ",modificationTime INTEGER"
-                         ",appId INTEGER"
                          ",isInBrowserElement INTEGER"
                          ")"));
 }
 
 NS_IMETHODIMP
 nsPermissionManager::Add(nsIURI* aURI, const nsACString& aType,
                          uint32_t aPermission, uint32_t aExpireType,
                          int64_t aExpireTime) {
@@ -2409,17 +2455,17 @@ nsresult nsPermissionManager::CommonTest
 
   *aPermission = aIncludingSession
                      ? entry->GetPermission(aTypeIndex).mPermission
                      : entry->GetPermission(aTypeIndex).mNonSessionPermission;
 
   return NS_OK;
 }
 
-// Returns PermissionHashKey for a given { host, appId, isInBrowserElement }
+// Returns PermissionHashKey for a given { host, isInBrowserElement }
 // tuple. This is not simply using PermissionKey because we will walk-up domains
 // in case of |host| contains sub-domains. Returns null if nothing found. Also
 // accepts host on the format "<foo>". This will perform an exact match lookup
 // as the string doesn't contain any dots.
 nsPermissionManager::PermissionHashKey*
 nsPermissionManager::GetPermissionHashKey(nsIPrincipal* aPrincipal,
                                           uint32_t aType,
                                           bool aExactHostMatch) {
@@ -2462,17 +2508,17 @@ nsPermissionManager::GetPermissionHashKe
       return GetPermissionHashKey(principal, aType, aExactHostMatch);
     }
   }
 
   // No entry, really...
   return nullptr;
 }
 
-// Returns PermissionHashKey for a given { host, appId, isInBrowserElement }
+// Returns PermissionHashKey for a given { host, isInBrowserElement }
 // tuple. This is not simply using PermissionKey because we will walk-up domains
 // in case of |host| contains sub-domains. Returns null if nothing found. Also
 // accepts host on the format "<foo>". This will perform an exact match lookup
 // as the string doesn't contain any dots.
 nsPermissionManager::PermissionHashKey*
 nsPermissionManager::GetPermissionHashKey(nsIURI* aURI,
                                           const nsACString& aOriginNoSuffix,
                                           uint32_t aType,
--- a/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js
+++ b/extensions/permissions/test/unit/test_permmanager_load_invalid_entries.js
@@ -32,91 +32,86 @@ function run_test() {
       ",appId INTEGER" +
       ",isInBrowserElement INTEGER" +
     ")");
 
   // Now we can inject garbadge in the database.
   var garbadge = [
     // Regular entry.
     { host: '42', type: '0', permission: 1, expireType: 0, expireTime: 0,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
 
     // Special values in host (some being invalid).
     { host: 'scheme:file', type: '1', permission: 0, expireType: 0,
-      expireTime: 0, appId: 0, isInBrowserElement: 0 },
+      expireTime: 0, isInBrowserElement: 0 },
     { host: '192.168.0.1', type: '2', permission: 0, expireType: 0,
-      expireTime: 0, appId: 0, isInBrowserElement: 0 },
+      expireTime: 0, isInBrowserElement: 0 },
     { host: '2001:0db8:0000:0000:0000:ff00:0042:8329', type: '3', permission: 0,
-      expireType: 0, expireTime: 0, appId: 0, isInBrowserElement: 0 },
+      expireType: 0, expireTime: 0, isInBrowserElement: 0 },
     { host: '::1', type: '4', permission: 0, expireType: 0, expireTime: 0,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
 
     // Permission is UNKNOWN_ACTION.
     { host: '42', type: '5', permission: Ci.nsIPermissionManager.UNKNOWN_ACTION,
-      expireType: 0, expireTime: 0, appId: 0, isInBrowserElement: 0 },
+      expireType: 0, expireTime: 0, isInBrowserElement: 0 },
 
     // Permission is out of range.
     { host: '42', type: '6', permission: 100, expireType: 0, expireTime: 0,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
     { host: '42', type: '7', permission: -100, expireType: 0, expireTime: 0,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
 
     // ExpireType is out of range.
     { host: '42', type: '8', permission: 1, expireType: -100, expireTime: 0,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
     { host: '42', type: '9', permission: 1, expireType: 100, expireTime: 0,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
 
     // ExpireTime is at 0 with ExpireType = Time.
     { host: '42', type: '10', permission: 1,
-      expireType: Ci.nsIPermissionManager.EXPIRE_TIME, expireTime: 0, appId: 0,
+      expireType: Ci.nsIPermissionManager.EXPIRE_TIME, expireTime: 0,
       isInBrowserElement: 0 },
 
     // ExpireTime has a value with ExpireType != Time
     { host: '42', type: '11', permission: 1,
       expireType: Ci.nsIPermissionManager.EXPIRE_SESSION, expireTime: 1000,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
     { host: '42', type: '12', permission: 1,
       expireType: Ci.nsIPermissionManager.EXPIRE_NEVER, expireTime: 1000,
-      appId: 0, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
 
     // ExpireTime is negative.
     { host: '42', type: '13', permission: 1,
       expireType: Ci.nsIPermissionManager.EXPIRE_TIME, expireTime: -1,
-      appId: 0, isInBrowserElement: 0 },
-
-    // AppId is negative.
-    { host: '42', type: '14', permission: 1, expireType: 0, expireTime: 0,
-      appId: -1, isInBrowserElement: 0 },
+      isInBrowserElement: 0 },
 
     // IsInBrowserElement is negative or higher than 1.
     { host: '42', type: '15', permission: 1, expireType: 0, expireTime: 0,
-      appId: 0, isInBrowserElement: -1 },
+      isInBrowserElement: -1 },
     { host: '42', type: '16', permission: 1, expireType: 0, expireTime: 0,
-      appId: 0, isInBrowserElement: 10 },
+      isInBrowserElement: 10 },
 
     // This insertion should be the last one. It is used to make sure we always
     // load it regardless of the previous entries validities.
     { host: 'example.org', type: 'test-load-invalid-entries',
       permission: Ci.nsIPermissionManager.ALLOW_ACTION, expireType: 0,
-      expireTime: 0, appId: 0, isInBrowserElement: 0 },
+      expireTime: 0, isInBrowserElement: 0 },
   ];
 
   for (var i=0; i<garbadge.length; ++i) {
     if (DEBUG_TEST) {
       dump("\n value #" + i + "\n\n");
     }
     var data = garbadge[i];
     connection.executeSimpleSQL(
       "INSERT INTO moz_hosts " +
-      " (id, host, type, permission, expireType, expireTime, appId, isInBrowserElement) " +
+      " (id, host, type, permission, expireType, expireTime, isInBrowserElement, appId) " +
       "VALUES (" + i + ", '" + data.host + "', '" + data.type + "', "
                  + data.permission + ", " + data.expireType + ", "
-                 + data.expireTime + ", " + data.appId + ", "
-                 + data.isInBrowserElement + ")"
+                 + data.expireTime + ", " + data.isInBrowserElement + ", 0)"
     );
   }
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk", "");
 
   let earliestNow = Number(Date.now());
   // Initialize the permission manager service
--- a/extensions/permissions/test/unit/test_permmanager_matches.js
+++ b/extensions/permissions/test/unit/test_permmanager_matches.js
@@ -66,60 +66,46 @@ function run_test() {
   let uri1_cnn = secMan.createCodebasePrincipal(uri1, attrs);
   let uri2_cnn = secMan.createCodebasePrincipal(uri2, attrs);
   let uri3_cnn = secMan.createCodebasePrincipal(uri3, attrs);
   let uri4_cnn = secMan.createCodebasePrincipal(uri4, attrs);
   let uri5_cnn = secMan.createCodebasePrincipal(uri5, attrs);
 
   pm.addFromPrincipal(uri0_n, "test/matches", pm.ALLOW_ACTION);
   let perm_n = pm.getPermissionObject(uri0_n, "test/matches", true);
-  pm.addFromPrincipal(uri0_1000_n, "test/matches", pm.ALLOW_ACTION);
-  let perm_1000_n = pm.getPermissionObject(uri0_1000_n, "test/matches", true);
   pm.addFromPrincipal(uri0_y_, "test/matches", pm.ALLOW_ACTION);
   let perm_y_ = pm.getPermissionObject(uri0_y_, "test/matches", true);
   pm.addFromPrincipal(uri0_1, "test/matches", pm.ALLOW_ACTION);
   let perm_1 = pm.getPermissionObject(uri0_n, "test/matches", true);
   pm.addFromPrincipal(uri0_cnn, "test/matches", pm.ALLOW_ACTION);
   let perm_cnn = pm.getPermissionObject(uri0_n, "test/matches", true);
 
   matches_always(perm_n, [uri0_n, uri0_1, uri0_cnn]);
   matches_weak(perm_n, [uri1_n, uri1_1, uri1_cnn]);
   matches_never(perm_n, [uri2_n, uri3_n, uri4_n, uri5_n,
-                           uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
                            uri0_y_, uri1_y_, uri2_y_, uri3_y_, uri4_y_, uri5_y_,
                            uri2_1, uri3_1, uri4_1, uri5_1,
                            uri2_cnn, uri3_cnn, uri4_cnn, uri5_cnn]);
 
-  matches_always(perm_1000_n, [uri0_1000_n]);
-  matches_weak(perm_1000_n, [uri1_1000_n]);
-  matches_never(perm_1000_n, [uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
-                              uri0_n, uri1_n, uri2_n, uri3_n, uri4_n, uri5_n,
-                              uri0_y_, uri1_y_, uri2_y_, uri3_y_, uri4_y_, uri5_y_,
-                              uri0_1, uri1_1, uri2_1, uri3_1, uri4_1, uri5_1,
-                              uri0_cnn, uri1_cnn, uri2_cnn, uri3_cnn, uri4_cnn, uri5_cnn]);
-
   matches_always(perm_y_, [uri0_y_]);
   matches_weak(perm_y_, [uri1_y_]);
   matches_never(perm_y_, [uri2_y_, uri3_y_, uri4_y_, uri5_y_,
                               uri0_n, uri1_n, uri2_n, uri3_n, uri4_n, uri5_n,
-                              uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
                               uri0_1, uri1_1, uri2_1, uri3_1, uri4_1, uri5_1,
                               uri0_cnn, uri1_cnn, uri2_cnn, uri3_cnn, uri4_cnn, uri5_cnn]);
 
   matches_always(perm_1, [uri0_n, uri0_1, uri0_cnn]);
   matches_weak(perm_1, [uri1_n, uri1_1, uri1_cnn]);
   matches_never(perm_1, [uri2_n, uri3_n, uri4_n, uri5_n,
-                         uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
                          uri0_y_, uri1_y_, uri2_y_, uri3_y_, uri4_y_, uri5_y_,
                          uri2_1, uri3_1, uri4_1, uri5_1,
                          uri2_cnn, uri3_cnn, uri4_cnn, uri5_cnn]);
 
   matches_always(perm_cnn, [uri0_n, uri0_1, uri0_cnn]);
   matches_weak(perm_cnn, [uri1_n, uri1_1, uri1_cnn]);
   matches_never(perm_cnn, [uri2_n, uri3_n, uri4_n, uri5_n,
-                           uri0_1000_n, uri1_1000_n, uri2_1000_n, uri3_1000_n, uri4_1000_n, uri5_1000_n,
                            uri0_y_, uri1_y_, uri2_y_, uri3_y_, uri4_y_, uri5_y_,
                            uri2_1, uri3_1, uri4_1, uri5_1,
                            uri2_cnn, uri3_cnn, uri4_cnn, uri5_cnn]);
 
   // Clean up!
   pm.removeAll();
 }
--- a/extensions/permissions/test/unit/test_permmanager_migrate_5-7b.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_5-7b.js
@@ -89,17 +89,17 @@ add_task(function test() {
   stmt5Insert.finalize();
   db.close();
   stmt5Insert = null;
   db = null;
 
   let expected = [
     ["https://foo.com", "A", 2, 0, 0, 0],
     ["http://foo.com", "A", 2, 0, 0, 0],
-    ["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0],
+    ["http://foo.com^inBrowser=1", "A", 2, 0, 0, 0],
 
     ["http://127.0.0.1", "B", 2, 0, 0, 0],
     ["http://localhost", "B", 2, 0, 0, 0],
   ];
 
   let found = expected.map((it) => 0);
 
   // This will force the permission-manager to reload the data.
@@ -139,32 +139,31 @@ add_task(function test() {
     let db = Services.storage.openDatabase(GetPermissionsFile(profile));
     Assert.ok(db.tableExists("moz_perms"));
     Assert.ok(db.tableExists("moz_hosts"));
     Assert.ok(!db.tableExists("moz_hosts_is_backup"));
     Assert.ok(!db.tableExists("moz_perms_v6"));
 
     let mozHostsStmt = db.createStatement("SELECT " +
                                           "host, type, permission, expireType, expireTime, " +
-                                          "modificationTime, appId, isInBrowserElement " +
+                                          "modificationTime, isInBrowserElement " +
                                           "FROM moz_hosts WHERE id = :id");
     try {
       // Check that the moz_hosts table still contains the correct values.
       created4.forEach((it) => {
         mozHostsStmt.reset();
         mozHostsStmt.bindByName("id", it.id);
         mozHostsStmt.executeStep();
         Assert.equal(mozHostsStmt.getUTF8String(0), it.host);
         Assert.equal(mozHostsStmt.getUTF8String(1), it.type);
         Assert.equal(mozHostsStmt.getInt64(2), it.permission);
         Assert.equal(mozHostsStmt.getInt64(3), it.expireType);
         Assert.equal(mozHostsStmt.getInt64(4), it.expireTime);
         Assert.equal(mozHostsStmt.getInt64(5), it.modificationTime);
-        Assert.equal(mozHostsStmt.getInt64(6), it.appId);
-        Assert.equal(mozHostsStmt.getInt64(7), it.isInBrowserElement);
+        Assert.equal(mozHostsStmt.getInt64(6), it.isInBrowserElement);
       });
     } finally {
       mozHostsStmt.finalize();
     }
 
     // Check that there are the right number of values
     let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
     try {
--- a/extensions/permissions/test/unit/test_permmanager_migrate_6-7b.js
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_6-7b.js
@@ -86,17 +86,17 @@ add_task(function test() {
   stmt6Insert.finalize();
   db.close();
   stmt6Insert = null;
   db = null;
 
   let expected = [
     ["https://foo.com", "A", 2, 0, 0, 0],
     ["http://foo.com", "A", 2, 0, 0, 0],
-    ["http://foo.com^appId=1000&inBrowser=1", "A", 2, 0, 0, 0]
+    ["http://foo.com^inBrowser=1", "A", 2, 0, 0, 0]
   ];
 
   let found = expected.map((it) => 0);
 
   // This will force the permission-manager to reload the data.
   Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk", "");
 
   // Force initialization of the nsPermissionManager
@@ -133,32 +133,31 @@ add_task(function test() {
     let db = Services.storage.openDatabase(GetPermissionsFile(profile));
     Assert.ok(db.tableExists("moz_perms"));
     Assert.ok(db.tableExists("moz_hosts"));
     Assert.ok(!db.tableExists("moz_hosts_is_backup"));
     Assert.ok(!db.tableExists("moz_perms_v6"));
 
     let mozHostsStmt = db.createStatement("SELECT " +
                                           "host, type, permission, expireType, expireTime, " +
-                                          "modificationTime, appId, isInBrowserElement " +
+                                          "modificationTime, isInBrowserElement " +
                                           "FROM moz_hosts WHERE id = :id");
     try {
       // Check that the moz_hosts table still contains the correct values.
       created4.forEach((it) => {
         mozHostsStmt.reset();
         mozHostsStmt.bindByName("id", it.id);
         mozHostsStmt.executeStep();
         Assert.equal(mozHostsStmt.getUTF8String(0), it.host);
         Assert.equal(mozHostsStmt.getUTF8String(1), it.type);
         Assert.equal(mozHostsStmt.getInt64(2), it.permission);
         Assert.equal(mozHostsStmt.getInt64(3), it.expireType);
         Assert.equal(mozHostsStmt.getInt64(4), it.expireTime);
         Assert.equal(mozHostsStmt.getInt64(5), it.modificationTime);
-        Assert.equal(mozHostsStmt.getInt64(6), it.appId);
-        Assert.equal(mozHostsStmt.getInt64(7), it.isInBrowserElement);
+        Assert.equal(mozHostsStmt.getInt64(6), it.isInBrowserElement);
       });
     } finally {
       mozHostsStmt.finalize();
     }
 
     // Check that there are the right number of values
     let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
     try {
new file mode 100644
--- /dev/null
+++ b/extensions/permissions/test/unit/test_permmanager_migrate_9-10.js
@@ -0,0 +1,217 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+ChromeUtils.defineModuleGetter(this, "PlacesTestUtils",
+                               "resource://testing-common/PlacesTestUtils.jsm");
+
+var PERMISSIONS_FILE_NAME = "permissions.sqlite";
+
+function GetPermissionsFile(profile)
+{
+  let file = profile.clone();
+  file.append(PERMISSIONS_FILE_NAME);
+  return file;
+}
+
+add_task(async function test() {
+  /* Create and set up the permissions database */
+  let profile = do_get_profile();
+  Services.prefs.setCharPref("permissions.manager.defaultsUrl", "");
+
+  let db = Services.storage.openDatabase(GetPermissionsFile(profile));
+  db.schemaVersion = 9;
+  db.executeSimpleSQL("DROP TABLE moz_perms");
+  db.executeSimpleSQL("DROP TABLE moz_hosts");
+
+  db.executeSimpleSQL(
+    "CREATE TABLE moz_perms (" +
+      " id INTEGER PRIMARY KEY" +
+      ",origin TEXT" +
+      ",type TEXT" +
+      ",permission INTEGER" +
+      ",expireType INTEGER" +
+      ",expireTime INTEGER" +
+      ",modificationTime INTEGER" +
+    ")");
+
+  let stmt6Insert = db.createStatement(
+    "INSERT INTO moz_perms (" +
+      "id, origin, type, permission, expireType, expireTime, modificationTime" +
+    ") VALUES (" +
+      ":id, :origin, :type, :permission, :expireType, :expireTime, :modificationTime" +
+    ")");
+
+  db.executeSimpleSQL(
+    "CREATE TABLE moz_hosts (" +
+      " id INTEGER PRIMARY KEY" +
+      ",host TEXT" +
+      ",type TEXT" +
+      ",permission INTEGER" +
+      ",expireType INTEGER" +
+      ",expireTime INTEGER" +
+      ",modificationTime INTEGER" +
+      ",appId INTEGER" +
+      ",isInBrowserElement INTEGER" +
+    ")");
+
+  let stmtInsert = db.createStatement(
+    "INSERT INTO moz_hosts (" +
+      "id, host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement" +
+    ") VALUES (" +
+      ":id, :host, :type, :permission, :expireType, :expireTime, :modificationTime, :appId, :isInBrowserElement" +
+    ")");
+
+  let id = 0;
+
+  function insertOrigin(origin, type, permission, expireType, expireTime, modificationTime) {
+    let thisId = id++;
+
+    stmt6Insert.bindByName("id", thisId);
+    stmt6Insert.bindByName("origin", origin);
+    stmt6Insert.bindByName("type", type);
+    stmt6Insert.bindByName("permission", permission);
+    stmt6Insert.bindByName("expireType", expireType);
+    stmt6Insert.bindByName("expireTime", expireTime);
+    stmt6Insert.bindByName("modificationTime", modificationTime);
+
+    try {
+      stmt6Insert.execute();
+    } finally {
+      stmt6Insert.reset();
+    }
+
+    return {
+      id: thisId,
+      origin: origin,
+      type: type,
+      permission: permission,
+      expireType: expireType,
+      expireTime: expireTime,
+      modificationTime: modificationTime
+    };
+  }
+
+  function insertHost(host, type, permission, expireType, expireTime, modificationTime, appId, isInBrowserElement) {
+    let thisId = id++;
+
+    stmtInsert.bindByName("id", thisId);
+    stmtInsert.bindByName("host", host);
+    stmtInsert.bindByName("type", type);
+    stmtInsert.bindByName("permission", permission);
+    stmtInsert.bindByName("expireType", expireType);
+    stmtInsert.bindByName("expireTime", expireTime);
+    stmtInsert.bindByName("modificationTime", modificationTime);
+    stmtInsert.bindByName("appId", appId);
+    stmtInsert.bindByName("isInBrowserElement", isInBrowserElement);
+
+    try {
+      stmtInsert.execute();
+    } finally {
+      stmtInsert.reset();
+    }
+
+    return {
+      id: thisId,
+      host: host,
+      type: type,
+      permission: permission,
+      expireType: expireType,
+      expireTime: expireTime,
+      modificationTime: modificationTime,
+      appId: appId,
+      isInBrowserElement: isInBrowserElement
+    };
+  }
+
+  let created7 = [
+    insertOrigin("https://foo.com", "A", 2, 0, 0, 0),
+    insertOrigin("http://foo.com", "A", 2, 0, 0, 0),
+    insertOrigin("http://foo.com^inBrowser=1", "A", 2, 0, 0, 0),
+  ];
+
+  // Add some rows to the database
+  let created = [
+    insertHost("foo.com", "A", 1, 0, 0, 0, 0, false),
+    insertHost("foo.com", "B", 1, 0, 0, 0, 1000, false),
+    insertHost("foo.com", "C", 1, 0, 0, 0, 2000, true),
+  ];
+
+  // CLose the db connection
+  stmt6Insert.finalize();
+  stmtInsert.finalize();
+  db.close();
+  stmtInsert = null;
+  db = null;
+
+  let expected = [
+    ["https://foo.com", "A", 2, 0, 0, 0],
+    ["http://foo.com", "A", 2, 0, 0, 0],
+    ["http://foo.com^inBrowser=1", "A", 2, 0, 0, 0],
+  ];
+
+  let found = expected.map((it) => 0);
+
+  // Add some places to the places database
+  await PlacesTestUtils.addVisits(Services.io.newURI("https://foo.com/some/other/subdirectory"));
+  await PlacesTestUtils.addVisits(Services.io.newURI("ftp://some.subdomain.of.foo.com:8000/some/subdirectory"));
+  await PlacesTestUtils.addVisits(Services.io.newURI("ftp://127.0.0.1:8080"));
+  await PlacesTestUtils.addVisits(Services.io.newURI("https://localhost:8080"));
+
+  // This will force the permission-manager to reload the data.
+  Services.obs.notifyObservers(null, "testonly-reload-permissions-from-disk", "");
+
+  // Force initialization of the nsPermissionManager
+  for (let permission of Services.perms.enumerator) {
+    let isExpected = false;
+
+    expected.forEach((it, i) => {
+      if (permission.principal.origin == it[0] &&
+          permission.type == it[1] &&
+          permission.capability == it[2] &&
+          permission.expireType == it[3] &&
+          permission.expireTime == it[4]) {
+        isExpected = true;
+        found[i]++;
+      }
+    });
+
+    Assert.ok(isExpected,
+              "Permission " + (isExpected ? "should" : "shouldn't") +
+              " be in permission database: " +
+              permission.principal.origin + ", " +
+              permission.type + ", " +
+              permission.capability + ", " +
+              permission.expireType + ", " +
+              permission.expireTime);
+  }
+
+  found.forEach((count, i) => {
+    Assert.ok(count == 1, "Expected count = 1, got count = " + count + " for permission " + expected[i]);
+  });
+
+  // Check to make sure that all of the tables which we care about are present
+  {
+    let db = Services.storage.openDatabase(GetPermissionsFile(profile));
+    Assert.ok(db.tableExists("moz_perms"));
+    Assert.ok(db.tableExists("moz_hosts"));
+    Assert.ok(!db.tableExists("moz_perms_v6"));
+
+    let mozHostsCount = db.createStatement("SELECT count(*) FROM moz_hosts");
+    try {
+      mozHostsCount.executeStep();
+      Assert.equal(mozHostsCount.getInt64(0), 1);
+    } finally {
+      mozHostsCount.finalize();
+    }
+
+    let mozPermsCount = db.createStatement("SELECT count(*) FROM moz_perms");
+    try {
+      mozPermsCount.executeStep();
+      Assert.equal(mozPermsCount.getInt64(0), expected.length);
+    } finally {
+      mozPermsCount.finalize();
+    }
+
+    db.close();
+  }
+});
--- a/extensions/permissions/test/unit/xpcshell.ini
+++ b/extensions/permissions/test/unit/xpcshell.ini
@@ -24,8 +24,9 @@ skip-if = debug == true
 [test_permmanager_matches.js]
 [test_permmanager_migrate_4-7.js]
 [test_permmanager_migrate_5-7a.js]
 [test_permmanager_migrate_5-7b.js]
 [test_permmanager_migrate_6-7a.js]
 [test_permmanager_migrate_6-7b.js]
 [test_permmanager_migrate_4-7_no_history.js]
 [test_permmanager_migrate_7-8.js]
+[test_permmanager_migrate_9-10.js]
--- a/testing/talos/talos/xtalos/xperf_whitelist.json
+++ b/testing/talos/talos/xtalos/xperf_whitelist.json
@@ -459,16 +459,22 @@
     "maxbytes": 196936
   },
   "{profile}\\permissions.sqlite": {
     "mincount": 14,
     "maxcount": 14,
     "minbytes": 4424,
     "maxbytes": 4424
   },
+  "{profile}\\permissions.sqlite-journal": {
+    "mincount": 0,
+    "maxcount": 18,
+    "minbytes": 0,
+    "maxbytes": 7208
+  },
   "{profile}\\pkcs11.txt": {
     "mincount": 0,
     "maxcount": 4,
     "minbytes": 0,
     "maxbytes": 16384
   },
   "{profile}\\places.sqlite": {
     "mincount": 8,