Bug 1165267 - Fix downgrading issue by restoring appId and inBrowserElement columns v3. r=honzab a=sylvestre
authorEthan Tseng <ettseng@mozilla.com>
Fri, 30 Oct 2015 22:42:56 +0800
changeset 305352 168743bc2474e8f6e9228e5fdbae74dc1c0bba34
parent 305351 d02de1b2320dfb3ff45b80d5e5620011a10d375c
child 305353 91a7bd126142aba70a33f6276a3b34dfa4c9499c
push id1001
push userraliiev@mozilla.com
push dateMon, 18 Jan 2016 19:06:03 +0000
treeherdermozilla-release@8b89261f3ac4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershonzab, sylvestre
bugs1165267
milestone44.0a2
Bug 1165267 - Fix downgrading issue by restoring appId and inBrowserElement columns v3. r=honzab a=sylvestre
extensions/cookie/test/unit/test_cookies_sync_failure.js
netwerk/cookie/nsCookieService.cpp
--- a/extensions/cookie/test/unit/test_cookies_sync_failure.js
+++ b/extensions/cookie/test/unit/test_cookies_sync_failure.js
@@ -13,17 +13,17 @@
 // 4) Migration fails. This will have different modes depending on the initial
 //    version:
 //    a) Schema 1: the 'lastAccessed' column already exists.
 //    b) Schema 2: the 'baseDomain' column already exists; or 'baseDomain'
 //       cannot be computed for a particular host.
 //    c) Schema 3: the 'creationTime' column already exists; or the
 //       'moz_uniqueid' index already exists.
 
-var COOKIE_DATABASE_SCHEMA_CURRENT = 6;
+var COOKIE_DATABASE_SCHEMA_CURRENT = 7;
 
 var test_generator = do_run_test();
 
 function run_test() {
   do_test_pending();
   do_run_generator(test_generator);
 }
 
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -46,16 +46,17 @@
 #include "mozilla/storage.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/FileUtils.h"
 #include "mozilla/Telemetry.h"
 #include "nsIAppsService.h"
 #include "mozIApplication.h"
 #include "mozIApplicationClearPrivateDataParams.h"
 #include "nsIConsoleService.h"
+#include "nsVariant.h"
 
 using namespace mozilla;
 using namespace mozilla::net;
 
 // Create key from baseDomain that will access the default cookie namespace.
 // TODO: When we figure out what the API will look like for nsICookieManager{2}
 // on content processes (see bug 777620), change to use the appropriate app
 // namespace.  For now those IDLs aren't supported on child processes.
@@ -69,17 +70,17 @@ using namespace mozilla::net;
 
 static nsCookieService *gCookieService;
 
 // XXX_hack. See bug 178993.
 // This is a hack to hide HttpOnly cookies from older browsers
 #define HTTP_ONLY_PREFIX "#HttpOnly_"
 
 #define COOKIES_FILE "cookies.sqlite"
-#define COOKIES_SCHEMA_VERSION 6
+#define COOKIES_SCHEMA_VERSION 7
 
 // parameter indexes; see EnsureReadDomain, EnsureReadComplete and
 // ReadCookieDBListener::HandleResult
 #define IDX_NAME 0
 #define IDX_VALUE 1
 #define IDX_HOST 2
 #define IDX_PATH 3
 #define IDX_EXPIRY 4
@@ -822,37 +823,96 @@ class ConvertAppIdToOriginAttrsSQLFuncti
   NS_DECL_ISUPPORTS
   NS_DECL_MOZISTORAGEFUNCTION
 };
 
 NS_IMPL_ISUPPORTS(ConvertAppIdToOriginAttrsSQLFunction, mozIStorageFunction);
 
 NS_IMETHODIMP
 ConvertAppIdToOriginAttrsSQLFunction::OnFunctionCall(
-    mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
+  mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
 {
   nsresult rv;
   int32_t appId, inBrowser;
 
   rv = aFunctionArguments->GetInt32(0, &appId);
   NS_ENSURE_SUCCESS(rv, rv);
   rv = aFunctionArguments->GetInt32(1, &inBrowser);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Create an originAttributes object by appId and inBrowserElemnt.
   // Then create the originSuffix string from this object.
   OriginAttributes attrs(appId, (inBrowser ? 1 : 0));
   nsAutoCString suffix;
   attrs.CreateSuffix(suffix);
 
-  nsCOMPtr<nsIWritableVariant> outVar(do_CreateInstance(
-    NS_VARIANT_CONTRACTID, &rv));
+  RefPtr<nsVariant> outVar(new nsVariant());
+  rv = outVar->SetAsAUTF8String(suffix);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  outVar.forget(aResult);
+  return NS_OK;
+}
+
+class SetAppIdFromOriginAttributesSQLFunction final : public mozIStorageFunction
+{
+  ~SetAppIdFromOriginAttributesSQLFunction() {}
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGEFUNCTION
+};
+
+NS_IMPL_ISUPPORTS(SetAppIdFromOriginAttributesSQLFunction, mozIStorageFunction);
+
+NS_IMETHODIMP
+SetAppIdFromOriginAttributesSQLFunction::OnFunctionCall(
+  mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
+{
+  nsresult rv;
+  nsAutoCString suffix;
+  OriginAttributes attrs;
+
+  rv = aFunctionArguments->GetUTF8String(0, suffix);
   NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = outVar->SetAsAUTF8String(suffix);
+  attrs.PopulateFromSuffix(suffix);
+
+  RefPtr<nsVariant> outVar(new nsVariant());
+  rv = outVar->SetAsInt32(attrs.mAppId);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  outVar.forget(aResult);
+  return NS_OK;
+}
+
+class SetInBrowserFromOriginAttributesSQLFunction final :
+  public mozIStorageFunction
+{
+  ~SetInBrowserFromOriginAttributesSQLFunction() {}
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGEFUNCTION
+};
+
+NS_IMPL_ISUPPORTS(SetInBrowserFromOriginAttributesSQLFunction,
+                  mozIStorageFunction);
+
+NS_IMETHODIMP
+SetInBrowserFromOriginAttributesSQLFunction::OnFunctionCall(
+  mozIStorageValueArray* aFunctionArguments, nsIVariant** aResult)
+{
+  nsresult rv;
+  nsAutoCString suffix;
+  OriginAttributes attrs;
+
+  rv = aFunctionArguments->GetUTF8String(0, suffix);
+  NS_ENSURE_SUCCESS(rv, rv);
+  attrs.PopulateFromSuffix(suffix);
+
+  RefPtr<nsVariant> outVar(new nsVariant());
+  rv = outVar->SetAsInt32(attrs.mInBrowser);
   NS_ENSURE_SUCCESS(rv, rv);
 
   outVar.forget(aResult);
   return NS_OK;
 }
 
 } // namespace
 
@@ -1142,17 +1202,17 @@ nsCookieService::TryInitDB(bool aRecreat
         COOKIE_LOGSTRING(LogLevel::Debug,
           ("Upgraded database to schema version 5"));
       }
       // Fall through to the next upgrade.
 
     case 5:
       {
         // Change in the version: Replace the columns |appId| and
-        // |isBrowserElement| by a single column |originAttributes|.
+        // |inBrowserElement| by a single column |originAttributes|.
         //
         // Why we made this change: FxOS new security model (NSec) encapsulates
         // "appId/inBrowser" in nsIPrincipal::originAttributes to make it easier
         // to modify the contents of this structure in the future.
         //
         // We do the migration in several steps:
         // 1. Rename the old table.
         // 2. Create a new table.
@@ -1174,41 +1234,98 @@ nsCookieService::TryInitDB(bool aRecreat
         NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
 
         // Copy data from old table without the two deprecated columns appId and
         // inBrowserElement.
         nsCOMPtr<mozIStorageFunction>
           convertToOriginAttrs(new ConvertAppIdToOriginAttrsSQLFunction());
         NS_ENSURE_TRUE(convertToOriginAttrs, RESULT_RETRY);
 
-        rv = mDefaultDBState->dbConn->CreateFunction(
-             NS_LITERAL_CSTRING("CONVERT_TO_ORIGIN_ATTRIBUTES"), 2,
-             convertToOriginAttrs);
+        NS_NAMED_LITERAL_CSTRING(convertToOriginAttrsName,
+                                 "CONVERT_TO_ORIGIN_ATTRIBUTES");
+
+        rv = mDefaultDBState->dbConn->CreateFunction(convertToOriginAttrsName,
+                                                     2, convertToOriginAttrs);
         NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
 
         rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
           "INSERT INTO moz_cookies "
           "(baseDomain, originAttributes, name, value, host, path, expiry,"
           " lastAccessed, creationTime, isSecure, isHttpOnly) "
           "SELECT baseDomain, "
           " CONVERT_TO_ORIGIN_ATTRIBUTES(appId, inBrowserElement),"
           " name, value, host, path, expiry, lastAccessed, creationTime, "
           " isSecure, isHttpOnly "
           "FROM moz_cookies_old"));
         NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
 
+        rv = mDefaultDBState->dbConn->RemoveFunction(convertToOriginAttrsName);
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
         // Drop old table
         rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
              "DROP TABLE moz_cookies_old"));
         NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
 
         COOKIE_LOGSTRING(LogLevel::Debug,
           ("Upgraded database to schema version 6"));
       }
 
+    case 6:
+      {
+        // We made a mistake in schema version 6. We cannot remove expected
+        // columns of any version (checked in the default case) from cookie
+        // database, because doing this would destroy the possibility of
+        // downgrading database.
+        //
+        // This version simply restores appId and inBrowserElement columns in
+        // order to fix downgrading issue even though these two columns are no
+        // longer used in the latest schema.
+        rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          "ALTER TABLE moz_cookies ADD appId INTEGER DEFAULT 0;"));
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
+        rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          "ALTER TABLE moz_cookies ADD inBrowserElement INTEGER DEFAULT 0;"));
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
+        // Compute and populate the values of appId and inBrwoserElement from
+        // originAttributes.
+        nsCOMPtr<mozIStorageFunction>
+          setAppId(new SetAppIdFromOriginAttributesSQLFunction());
+        NS_ENSURE_TRUE(setAppId, RESULT_RETRY);
+
+        NS_NAMED_LITERAL_CSTRING(setAppIdName, "SET_APP_ID");
+
+        rv = mDefaultDBState->dbConn->CreateFunction(setAppIdName, 1, setAppId);
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
+        nsCOMPtr<mozIStorageFunction>
+          setInBrowser(new SetInBrowserFromOriginAttributesSQLFunction());
+        NS_ENSURE_TRUE(setInBrowser, RESULT_RETRY);
+
+        NS_NAMED_LITERAL_CSTRING(setInBrowserName, "SET_IN_BROWSER");
+
+        rv = mDefaultDBState->dbConn->CreateFunction(setInBrowserName, 1,
+                                                     setInBrowser);
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
+        rv = mDefaultDBState->dbConn->ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          "UPDATE moz_cookies SET appId = SET_APP_ID(originAttributes), "
+          "inBrowserElement = SET_IN_BROWSER(originAttributes);"
+        ));
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
+        rv = mDefaultDBState->dbConn->RemoveFunction(setAppIdName);
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+
+        rv = mDefaultDBState->dbConn->RemoveFunction(setInBrowserName);
+        NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
+      }
+
       // No more upgrades. Update the schema version.
       rv = mDefaultDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION);
       NS_ENSURE_SUCCESS(rv, RESULT_RETRY);
 
     case COOKIES_SCHEMA_VERSION:
       break;
 
     case 0: