bug 545625 - "back-fork ifdef'd mozStorage of bug 507414 into comm-central or mozilla-1.9.2 for TB 3.1 release". transplant bug 507414 patch v5 to comm-central/storage-backport. that patch is under review by sdwilsh for mozilla-central landing but is believed good per mozilla-central try builds and local tests. comm-central landing: rs=Standard8.
authorAndrew Sutherland <asutherland@asutherland.org>
Wed, 10 Mar 2010 09:11:42 -0800
changeset 5128 b305fcdd06289f37e525aeadc8be6b602e2234c6
parent 5127 715859e3dc66d59393dc5902334910fe19696047
child 5129 4be99c0f603648378fa0ebd618433cb41a7690af
push idunknown
push userunknown
push dateunknown
reviewersStandard8
bugs545625, 507414
bug 545625 - "back-fork ifdef'd mozStorage of bug 507414 into comm-central or mozilla-1.9.2 for TB 3.1 release". transplant bug 507414 patch v5 to comm-central/storage-backport. that patch is under review by sdwilsh for mozilla-central landing but is believed good per mozilla-central try builds and local tests. comm-central landing: rs=Standard8.
storage-backport/Makefile.in
storage-backport/build/Makefile.in
storage-backport/build/mozStorageCID.h
storage-backport/build/mozStorageModule.cpp
storage-backport/public/Makefile.in
storage-backport/public/mozIStorageAggregateFunction.idl
storage-backport/public/mozIStorageAsyncStatement.idl
storage-backport/public/mozIStorageBaseStatement.idl
storage-backport/public/mozIStorageBindingParams.idl
storage-backport/public/mozIStorageBindingParamsArray.idl
storage-backport/public/mozIStorageCompletionCallback.idl
storage-backport/public/mozIStorageConnection.idl
storage-backport/public/mozIStorageError.idl
storage-backport/public/mozIStorageFunction.idl
storage-backport/public/mozIStoragePendingStatement.idl
storage-backport/public/mozIStorageProgressHandler.idl
storage-backport/public/mozIStorageResultSet.idl
storage-backport/public/mozIStorageRow.idl
storage-backport/public/mozIStorageService.idl
storage-backport/public/mozIStorageStatement.idl
storage-backport/public/mozIStorageStatementCallback.idl
storage-backport/public/mozIStorageStatementWrapper.idl
storage-backport/public/mozIStorageValueArray.idl
storage-backport/public/mozStorage.h
storage-backport/public/mozStorageHelper.h
storage-backport/public/storage.h
storage-backport/src/IStorageBindingParamsInternal.h
storage-backport/src/Makefile.in
storage-backport/src/SQLCollations.cpp
storage-backport/src/SQLCollations.h
storage-backport/src/SQLiteMutex.h
storage-backport/src/StorageBaseStatementInternal.cpp
storage-backport/src/StorageBaseStatementInternal.h
storage-backport/src/Variant.h
storage-backport/src/Variant_inl.h
storage-backport/src/mozStorageArgValueArray.cpp
storage-backport/src/mozStorageArgValueArray.h
storage-backport/src/mozStorageAsyncStatement.cpp
storage-backport/src/mozStorageAsyncStatement.h
storage-backport/src/mozStorageAsyncStatementExecution.cpp
storage-backport/src/mozStorageAsyncStatementExecution.h
storage-backport/src/mozStorageAsyncStatementJSHelper.cpp
storage-backport/src/mozStorageAsyncStatementJSHelper.h
storage-backport/src/mozStorageAsyncStatementParams.cpp
storage-backport/src/mozStorageAsyncStatementParams.h
storage-backport/src/mozStorageBindingParams.cpp
storage-backport/src/mozStorageBindingParams.h
storage-backport/src/mozStorageBindingParamsArray.cpp
storage-backport/src/mozStorageBindingParamsArray.h
storage-backport/src/mozStorageConnection.cpp
storage-backport/src/mozStorageConnection.h
storage-backport/src/mozStorageError.cpp
storage-backport/src/mozStorageError.h
storage-backport/src/mozStoragePrivateHelpers.cpp
storage-backport/src/mozStoragePrivateHelpers.h
storage-backport/src/mozStorageResultSet.cpp
storage-backport/src/mozStorageResultSet.h
storage-backport/src/mozStorageRow.cpp
storage-backport/src/mozStorageRow.h
storage-backport/src/mozStorageSQLFunctions.cpp
storage-backport/src/mozStorageSQLFunctions.h
storage-backport/src/mozStorageService.cpp
storage-backport/src/mozStorageService.h
storage-backport/src/mozStorageStatement.cpp
storage-backport/src/mozStorageStatement.h
storage-backport/src/mozStorageStatementData.h
storage-backport/src/mozStorageStatementJSHelper.cpp
storage-backport/src/mozStorageStatementJSHelper.h
storage-backport/src/mozStorageStatementParams.cpp
storage-backport/src/mozStorageStatementParams.h
storage-backport/src/mozStorageStatementRow.cpp
storage-backport/src/mozStorageStatementRow.h
storage-backport/src/mozStorageStatementWrapper.cpp
storage-backport/src/mozStorageStatementWrapper.h
storage-backport/src/variantToSQLiteT_impl.h
storage-backport/style.txt
storage-backport/test/Makefile.in
storage-backport/test/storage_test_harness.h
storage-backport/test/storage_test_harness_tail.h
storage-backport/test/test_binding_params.cpp
storage-backport/test/test_deadlock_detector.cpp
storage-backport/test/test_mutex.cpp
storage-backport/test/test_statement_scoper.cpp
storage-backport/test/test_transaction_helper.cpp
storage-backport/test/test_true_async.cpp
storage-backport/test/unit/corruptDB.sqlite
storage-backport/test/unit/head_storage.js
storage-backport/test/unit/locale_collation.txt
storage-backport/test/unit/test_bug-365166.js
storage-backport/test/unit/test_bug-393952.js
storage-backport/test/unit/test_bug-429521.js
storage-backport/test/unit/test_bug-444233.js
storage-backport/test/unit/test_connection_executeAsync.js
storage-backport/test/unit/test_js_helpers_enumerate.js
storage-backport/test/unit/test_js_helpers_prototype_chain_safe.js
storage-backport/test/unit/test_levenshtein.js
storage-backport/test/unit/test_like.js
storage-backport/test/unit/test_like_escape.js
storage-backport/test/unit/test_locale_collation.js
storage-backport/test/unit/test_sqlite_secure_delete.js
storage-backport/test/unit/test_statement_executeAsync.js
storage-backport/test/unit/test_statement_wrapper_automatically.js
storage-backport/test/unit/test_storage_aggregates.js
storage-backport/test/unit/test_storage_connection.js
storage-backport/test/unit/test_storage_fulltextindex.js
storage-backport/test/unit/test_storage_function.js
storage-backport/test/unit/test_storage_progresshandler.js
storage-backport/test/unit/test_storage_service.js
storage-backport/test/unit/test_storage_service_unshared.js
storage-backport/test/unit/test_storage_statement.js
storage-backport/test/unit/test_storage_statement_wrapper.js
storage-backport/test/unit/test_storage_value_array.js
storage-backport/test/unit/test_unicode.js
new file mode 100644
--- /dev/null
+++ b/storage-backport/Makefile.in
@@ -0,0 +1,62 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Oracle Corporation code.
+#
+# The Initial Developer of the Original Code is
+#   Oracle Corporation
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH		= ..
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= storage
+
+ifndef MOZ_NATIVE_SQLITE
+DIRS		= ../db/sqlite3/src
+endif
+
+DIRS		+= public \
+		   src \
+		   build \
+		   $(NULL)
+
+ifdef ENABLE_TESTS
+TOOL_DIRS += test
+endif
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/storage-backport/build/Makefile.in
@@ -0,0 +1,77 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Oracle Corporation code.
+#
+# The Initial Developer of the Original Code is
+#   Oracle Corporation
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+#   Shawn Wilsher <me@shawnwilsher.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH=../..
+topsrcdir=@top_srcdir@
+srcdir=@srcdir@
+VPATH=@srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE		= storage
+LIBRARY_NAME = storagecomps
+SHORT_LIBNAME = strgcmps
+EXPORT_LIBRARY = 1
+IS_COMPONENT = 1
+MODULE_NAME = mozStorageModule
+LIBXUL_LIBRARY = 1
+
+
+EXPORTS = mozStorageCID.h
+
+CPPSRCS = mozStorageModule.cpp
+
+LOCAL_INCLUDES = \
+	$(SQLITE_CFLAGS) \
+	-I$(srcdir)/../src
+
+SHARED_LIBRARY_LIBS = \
+	../src/$(LIB_PREFIX)storage_s.$(LIB_SUFFIX) \
+	$(NULL)
+
+EXTRA_DSO_LDOPTS += \
+	$(LIBS_DIR) \
+	$(SQLITE_LIBS) \
+	$(MOZ_UNICHARUTIL_LIBS) \
+	$(MOZ_COMPONENT_LIBS) \
+	$(MOZ_JS_LIBS) \
+	$(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
new file mode 100644
--- /dev/null
+++ b/storage-backport/build/mozStorageCID.h
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _MOZSTORAGECID_H_
+#define _MOZSTORAGECID_H_
+
+#define MOZ_STORAGE_CONTRACTID_PREFIX "@mozilla.org/storage"
+
+
+/* b71a1f84-3a70-4d37-a348-f1ba0e27eead */
+#define MOZ_STORAGE_CONNECTION_CID \
+{ 0xb71a1f84, 0x3a70, 0x4d37, {0xa3, 0x48, 0xf1, 0xba, 0x0e, 0x27, 0xee, 0xad} }
+
+#define MOZ_STORAGE_CONNECTION_CONTRACTID MOZ_STORAGE_CONTRACTID_PREFIX "/connection;1"
+
+/* bbbb1d61-438f-4436-92ed-8308e5830fb0 */
+#define MOZ_STORAGE_SERVICE_CID \
+{ 0xbbbb1d61, 0x438f, 0x4436, {0x92, 0xed, 0x83, 0x08, 0xe5, 0x83, 0x0f, 0xb0} }
+
+#define MOZ_STORAGE_SERVICE_CONTRACTID MOZ_STORAGE_CONTRACTID_PREFIX "/service;1"
+
+/* dab3a846-3a59-4fc2-9745-c6ff48776f00 */
+#define MOZ_STORAGE_STATEMENT_WRAPPER_CID \
+{ 0xdab3a846, 0x3a59, 0x4fc2, {0x97, 0x45, 0xc6, 0xff, 0x48, 0x77, 0x6f, 0x00} }
+
+#define MOZ_STORAGE_STATEMENT_WRAPPER_CONTRACTID MOZ_STORAGE_CONTRACTID_PREFIX "/statement-wrapper;1"
+
+#endif /* _MOZSTORAGECID_H_ */
new file mode 100644
--- /dev/null
+++ b/storage-backport/build/mozStorageModule.cpp
@@ -0,0 +1,76 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsCOMPtr.h"
+#include "nsIGenericFactory.h"
+#include "nsIModule.h"
+
+#include "mozStorageService.h"
+#include "mozStorageConnection.h"
+#include "mozStorageStatementWrapper.h"
+
+#include "mozStorageCID.h"
+
+namespace mozilla {
+namespace storage {
+
+NS_GENERIC_FACTORY_SINGLETON_CONSTRUCTOR(Service,
+                                         Service::getSingleton)
+NS_GENERIC_FACTORY_CONSTRUCTOR(StatementWrapper)
+
+
+} // namespace storage
+} // namespace mozilla
+
+static const nsModuleComponentInfo components[] =
+{
+    { "Unified Data Store Service",
+      MOZ_STORAGE_SERVICE_CID,
+      MOZ_STORAGE_SERVICE_CONTRACTID,
+      mozilla::storage::ServiceConstructor
+    },
+
+    { "Unified Data Store Scriptable Statement Wrapper",
+      MOZ_STORAGE_STATEMENT_WRAPPER_CID,
+      MOZ_STORAGE_STATEMENT_WRAPPER_CONTRACTID,
+      mozilla::storage::StatementWrapperConstructor
+    }
+};
+
+NS_IMPL_NSGETMODULE(mozStorageModule, components)
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/Makefile.in
@@ -0,0 +1,81 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Oracle Corporation code.
+#
+# The Initial Developer of the Original Code is
+#   Oracle Corporation
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+#   Lev Serebryakov <lev@serebryakov.spb.ru>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH   = ../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH   = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE       = storage
+XPIDL_MODULE = storage
+GRE_MODULE   = 1
+
+XPIDLSRCS = \
+	mozIStorageService.idl \
+	mozIStorageConnection.idl \
+	mozIStorageAggregateFunction.idl \
+	mozIStorageFunction.idl \
+	mozIStorageProgressHandler.idl \
+	mozIStorageStatement.idl \
+	mozIStorageStatementWrapper.idl \
+	mozIStorageValueArray.idl \
+	mozIStorageResultSet.idl \
+	mozIStorageRow.idl \
+  mozIStorageError.idl \
+  mozIStorageStatementCallback.idl \
+  mozIStoragePendingStatement.idl \
+  mozIStorageBindingParamsArray.idl \
+  mozIStorageBindingParams.idl \
+  mozIStorageCompletionCallback.idl \
+  mozIStorageBaseStatement.idl \
+  mozIStorageAsyncStatement.idl \
+	$(NULL)
+
+EXPORTS_NAMESPACES = mozilla
+
+EXPORTS = \
+	mozStorageHelper.h \
+	mozStorage.h \
+	$(NULL)
+
+EXPORTS_mozilla = storage.h
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageAggregateFunction.idl
@@ -0,0 +1,70 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Storage Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Lev Serebryakov <lev@serebryakov.spb.ru>
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface mozIStorageConnection;
+interface mozIStorageValueArray;
+interface nsIArray;
+interface nsIVariant;
+
+/**
+ * mozIStorageAggregateFunction represents aggregate SQL function.
+ * Common examples of aggregate functions are SUM() and COUNT().
+ *
+ * An aggregate function calculates one result for a given set of data, where
+ * a set of data is a group of tuples. There can be one group
+ * per request or many of them, if GROUP BY clause is used or not.
+ */
+[scriptable, uuid(763217b7-3123-11da-918d-000347412e16)]
+interface mozIStorageAggregateFunction : nsISupports {
+  /**
+   * onStep is called when next value should be passed to
+   * a custom function.
+   * 
+   * @param aFunctionArguments    The arguments passed in to the function
+   */
+  void onStep(in mozIStorageValueArray aFunctionArguments);
+
+  /**
+   * Called when all tuples in a group have been processed and the engine
+   * needs the aggregate function's value.
+   *
+   * @returns aggregate result as Variant.
+   */
+  nsIVariant onFinal();
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageAsyncStatement.idl
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozIStorageBaseStatement.idl"
+
+/**
+ * An asynchronous SQL statement.  This differs from mozIStorageStatement by
+ * only being usable for asynchronous execution.  (mozIStorageStatement can
+ * be used for both synchronous and asynchronous purposes.)  This specialization
+ * for asynchronous operation allows us to avoid needing to acquire
+ * synchronization primitives also used by the asynchronous execution thread.
+ * In contrast, mozIStorageStatement may need to acquire the primitives and
+ * consequently can cause the main thread to lock for extended intervals while
+ * the asynchronous thread performs some long-running operation.
+ */
+[scriptable, uuid(2400f64d-2cb3-49a9-b01e-f03cacb8aa6e)]
+interface mozIStorageAsyncStatement : mozIStorageBaseStatement {
+  /*
+   * 'params' provides a magic JS helper that lets you assign parameters by
+   * name.  Unlike the helper on mozIStorageStatement, you cannot enumerate
+   * in order to find out what parameters are legal.
+   *
+   * This does not work for BLOBs.  You must use an explicit binding API for
+   * that.
+   *
+   * example:
+   *  stmt.params.foo = 1;
+   *  stmt.params["bar"] = 2;
+   *  let argName = "baz";
+   *  stmt.params[argName] = 3;
+   *
+   * readonly attribute nsIMagic params;
+   */
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageBaseStatement.idl
@@ -0,0 +1,179 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 et
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozStorage.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+#include "mozIStorageBindingParams.idl"
+
+interface mozIStorageConnection;
+interface mozIStorageStatementCallback;
+interface mozIStoragePendingStatement;
+interface mozIStorageBindingParams;
+interface mozIStorageBindingParamsArray;
+
+/**
+ * The base interface for both pure asynchronous storage statements 
+ * (mozIStorageAsyncStatement) and 'classic' storage statements
+ * (mozIStorageStatement) that can be used for both synchronous and asynchronous
+ * purposes.
+ */
+[scriptable, uuid(da2ec336-fbbb-4ba1-9778-8c9825980d01)]
+interface mozIStorageBaseStatement : mozIStorageBindingParams {
+  /**
+   * Finalizes a statement so you can successfully close a database connection.
+   * Once a statement has been finalized it can no longer be used for any
+   * purpose.
+   * 
+   * Statements are implicitly finalized when their reference counts hits zero.
+   * If you are a native (C++) caller this is accomplished by setting all of
+   * your nsCOMPtr instances to be NULL.  If you are operating from JavaScript
+   * code then you cannot rely on this behavior because of the involvement of
+   * garbage collection.
+   *
+   * When finalizing an asynchronous statement you do not need to worry about
+   * whether the statement has actually been executed by the asynchronous
+   * thread; you just need to call finalize after your last call to executeAsync
+   * involving the statement.  However, you do need to use asyncClose instead of
+   * close on the connection if any statements have been used asynchronously.
+   */
+  void finalize();
+
+  /**
+   * Bind the given value at the given numeric index.
+   *
+   * @param aParamIndex
+   *        0-based index, 0 corresponding to the first numbered argument or
+   *        "?1".
+   * @param aValue Argument value.
+   * @{
+   */
+  [deprecated] void bindUTF8StringParameter(in unsigned long aParamIndex,
+                                            in AUTF8String aValue);
+  [deprecated] void bindStringParameter(in unsigned long aParamIndex,
+                                        in AString aValue);
+  [deprecated] void bindDoubleParameter(in unsigned long aParamIndex,
+                                        in double aValue);
+  [deprecated] void bindInt32Parameter(in unsigned long aParamIndex,
+                                       in long aValue);
+  [deprecated] void bindInt64Parameter(in unsigned long aParamIndex,
+                                       in long long aValue);
+  [deprecated] void bindNullParameter(in unsigned long aParamIndex);
+  [deprecated] void bindBlobParameter(
+    in unsigned long aParamIndex,
+    [array,const,size_is(aValueSize)] in octet aValue,
+    in unsigned long aValueSize);
+  /**@}*/
+
+  /**
+   * Binds the array of parameters to the statement.  When executeAsync is
+   * called, all the parameters in aParameters are bound and then executed.
+   *
+   * @param aParameters
+   *        The array of parameters to bind to the statement upon execution.
+   *
+   * @note This is only works on statements being used asynchronously.
+   */
+  void bindParameters(in mozIStorageBindingParamsArray aParameters);
+
+  /**
+   * Creates a new mozIStorageBindingParamsArray that can be used to bind
+   * multiple sets of data to a statement with bindParameters.
+   *
+   * @return a mozIStorageBindingParamsArray that multiple sets of parameters
+   *         can be bound to.
+   *
+   * @note This is only useful for statements being used asynchronously.
+   */
+  mozIStorageBindingParamsArray newBindingParamsArray();
+
+  /**
+   * Execute a query asynchronously using any currently bound parameters.  This
+   * statement can be reused immediately, and reset does not need to be called.
+   *
+   * @note If you have any custom defined functions, they must be re-entrant
+   *       since they can be called on multiple threads.
+   *
+   * @param aCallback [optional]
+   *        The callback object that will be notified of progress, errors, and
+   *        completion.
+   * @return an object that can be used to cancel the statements execution.
+   */
+  mozIStoragePendingStatement executeAsync(
+    [optional] in mozIStorageStatementCallback aCallback
+  );
+
+  /**
+   * The statement is not usable, either because it failed to initialize or
+   * was explicitly finalized.
+   */
+  const long MOZ_STORAGE_STATEMENT_INVALID = 0;
+  /**
+   * The statement is usable.
+   */
+  const long MOZ_STORAGE_STATEMENT_READY = 1;
+  /**
+   * Indicates that the statement is executing and the row getters may be used.
+   *
+   * @note This is only relevant for mozIStorageStatement instances being used
+   *       in a synchronous fashion.
+   */
+  const long MOZ_STORAGE_STATEMENT_EXECUTING = 2;
+
+  /**
+   * Find out whether the statement is usable (has not been finalized).
+   */
+  readonly attribute long state;
+
+  /**
+   * Escape a string for SQL LIKE search.
+   *
+   * @note Consumers will have to use same escape char when doing statements
+   *       such as:   ...LIKE '?1' ESCAPE '/'...
+   *
+   * @param aValue
+   *        The string to escape for SQL LIKE.
+   * @param aEscapeChar
+   *        The escape character.
+   * @return an AString of an escaped version of aValue
+   *         (%, _ and the escape char are escaped with the escape char)
+   *         For example, we will convert "foo/bar_baz%20cheese" 
+   *         into "foo//bar/_baz/%20cheese" (if the escape char is '/').
+   */
+  AString escapeStringForLIKE(in AString aValue, in wchar aEscapeChar);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageBindingParams.idl
@@ -0,0 +1,95 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 et
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface nsIVariant;
+
+[scriptable, uuid(a8d4827c-641c-45e3-a9ea-493570b4106b)]
+interface mozIStorageBindingParams : nsISupports {
+  /**
+   * Binds aValue to the parameter with the name aName.
+   *
+   * @param aName
+   *        The name of the parameter to bind aValue to.
+   * @param aValue
+   *        The value to bind.
+   */
+   void bindByName(in AUTF8String aName,
+                   in nsIVariant aValue);
+   [noscript] void bindUTF8StringByName(in AUTF8String aName,
+                                        in AUTF8String aValue);
+   [noscript] void bindStringByName(in AUTF8String aName,
+                                    in AString aValue);
+   [noscript] void bindDoubleByName(in AUTF8String aName,
+                                    in double aValue);
+   [noscript] void bindInt32ByName(in AUTF8String aName,
+                                   in long aValue);
+   [noscript] void bindInt64ByName(in AUTF8String aName,
+                                   in long long aValue);
+   [noscript] void bindNullByName(in AUTF8String aName);
+   void bindBlobByName(in AUTF8String aName,
+                       [array, const, size_is(aValueSize)] in octet aValue,
+                       in unsigned long aValueSize);
+
+   /**
+    * Binds aValue to the parameter with the index aIndex.
+    *
+    * @param aIndex
+    *        The zero-based index of the parameter to bind aValue to.
+    * @param aValue
+    *        The value to bind.
+    */
+   void bindByIndex(in unsigned long aIndex,
+                    in nsIVariant aValue);
+   [noscript] void bindUTF8StringByIndex(in unsigned long aIndex,
+                                         in AUTF8String aValue);
+   [noscript] void bindStringByIndex(in unsigned long aIndex,
+                                     in AString aValue);
+   [noscript] void bindDoubleByIndex(in unsigned long aIndex,
+                                     in double aValue);
+   [noscript] void bindInt32ByIndex(in unsigned long aIndex,
+                                    in long aValue);
+   [noscript] void bindInt64ByIndex(in unsigned long aIndex,
+                                    in long long aValue);
+   [noscript] void bindNullByIndex(in unsigned long aIndex);
+   void bindBlobByIndex(in unsigned long aIndex,
+                        [array, const, size_is(aValueSize)] in octet aValue,
+                        in unsigned long aValueSize);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageBindingParamsArray.idl
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 et
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface mozIStorageBindingParams;
+
+[scriptable, uuid(e676e1a3-1dc6-4802-ac03-291fa9de7f93)]
+interface mozIStorageBindingParamsArray : nsISupports {
+  /**
+   * Creates a new mozIStorageBindingParams object that can be added to this
+   * array.
+   *
+   * @returns a mozIStorageBindingParams object that can be used to specify
+   *          parameters that need to be bound.
+   */
+  mozIStorageBindingParams newBindingParams();
+
+  /**
+   * Adds the parameters to the end of this array.
+   *
+   * @param aParameters
+   *        The parameters to add to this array.
+   */
+  void addParams(in mozIStorageBindingParams aParameters);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageCompletionCallback.idl
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+  vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable,function, uuid(0bfee0c4-2c24-400e-b18e-b5bb41a032c8)]
+interface mozIStorageCompletionCallback : nsISupports {
+  /**
+   * Indicates that the event this callback was passed in for has completed.
+   */
+  void complete();
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageConnection.idl
@@ -0,0 +1,334 @@
+/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Brett Wilson <brettw@gmail.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *   Lev Serebryakov <lev@serebryakov.spb.ru>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface mozIStorageAggregateFunction;
+interface mozIStorageCompletionCallback;
+interface mozIStorageFunction;
+interface mozIStorageProgressHandler;
+interface mozIStorageBaseStatement;
+interface mozIStorageStatement;
+interface mozIStorageAsyncStatement;
+interface mozIStorageStatementCallback;
+interface mozIStoragePendingStatement;
+interface nsIFile;
+
+/**
+ * mozIStorageConnection represents a database connection attached to
+ * a specific file or to the in-memory data storage.  It is the
+ * primary interface for interacting with a database, including
+ * creating prepared statements, executing SQL, and examining database
+ * errors.
+ *
+ * @threadsafe
+ */
+[scriptable, uuid(32b43ec6-e905-4070-9cfe-370c45f7c1bf)]
+interface mozIStorageConnection : nsISupports {
+  //////////////////////////////////////////////////////////////////////////////
+  //// Initialization and status
+
+  /**
+   * Closes a database connection.  Callers must finalize all statements created
+   * for this connection prior to calling this method.  It is illegal to use
+   * call this method if any asynchronous statements have been executed on this
+   * connection.
+   *
+   * @throws NS_ERROR_UNEXPECTED
+   *         If any statement has been executed asynchronously on this object.
+   * @throws NS_ERROR_UNEXPECTED
+   *         If is called on a thread other than the one that opened it.
+   */
+  void close();
+
+  /**
+   * Asynchronously closes a database connection, allowing all pending
+   * asynchronous statements to complete first.
+   *
+   * @param aCallback [optional]
+   *        A callback that will be notified when the close is completed.
+   *
+   * @throws NS_ERROR_UNEXPECTED
+   *         If is called on a thread other than the one that opened it.
+   */
+  void asyncClose([optional] in mozIStorageCompletionCallback aCallback);
+
+  /**
+   * Indicates if the connection is open and ready to use.  This will be false
+   * if the connection failed to open, or it has been closed.
+   */
+  readonly attribute boolean connectionReady;
+
+  /**
+   * The current database nsIFile.  Null if the database
+   * connection refers to an in-memory database.
+   */
+  readonly attribute nsIFile databaseFile;
+
+  /**
+   * lastInsertRowID returns the row ID from the last INSERT
+   * operation.
+   */
+  readonly attribute long long lastInsertRowID;
+
+  /**
+   * The last error SQLite error code.
+   */
+  readonly attribute long lastError;
+
+  /**
+   * The last SQLite error as a string (in english, straight from the
+   * sqlite library).
+   */
+  readonly attribute AUTF8String lastErrorString;
+
+  /**
+   * The schema version of the database.  This should not be used until the 
+   * database is ready.  The schema will be reported as zero if it is not set.
+   */
+  attribute long schemaVersion;
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Statement creation
+
+  /**
+   * Create a mozIStorageStatement for the given SQL expression.  The
+   * expression may use ? to indicate sequential numbered arguments,
+   * ?1, ?2 etc. to indicate specific numbered arguments or :name and 
+   * $var to indicate named arguments.
+   *
+   * @param aSQLStatement
+   *        The SQL statement to execute.
+   * @return a new mozIStorageStatement
+   */
+  mozIStorageStatement createStatement(in AUTF8String aSQLStatement);
+
+  /**
+   * Create an asynchronous statement (mozIStorageAsyncStatement) for the given
+   * SQL expression.  An asynchronous statement can only be used to dispatch
+   * asynchronous requests to the asynchronous execution thread and cannot be
+   * used to take any synchronous actions on the database.
+   *
+   * The expression may use ? to indicate sequential numbered arguments,
+   * ?1, ?2 etc. to indicate specific numbered arguments or :name and
+   * $var to indicate named arguments.
+   *
+   * @param aSQLStatement
+   *        The SQL statement to execute.
+   * @return a new mozIStorageAsyncStatement
+   */
+  mozIStorageAsyncStatement createAsyncStatement(in AUTF8String aSQLStatement);
+
+  /**
+   * Execute a SQL expression, expecting no arguments.
+   *
+   * @param aSQLStatement  The SQL statement to execute
+   */
+  void executeSimpleSQL(in AUTF8String aSQLStatement);
+
+  /**
+   * Execute an array of queries created with this connection asynchronously
+   * using any currently bound parameters.  The statements are ran wrapped in a
+   * transaction.  These statements can be reused immediately, and reset does
+   * not need to be called.
+   *
+   * Note:  If you have any custom defined functions, they must be re-entrant
+   *        since they can be called on multiple threads.
+   *
+   * @param aStatements
+   *        The array of statements to execute asynchronously, in the order they
+   *        are given in the array.
+   * @param aNumStatements
+   *        The number of statements in aStatements.
+   * @param aCallback [optional]
+   *        The callback object that will be notified of progress, errors, and
+   *        completion.
+   * @return an object that can be used to cancel the statements execution.
+   */
+  mozIStoragePendingStatement executeAsync(
+    [array, size_is(aNumStatements)] in mozIStorageBaseStatement aStatements,
+    in unsigned long aNumStatements,
+    [optional] in mozIStorageStatementCallback aCallback
+  );
+
+  /**
+   * Check if the given table exists.
+   *
+   * @param aTableName
+   *        The table to check
+   * @return TRUE if table exists, FALSE otherwise.
+   */
+  boolean tableExists(in AUTF8String aTableName);
+
+  /**
+   * Check if the given index exists.
+   *
+   * @param aIndexName   The index to check
+   * @return TRUE if the index exists, FALSE otherwise.
+   */
+  boolean indexExists(in AUTF8String aIndexName);
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Transactions
+
+  /**
+   * Returns true if a transaction is active on this connection.
+   */
+  readonly attribute boolean transactionInProgress;
+
+  /**
+   * Begin a new transaction.  sqlite default transactions are deferred.
+   * If a transaction is active, throws an error.
+   */
+  void beginTransaction();
+
+  /**
+   * Begins a new transaction with the given type.
+   */
+  const PRInt32 TRANSACTION_DEFERRED = 0;
+  const PRInt32 TRANSACTION_IMMEDIATE = 1;
+  const PRInt32 TRANSACTION_EXCLUSIVE = 2;
+  void beginTransactionAs(in PRInt32 transactionType);
+
+  /**
+   * Commits the current transaction.  If no transaction is active,
+   * @throws NS_ERROR_STORAGE_NO_TRANSACTION.
+   */
+  void commitTransaction();
+
+  /**
+   * Rolls back the current transaction.  If no transaction is active,
+   * @throws NS_ERROR_STORAGE_NO_TRANSACTION.
+   */
+  void rollbackTransaction();
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Tables
+
+  /**
+   * Create the table with the given name and schema.
+   *
+   * If the table already exists, NS_ERROR_FAILURE is thrown.
+   * (XXX at some point in the future it will check if the schema is
+   * the same as what is specified, but that doesn't happen currently.)
+   *
+   * @param aTableName
+   *        The table name to be created, consisting of [A-Za-z0-9_], and
+   *        beginning with a letter.
+   * @param aTableSchema
+   *        The schema of the table; what would normally go between the parens
+   *        in a CREATE TABLE statement: e.g., "foo  INTEGER, bar STRING".
+   *
+   * @throws NS_ERROR_FAILURE if the table already exists or could not be
+   *         created for any other reason.
+   */
+  void createTable(in string aTableName,
+                   in string aTableSchema);
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Functions
+
+  /**
+   * Create a new SQL function.  If you use your connection on multiple threads,
+   * your function needs to be threadsafe, or it should only be called on one
+   * thread.
+   *
+   * @param aFunctionName
+   *        The name of function to create, as seen in SQL.
+   * @param aNumArguments
+   *        The number of arguments the function takes. Pass -1 for
+   *        variable-argument functions.
+   * @param aFunction
+   *        The instance of mozIStorageFunction, which implements the function
+   *        in question.
+   */
+  void createFunction(in AUTF8String aFunctionName,
+                      in long aNumArguments,
+                      in mozIStorageFunction aFunction);
+
+  /**
+   * Create a new SQL aggregate function.  If you use your connection on
+   * multiple threads, your function needs to be threadsafe, or it should only
+   * be called on one thread.
+   *
+   * @param aFunctionName
+   *        The name of aggregate function to create, as seen in SQL.
+   * @param aNumArguments
+   *        The number of arguments the function takes. Pass -1 for
+   *        variable-argument functions.
+   * @param aFunction
+   *        The instance of mozIStorageAggreagteFunction, which implements the
+   *        function in question.
+   */
+  void createAggregateFunction(in AUTF8String aFunctionName,
+                               in long aNumArguments,
+                               in mozIStorageAggregateFunction aFunction);
+  /**
+   * Delete custom SQL function (simple or aggregate one).
+   *
+   * @param aFunctionName
+   *        The name of function to remove.
+   */
+  void removeFunction(in AUTF8String aFunctionName);
+
+  /**
+   * Sets a progress handler. Only one handler can be registered at a time.
+   * If you need more than one, you need to chain them yourself.  This progress
+   * handler should be threadsafe if you use this connection object on more than
+   * one thread.
+   *
+   * @param aGranularity
+   *        The number of SQL virtual machine steps between progress handler
+   *        callbacks.
+   * @param aHandler
+   *        The instance of mozIStorageProgressHandler.
+   * @return previous registered handler.
+   */
+  mozIStorageProgressHandler setProgressHandler(in PRInt32 aGranularity,
+                                                in mozIStorageProgressHandler aHandler);
+
+  /**
+   * Remove a progress handler.
+   *
+   * @return previous registered handler.
+   */
+  mozIStorageProgressHandler removeProgressHandler();
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageError.idl
@@ -0,0 +1,182 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+%{C++
+#ifdef ERROR
+#undef ERROR
+#endif
+%}
+
+[scriptable, uuid(1f350f96-7023-434a-8864-40a1c493aac1)]
+interface mozIStorageError : nsISupports {
+
+  /**
+   * General SQL error or missing database.
+   */
+  const long ERROR = 1;
+
+  /**
+   * Internal logic error.
+   */
+  const long INTERNAL = 2;
+
+  /**
+   * Access permission denied.
+   */
+  const long PERM = 3;
+
+  /**
+   * A callback routine requested an abort.
+   */
+  const long ABORT = 4;
+
+  /**
+   * The database file is locked.
+   */
+  const long BUSY = 5;
+
+  /**
+   * A table in the database is locked.
+   */
+  const long LOCKED = 6;
+
+  /**
+   * An allocation failed.
+   */
+  const long NOMEM = 7;
+
+  /**
+   * Attempt to write to a readonly database.
+   */
+  const long READONLY = 8;
+
+  /**
+   * Operation was terminated by an interrupt.
+   */
+  const long INTERRUPT = 9;
+
+  /**
+   * Some kind of disk I/O error occurred.
+   */
+  const long IOERR = 10;
+
+  /**
+   * The database disk image is malformed.
+   */
+  const long CORRUPT = 11;
+
+  /**
+   * An insertion failed because the database is full.
+   */
+  const long FULL = 13;
+
+  /**
+   * Unable to open the database file.
+   */
+  const long CANTOPEN = 14;
+
+  /**
+   * The database is empty.
+   */
+  const long EMPTY = 16;
+
+  /**
+   * The database scheme changed.
+   */
+  const long SCHEMA = 17;
+
+  /**
+   * A string or blob exceeds the size limit.
+   */
+  const long TOOBIG = 18;
+
+  /**
+   * Abort due to a constraint violation.
+   */
+  const long CONSTRAINT = 19;
+
+  /**
+   * Data type mismatch.
+   */
+  const long MISMATCH = 20;
+
+  /**
+   * Library used incorrectly.
+   */
+  const long MISUSE = 21;
+
+  /**
+   * Uses OS features not supported on the host system.
+   */
+  const long NOLFS = 22;
+
+  /**
+   * Authorization denied.
+   */
+  const long AUTH = 23;
+
+  /**
+   * Auxiliary database format error.
+   */
+  const long FORMAT = 24;
+
+  /**
+   * Attempt to bind a parameter using an out-of-range index or nonexistent
+   * named parameter name.
+   */
+  const long RANGE = 25;
+
+  /**
+   * File opened that is not a database file.
+   */
+  const long NOTADB = 26;
+
+
+  /**
+   * Indicates what type of error occurred.
+   */
+  readonly attribute long result;
+
+  /**
+   * An error string the gives more details, if available.
+   */
+  readonly attribute AUTF8String message;
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageFunction.idl
@@ -0,0 +1,74 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Lev Serebryakov <lev@serebryakov.spb.ru>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+#include "mozIStorageValueArray.idl"
+
+interface mozIStorageConnection;
+interface nsIArray;
+interface nsIVariant;
+
+/**
+ * mozIStorageFunction is to be implemented by storage consumers that
+ * wish to receive callbacks during the request execution.
+ *
+ * SQL can apply functions to values from tables. Examples of
+ * such functions are MIN(a1,a2) or SQRT(num). Many functions are
+ * implemented in SQL engine.
+ *
+ * This interface allows consumers to implement their own,
+ * problem-specific functions.
+ * These functions can be called from triggers, too.
+ *
+ */
+[scriptable, function, uuid(9ff02465-21cb-49f3-b975-7d5b38ceec73)]
+interface mozIStorageFunction : nsISupports {
+  /**
+   * onFunctionCall is called when execution of a custom
+   * function should occur.
+   * 
+   * @param aNumArguments         The number of arguments
+   * @param aFunctionArguments    The arguments passed in to the function
+   *
+   * @returns any value as Variant type.
+   */
+
+  nsIVariant onFunctionCall(in mozIStorageValueArray aFunctionArguments);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStoragePendingStatement.idl
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(00da7d20-3768-4398-bedc-e310c324b3f0)]
+interface mozIStoragePendingStatement : nsISupports {
+
+  /**
+   * Cancels a pending statement, if possible.  This will only fail if you try
+   * cancel more than once.
+   *
+   * @note For read statements (such as SELECT), you will no longer receive any
+   *       notifications about results once cancel is called.
+   */
+   void cancel();
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageProgressHandler.idl
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Storage Code.
+ *
+ * The Initial Developer of the Original Code is
+ *   Lev Serebryakov <lev@serebryakov.spb.ru>
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface mozIStorageConnection;
+
+/**
+ * mozIProgressHandler is to be implemented by storage consumers that
+ * wish to receive callbacks during the request execution.
+ */
+[scriptable, uuid(a3a6fcd4-bf89-4208-a837-bf2a73afd30c)]
+interface mozIStorageProgressHandler : nsISupports {
+  /**
+   * onProgress is invoked periodically during long running calls.
+   * 
+   * @param aConnection    connection, for which progress handler is
+   *                       invoked.
+   *
+   * @return true to abort request, false to continue work.
+   */
+
+  boolean onProgress(in mozIStorageConnection aConnection);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageResultSet.idl
@@ -0,0 +1,54 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+interface mozIStorageRow;
+
+[scriptable, uuid(18dd7953-076d-4598-8105-3e32ad26ab24)]
+interface mozIStorageResultSet : nsISupports {
+
+  /**
+   * Obtains the next row from the result set from the statement that was
+   * executed.
+   *
+   * @returns the next row from the result set.  This will be null when there
+   *          are no more results.
+   */
+  mozIStorageRow getNextRow();
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageRow.idl
@@ -0,0 +1,63 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozIStorageValueArray.idl"
+interface nsIVariant;
+
+[scriptable, uuid(62d1b6bd-cbfe-4f9b-aee1-0ead4af4e6dc)]
+interface mozIStorageRow : mozIStorageValueArray {
+
+  /**
+   * Obtains the result of a given column specified by aIndex.
+   *
+   * @param aIndex
+   *        Zero-based index of the result to get from the tuple.
+   * @returns the result of the specified column.
+   */
+  nsIVariant getResultByIndex(in unsigned long aIndex);
+
+  /**
+   * Obtains the result of a given column specified by aIndex.
+   *
+   * @param aName
+   *        Name of the result to get from the tuple.
+   * @returns the result of the specified column.
+   */
+  nsIVariant getResultByName(in AUTF8String aName);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageService.idl
@@ -0,0 +1,172 @@
+/* -*- Mode: idl; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface mozIStorageConnection;
+interface nsIFile;
+
+/**
+ * The mozIStorageService interface is intended to be implemented by
+ * a service that can create storage connections (mozIStorageConnection)
+ * to either a well-known profile database or to a specific database file.
+ *
+ * This is the only way to open a database connection.
+ */
+[scriptable, uuid(fe8e95cb-b377-4c8d-bccb-d9198c67542b)]
+interface mozIStorageService : nsISupports {
+  /**
+   * Get a connection to a named special database storage.
+   *
+   * @param aStorageKey a string key identifying the type of storage
+   * requested.  Valid values include: "profile", "memory".
+   *
+   * @see openDatabase for restrictions on how database connections may be
+   * used. For the profile database, you should only access it from the main
+   * thread since other callers may also have connections.
+   *
+   * @returns a new mozIStorageConnection for the requested
+   * storage database.
+   *
+   * @throws NS_ERROR_INVALID_ARG if aStorageKey is invalid.
+   */
+  mozIStorageConnection openSpecialDatabase(in string aStorageKey);
+
+  /**
+   * Open a connection to the specified file.
+   *
+   * Consumers should check mozIStorageConnection::connectionReady to ensure
+   * that they can use the database.  If this value is false, it is strongly
+   * recommended that the database be backed up with
+   * mozIStorageConnection::backupDB so user data is not lost.
+   *
+   * ==========
+   *   DANGER
+   * ==========
+   *
+   * If you have more than one connection to a file, you MUST use the EXACT
+   * SAME NAME for the file each time, including case. The sqlite code uses
+   * a simple string compare to see if there is already a connection. Opening
+   * a connection to "Foo.sqlite" and "foo.sqlite" will CORRUPT YOUR DATABASE.
+   *
+   * The connection object returned by this function is not threadsafe. You must
+   * use it only from the thread you created it from.
+   *
+   * If your database contains virtual tables (f.e. for full-text indexes), you
+   * must open it with openUnsharedDatabase, as those tables are incompatible
+   * with a shared cache.  If you attempt to use this method to open a database
+   * containing virtual tables, it will think the database is corrupted and
+   * throw NS_ERROR_FILE_CORRUPTED.
+   *
+   * @param aDatabaseFile
+   *        A nsIFile that represents the database that is to be opened..
+   *
+   * @returns a mozIStorageConnection for the requested database file.
+   *
+   * @throws NS_ERROR_OUT_OF_MEMORY
+   *         If allocating a new storage object fails.
+   * @throws NS_ERROR_FILE_CORRUPTED
+   *         If the database file is corrupted.
+   */
+  mozIStorageConnection openDatabase(in nsIFile aDatabaseFile);
+
+  /**
+   * Open a connection to the specified file that doesn't share a sqlite cache.
+   *
+   * Each connection uses its own sqlite cache, which is inefficient, so you
+   * should use openDatabase instead of this method unless you need a feature
+   * of SQLite that is incompatible with a shared cache, like virtual table
+   * and full text indexing support.
+   *
+   * Consumers should check mozIStorageConnection::connectionReady to ensure
+   * that they can use the database.  If this value is false, it is strongly
+   * recommended that the database be backed up with
+   * mozIStorageConnection::backupDB so user data is not lost.
+   *
+   * ==========
+   *   DANGER
+   * ==========
+   *
+   * If you have more than one connection to a file, you MUST use the EXACT
+   * SAME NAME for the file each time, including case. The sqlite code uses
+   * a simple string compare to see if there is already a connection. Opening
+   * a connection to "Foo.sqlite" and "foo.sqlite" will CORRUPT YOUR DATABASE.
+   *
+   * The connection object returned by this function is not threadsafe. You must
+   * use it only from the thread you created it from.
+   *
+   * @param aDatabaseFile
+   *        A nsIFile that represents the database that is to be opened..
+   *
+   * @returns a mozIStorageConnection for the requested database file.
+   *
+   * @throws NS_ERROR_OUT_OF_MEMORY
+   *         If allocating a new storage object fails.
+   * @throws NS_ERROR_FILE_CORRUPTED
+   *         If the database file is corrupted.
+   */
+  mozIStorageConnection openUnsharedDatabase(in nsIFile aDatabaseFile);
+
+  /*
+   * Utilities
+   */
+
+  /**
+   * Copies the specified database file to the specified parent directory with
+   * the specified file name.  If the parent directory is not specified, it
+   * places the backup in the same directory as the current file.  This function
+   * ensures that the file being created is unique.
+   *
+   * @param aDBFile
+   *        The database file that will be backed up.
+   * @param aBackupFileName
+   *        The name of the new backup file to create.
+   * @param [optional] aBackupParentDirectory
+   *        The directory you'd like the backup file to be placed.
+   * @return The nsIFile representing the backup file.
+   */
+  nsIFile backupDatabaseFile(in nsIFile aDBFile, in AString aBackupFileName,
+                             [optional] in nsIFile aBackupParentDirectory);
+};
+
+%{C++
+
+#define MOZ_STORAGE_MEMORY_STORAGE_KEY    "memory"
+#define MOZ_STORAGE_PROFILE_STORAGE_KEY   "profile"
+
+%}
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageStatement.idl
@@ -0,0 +1,309 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozIStorageBaseStatement.idl"
+
+[ptr] native octetPtr(PRUint8);
+
+/**
+ * A SQL statement that can be used for both synchronous and asynchronous
+ * purposes.
+ */
+[scriptable, uuid(57ec7be1-36cf-4510-b938-7d1c9ee8cec5)]
+interface mozIStorageStatement : mozIStorageBaseStatement {
+  /**
+   * Create a clone of this statement, by initializing a new statement
+   * with the same connection and same SQL statement as this one.  It
+   * does not preserve statement state; that is, if a statement is
+   * being executed when it is cloned, the new statement will not be
+   * executing.
+   */
+  mozIStorageStatement clone();
+
+  /*
+   * Number of parameters
+   */
+  readonly attribute unsigned long parameterCount;
+
+  /**
+   * Name of nth parameter, if given
+   */
+  AUTF8String getParameterName(in unsigned long aParamIndex);
+
+  /**
+   * Returns the index of the named parameter.
+   *
+   * @param aName
+   *        The name of the parameter you want the index for.  This does not
+   *        include the leading ':'.
+   * @return the index of the named parameter.
+   */
+  unsigned long getParameterIndex(in AUTF8String aName);
+
+  /**
+   * Number of columns returned
+   */
+  readonly attribute unsigned long columnCount;
+
+  /**
+   * Name of nth column
+   */
+  AUTF8String getColumnName(in unsigned long aColumnIndex);
+
+  /**
+   * Obtains the index of the column with the specified name.
+   *
+   * @param aName
+   *        The name of the column.
+   * @return The index of the column with the specified name.
+   */
+  unsigned long getColumnIndex(in AUTF8String aName);
+
+  /**
+   * Obtains the declared column type of a prepared statement.
+   *
+   * @param aParamIndex
+   *        The zero-based index of the column who's declared type we are
+   *        interested in.
+   * @return the declared index type.
+   */
+  AUTF8String getColumnDecltype(in unsigned long aParamIndex);
+
+  /**
+   * Reset parameters/statement execution
+   */
+  void reset();
+
+  /**
+   * Execute the query, ignoring any results.  This is accomplished by
+   * calling executeStep() once, and then calling reset().
+   *
+   * Error and last insert info, etc. are available from
+   * the mozStorageConnection.
+   */
+  void execute();
+
+  /**
+   * Execute a query, using any currently-bound parameters.  Reset
+   * must be called on the statement after the last call of
+   * executeStep.
+   *
+   * @return a boolean indicating whether there are more rows or not;
+   *         row data may be accessed using mozIStorageValueArray methods on
+   *         the statement.
+   */
+  boolean executeStep();
+
+  /**
+   * Execute a query, using any currently-bound parameters.  Reset is called
+   * when no more data is returned.  This method is only available to JavaScript
+   * consumers.
+   *
+   * @deprecated As of Mozilla 1.9.2 in favor of executeStep().
+   *
+   * @return a boolean indicating whether there are more rows or not.
+   *
+   * [deprecated] boolean step();
+   */
+
+  /**
+   * Obtains the current list of named parameters, which are settable.  This
+   * property is only available to JavaScript consumers.
+   *
+   * readonly attribute mozIStorageStatementParams params;
+   */
+
+  /**
+   * Obtains the current row, with access to all the data members by name.  This
+   * property is only available to JavaScript consumers.
+   *
+   * readonly attribute mozIStorageStatementRow row;
+   */
+
+  //////////////////////////////////////////////////////////////////////////////
+  //// Copied contents of mozIStorageValueArray
+
+  /**
+   * These type values are returned by getTypeOfIndex
+   * to indicate what type of value is present at
+   * a given column.
+   */
+  const long VALUE_TYPE_NULL = 0;
+  const long VALUE_TYPE_INTEGER = 1;
+  const long VALUE_TYPE_FLOAT = 2;
+  const long VALUE_TYPE_TEXT = 3;
+  const long VALUE_TYPE_BLOB = 4;
+
+  /**
+   * The number of entries in the array (each corresponding to a column in the
+   * database row)
+   */
+  readonly attribute unsigned long numEntries;
+
+  /**
+   * Indicate the data type of the current result row for the the given column.
+   * SQLite will perform type conversion if you ask for a value as a different
+   * type than it is stored as.
+   *
+   * @param aIndex
+   *        0-based column index.
+   * @return The type of the value at the given column index; one of
+   *         VALUE_TYPE_NULL, VALUE_TYPE_INTEGER, VALUE_TYPE_FLOAT,
+   *         VALUE_TYPE_TEXT, VALUE_TYPE_BLOB.
+   */
+  long getTypeOfIndex(in unsigned long aIndex);
+
+  /**
+   * Retrieve the contents of a column from the current result row as an
+   * integer.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @return Column value interpreted as an integer per type conversion rules.
+   * @{
+   */
+  long getInt32(in unsigned long aIndex);
+  long long getInt64(in unsigned long aIndex);
+  /** @} */
+  /**
+   * Retrieve the contents of a column from the current result row as a
+   * floating point double.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @return Column value interpreted as a double per type conversion rules.
+   */
+  double getDouble(in unsigned long aIndex);
+  /**
+   * Retrieve the contents of a column from the current result row as a
+   * string.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @return The value for the result column interpreted as a string.  If the
+   *         stored value was NULL, you will get an empty string with IsVoid set
+   *         to distinguish it from an explicitly set empty string.
+   * @{
+   */
+  AUTF8String getUTF8String(in unsigned long aIndex);
+  AString getString(in unsigned long aIndex);
+  /** @} */
+
+  /**
+   * Retrieve the contents of a column from the current result row as a
+   * blob.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @param[out] aDataSize
+   *             The number of bytes in the blob.
+   * @param[out] aData
+   *             The contents of the BLOB.  This will be NULL if aDataSize == 0.
+   */
+  void getBlob(in unsigned long aIndex, out unsigned long aDataSize, [array,size_is(aDataSize)] out octet aData);
+  /**
+   * Check whether the given column in the current result row is NULL.
+   *
+   * @param aIndex
+   *        0-based colummn index.
+   * @return true if the value for the result column is null.
+   */
+  boolean getIsNull(in unsigned long aIndex);
+
+  /**
+   * Returns a shared string pointer
+   */
+  [noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out string aResult);
+  [noscript] void getSharedString(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out wstring aResult);
+  [noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out octetPtr aResult);
+
+%{C++
+  /**
+   * Getters for native code that return their values as
+   * the return type, for convenience and sanity.
+   *
+   * Not virtual; no vtable bloat.
+   */
+
+  inline PRInt32 AsInt32(PRUint32 idx) {
+    PRInt32 v;
+    GetInt32(idx, &v);
+    return v;
+  }
+
+  inline PRInt64 AsInt64(PRUint32 idx) {
+    PRInt64 v;
+    GetInt64(idx, &v);
+    return v;
+  }
+
+  inline double AsDouble(PRUint32 idx) {
+    double v;
+    GetDouble(idx, &v);
+    return v;
+  }
+
+  inline const char* AsSharedUTF8String(PRUint32 idx, PRUint32 *len) {
+    const char *str = nsnull;
+    GetSharedUTF8String(idx, len, &str);
+    return str;
+  }
+
+  inline const PRUnichar* AsSharedWString(PRUint32 idx, PRUint32 *len) {
+    const PRUnichar *str = nsnull;
+    GetSharedString(idx, len, &str);
+    return str;
+  }
+
+  inline const PRUint8* AsSharedBlob(PRUint32 idx, PRUint32 *len) {
+    const PRUint8 *blob = nsnull;
+    GetSharedBlob(idx, len, &blob);
+    return blob;
+  }
+
+  inline PRBool IsNull(PRUint32 idx) {
+    PRBool b = PR_FALSE;
+    GetIsNull(idx, &b);
+    return b;
+  }
+
+%}
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageStatementCallback.idl
@@ -0,0 +1,81 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+interface mozIStorageResultSet;
+interface mozIStorageError;
+
+[scriptable, uuid(29383d00-d8c4-4ddd-9f8b-c2feb0f2fcfa)]
+interface mozIStorageStatementCallback : nsISupports {
+
+  /**
+   * Called when some result is obtained from the database.  This function can
+   * be called more than once with a different storageIResultSet each time for
+   * any given asynchronous statement.
+   *
+   * @param aResultSet
+   *        The result set containing the data from the database.
+   */
+  void handleResult(in mozIStorageResultSet aResultSet);
+
+  /**
+   * Called when some error occurs while executing the statement.  This function
+   * may be called more than once with a different storageIError each time for
+   * any given asynchronous statement.
+   *
+   * @param aError
+   *        An object containing information about the error.
+   */
+  void handleError(in mozIStorageError aError);
+
+  /**
+   * Called when the statement has finished executing.  This function will only
+   * be called once for any given asynchronous statement.
+   *
+   * @param aReason
+   *        Indicates if the statement is no longer executing because it either
+   *        finished (REASON_FINISHED), was canceled (REASON_CANCELED), or
+   *        a fatal error occurred (REASON_ERROR).
+   */
+  const unsigned short REASON_FINISHED = 0;
+  const unsigned short REASON_CANCELED = 1;
+  const unsigned short REASON_ERROR = 2;
+  void handleCompletion(in unsigned short aReason);
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageStatementWrapper.idl
@@ -0,0 +1,88 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozIStorageStatement.idl"
+
+[scriptable, uuid(02eeaf95-c3db-4182-9340-222c29f68f02)]
+interface mozIStorageStatementRow : nsISupports {
+  // magic interface we return that implements nsIXPCScriptable, to allow
+  // for by-name access to rows
+};
+
+[scriptable, uuid(e65fe6e2-2643-463c-97e2-27665efe2386)]
+interface mozIStorageStatementParams : nsISupports {
+  // magic interface for parameter setting that implements nsIXPCScriptable.
+};
+
+/**
+ * @deprecated As of Mozilla 1.9.2.  Methods are already provided on
+ *             mozIStorageStatement.
+ */
+[scriptable, deprecated, uuid(eee6f7c9-5586-4eaf-b35c-dca987c4ffd1)]
+interface mozIStorageStatementWrapper : nsISupports {
+  /**
+   * Initialize this wrapper with aStatement.
+   */
+  void initialize(in mozIStorageStatement aStatement);
+
+  /**
+   * The statement that is wrapped.
+   */
+  readonly attribute mozIStorageStatement statement;
+
+  /**
+   * Step, reset, and execute the wrapped statement.
+   */
+  void reset();
+  [deprecated] boolean step();
+  void execute();
+
+  /**
+   * The current row.  Throws an exception if no row is currently
+   * available.  Useful only from script.  The value of this is only
+   * valid while the statement is still executing, and is still on the
+   * appropriate row.
+   */
+  readonly attribute mozIStorageStatementRow row;
+
+  /**
+   * The parameters; these can be set in lieu of using the call
+   * notation on this.
+   */
+  readonly attribute mozIStorageStatementParams params;
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozIStorageValueArray.idl
@@ -0,0 +1,156 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsISupports.idl"
+
+[ptr] native octetPtr(PRUint8);
+
+/**
+ * mozIStorageValueArray wraps an array of SQL values, such as a single database
+ * row.
+ */
+[scriptable, uuid(07b5b93e-113c-4150-863c-d247b003a55d)]
+interface mozIStorageValueArray : nsISupports {
+  /**
+   * These type values are returned by getTypeOfIndex
+   * to indicate what type of value is present at
+   * a given column.
+   */
+  const long VALUE_TYPE_NULL = 0;
+  const long VALUE_TYPE_INTEGER = 1;
+  const long VALUE_TYPE_FLOAT = 2;
+  const long VALUE_TYPE_TEXT = 3;
+  const long VALUE_TYPE_BLOB = 4;
+
+  /**
+   * numEntries
+   *
+   * number of entries in the array (each corresponding to a column
+   * in the database row)
+   */
+  readonly attribute unsigned long numEntries;
+
+  /**
+   * Returns the type of the value at the given column index;
+   * one of VALUE_TYPE_NULL, VALUE_TYPE_INTEGER, VALUE_TYPE_FLOAT,
+   * VALUE_TYPE_TEXT, VALUE_TYPE_BLOB.
+   */
+  long getTypeOfIndex(in unsigned long aIndex);
+
+  /**
+   * Obtain a value for the given entry (column) index.
+   * Due to SQLite's type conversion rules, any of these are valid
+   * for any column regardless of the column's data type.  However,
+   * if the specific type matters, getTypeOfIndex should be used
+   * first to identify the column type, and then the appropriate
+   * get method should be called.
+   *
+   * If you ask for a string value for a NULL column, you will get an empty
+   * string with IsVoid set to distinguish it from an explicitly set empty
+   * string.
+   */
+  long getInt32(in unsigned long aIndex);
+  long long getInt64(in unsigned long aIndex);
+  double getDouble(in unsigned long aIndex);
+  AUTF8String getUTF8String(in unsigned long aIndex);
+  AString getString(in unsigned long aIndex);
+
+  // data will be NULL if dataSize = 0
+  void getBlob(in unsigned long aIndex, out unsigned long aDataSize, [array,size_is(aDataSize)] out octet aData);
+  boolean getIsNull(in unsigned long aIndex);
+
+  /**
+   * Returns a shared string pointer
+   */
+  [noscript] void getSharedUTF8String(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out string aResult);
+  [noscript] void getSharedString(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out wstring aResult);
+  [noscript] void getSharedBlob(in unsigned long aIndex, out unsigned long aLength, [shared,retval] out octetPtr aResult);
+
+%{C++
+  /**
+   * Getters for native code that return their values as
+   * the return type, for convenience and sanity.
+   *
+   * Not virtual; no vtable bloat.
+   */
+
+  inline PRInt32 AsInt32(PRUint32 idx) {
+    PRInt32 v;
+    GetInt32(idx, &v);
+    return v;
+  }
+
+  inline PRInt64 AsInt64(PRUint32 idx) {
+    PRInt64 v;
+    GetInt64(idx, &v);
+    return v;
+  }
+
+  inline double AsDouble(PRUint32 idx) {
+    double v;
+    GetDouble(idx, &v);
+    return v;
+  }
+
+  inline const char* AsSharedUTF8String(PRUint32 idx, PRUint32 *len) {
+    const char *str = nsnull;
+    GetSharedUTF8String(idx, len, &str);
+    return str;
+  }
+
+  inline const PRUnichar* AsSharedWString(PRUint32 idx, PRUint32 *len) {
+    const PRUnichar *str = nsnull;
+    GetSharedString(idx, len, &str);
+    return str;
+  }
+
+  inline const PRUint8* AsSharedBlob(PRUint32 idx, PRUint32 *len) {
+    const PRUint8 *blob = nsnull;
+    GetSharedBlob(idx, len, &blob);
+    return blob;
+  }
+
+  inline PRBool IsNull(PRUint32 idx) {
+    PRBool b = PR_FALSE;
+    GetIsNull(idx, &b);
+    return b;
+  }
+
+%}
+
+};
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozStorage.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _MOZSTORAGE_H_
+#define _MOZSTORAGE_H_
+
+#define NS_ERROR_STORAGE_BUSY \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_STORAGE, 1)
+
+#define NS_ERROR_STORAGE_IOERR \
+  NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_STORAGE, 2)
+
+#endif /* _MOZSTORAGE_H_ */
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/mozStorageHelper.h
@@ -0,0 +1,195 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Storage code
+ *
+ * The Initial Developer of the Original Code is
+ * Google Inc.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Brett Wilson <brettw@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _MOZSTORAGEHELPER_H_
+#define _MOZSTORAGEHELPER_H_
+
+#include "nsAutoPtr.h"
+
+#include "mozIStorageConnection.h"
+#include "mozIStorageStatement.h"
+#include "mozStorage.h"
+
+
+/**
+ * This class wraps a transaction inside a given C++ scope, guaranteeing that
+ * the transaction will be completed even if you have an exception or
+ * return early.
+ *
+ * aCommitOnComplete controls whether the transaction is committed or rolled
+ * back when it goes out of scope. A common use is to create an instance with
+ * commitOnComplete = FALSE (rollback), then call Commit on this object manually
+ * when your function completes successfully.
+ *
+ * Note that nested transactions are not supported by sqlite, so if a transaction
+ * is already in progress, this object does nothing. Note that in this case,
+ * you may not get the transaction type you ask for, and you won't be able
+ * to rollback.
+ */
+class mozStorageTransaction
+{
+public:
+  mozStorageTransaction(mozIStorageConnection* aConnection,
+                        PRBool aCommitOnComplete,
+                        PRInt32 aType = mozIStorageConnection::TRANSACTION_DEFERRED)
+    : mConnection(aConnection),
+      mHasTransaction(PR_FALSE),
+      mCommitOnComplete(aCommitOnComplete),
+      mCompleted(PR_FALSE)
+  {
+    // We won't try to get a transaction if one is already in progress.
+    if (mConnection)
+      mHasTransaction = NS_SUCCEEDED(mConnection->BeginTransactionAs(aType));
+  }
+  ~mozStorageTransaction()
+  {
+    if (mConnection && mHasTransaction && ! mCompleted) {
+      if (mCommitOnComplete)
+        mConnection->CommitTransaction();
+      else
+        mConnection->RollbackTransaction();
+    }
+  }
+
+  /**
+   * Commits the transaction if one is in progress. If one is not in progress,
+   * this is a NOP since the actual owner of the transaction outside of our
+   * scope is in charge of finally comitting or rolling back the transaction.
+   */
+  nsresult Commit()
+  {
+    if (!mConnection || mCompleted)
+      return NS_OK; // no connection, or already done
+    mCompleted = PR_TRUE;
+    if (! mHasTransaction)
+      return NS_OK; // transaction not ours, ignore
+    nsresult rv = mConnection->CommitTransaction();
+    if (NS_SUCCEEDED(rv))
+      mHasTransaction = PR_FALSE;
+
+    return rv;
+  }
+
+  /**
+   * Rolls back the transaction in progress. You should only call this function
+   * if this object has a real transaction (HasTransaction() = true) because
+   * otherwise, there is no transaction to roll back.
+   */
+  nsresult Rollback()
+  {
+    if (!mConnection || mCompleted)
+      return NS_OK; // no connection, or already done
+    mCompleted = PR_TRUE;
+    if (! mHasTransaction)
+      return NS_ERROR_FAILURE;
+
+    // It is possible that a rollback will return busy, so we busy wait...
+    nsresult rv = NS_OK;
+    do {
+      rv = mConnection->RollbackTransaction();
+      if (rv == NS_ERROR_STORAGE_BUSY)
+        (void)PR_Sleep(PR_INTERVAL_NO_WAIT);
+    } while (rv == NS_ERROR_STORAGE_BUSY);
+
+    if (NS_SUCCEEDED(rv))
+      mHasTransaction = PR_FALSE;
+
+    return rv;
+  }
+
+  /**
+   * Returns whether this object wraps a real transaction. False means that
+   * this object doesn't do anything because there was already a transaction in
+   * progress when it was created.
+   */
+  PRBool HasTransaction()
+  {
+    return mHasTransaction;
+  }
+
+  /**
+   * This sets the default action (commit or rollback) when this object goes
+   * out of scope.
+   */
+  void SetDefaultAction(PRBool aCommitOnComplete)
+  {
+    mCommitOnComplete = aCommitOnComplete;
+  }
+
+protected:
+  nsCOMPtr<mozIStorageConnection> mConnection;
+  PRBool mHasTransaction;
+  PRBool mCommitOnComplete;
+  PRBool mCompleted;
+};
+
+
+/**
+ * This class wraps a statement so that it is guaraneed to be reset when
+ * this object goes out of scope.
+ *
+ * Note that this always just resets the statement. If the statement doesn't
+ * need resetting, the reset operation is inexpensive.
+ */
+class NS_STACK_CLASS mozStorageStatementScoper
+{
+public:
+  mozStorageStatementScoper(mozIStorageStatement* aStatement)
+      : mStatement(aStatement)
+  {
+  }
+  ~mozStorageStatementScoper()
+  {
+    if (mStatement)
+      mStatement->Reset();
+  }
+
+  /**
+   * Call this to make the statement not reset. You might do this if you know
+   * that the statement has been reset.
+   */
+  void Abandon()
+  {
+    mStatement = nsnull;
+  }
+
+protected:
+  nsCOMPtr<mozIStorageStatement> mStatement;
+};
+
+#endif /* _MOZSTORAGEHELPER_H_ */
new file mode 100644
--- /dev/null
+++ b/storage-backport/public/storage.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Storage code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_h_
+#define mozilla_storage_h_
+
+////////////////////////////////////////////////////////////////////////////////
+//// Public Interfaces
+
+#include "mozIStorageAggregateFunction.h"
+#include "mozIStorageConnection.h"
+#include "mozIStorageError.h"
+#include "mozIStorageFunction.h"
+#include "mozIStoragePendingStatement.h"
+#include "mozIStorageProgressHandler.h"
+#include "mozIStorageResultSet.h"
+#include "mozIStorageRow.h"
+#include "mozIStorageService.h"
+#include "mozIStorageStatement.h"
+#include "mozIStorageStatementCallback.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//// Native Language Helpers
+
+#include "mozStorageHelper.h"
+#include "mozStorageCID.h"
+
+#include "mozilla/storage/Variant.h"
+
+#endif // mozilla_storage_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/IStorageBindingParamsInternal.h
@@ -0,0 +1,83 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_IStorageBindingParamsInternal_h_
+#define mozilla_storage_IStorageBindingParamsInternal_h_
+
+#include "nsISupports.h"
+
+struct sqlite3_stmt;
+class mozIStorageError;
+
+namespace mozilla {
+namespace storage {
+
+#define ISTORAGEBINDINGPARAMSINTERNAL_IID \
+  {0x4c43d33a, 0xc620, 0x41b8, {0xba, 0x1d, 0x50, 0xc5, 0xb1, 0xe9, 0x1a, 0x04}}
+
+/**
+ * Implementation-only interface for mozIStorageBindingParams.  This defines the
+ * set of methods required by the asynchronous execution code in order to
+ * consume the contents stored in mozIStorageBindingParams instances.
+ */
+class IStorageBindingParamsInternal : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(ISTORAGEBINDINGPARAMSINTERNAL_IID)
+
+  /**
+   * Binds our stored data to the statement.
+   *
+   * @param aStatement
+   *        The statement to bind our data to.
+   * @return nsnull on success, or a mozIStorageError object if an error
+   *         occurred.
+   */
+  virtual already_AddRefed<mozIStorageError> bind(sqlite3_stmt *aStatement) = 0;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(IStorageBindingParamsInternal,
+                              ISTORAGEBINDINGPARAMSINTERNAL_IID)
+
+#define NS_DECL_ISTORAGEBINDINGPARAMSINTERNAL \
+  already_AddRefed<mozIStorageError> bind(sqlite3_stmt *aStatement);
+
+} // storage
+} // mozilla
+
+#endif // mozilla_storage_IStorageBindingParamsInternal_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/Makefile.in
@@ -0,0 +1,92 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is Oracle Corporation code.
+#
+# The Initial Developer of the Original Code is
+#   Oracle Corporation
+# Portions created by the Initial Developer are Copyright (C) 2004
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH   = ../..
+topsrcdir = @top_srcdir@
+srcdir    = @srcdir@
+VPATH   = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE           = storage
+LIBRARY_NAME     = storage_s
+MODULE_NAME      = mozStorageModule
+FORCE_STATIC_LIB = 1
+GRE_MODULE       = 1
+LIBXUL_LIBRARY = 1
+
+
+EXPORTS_NAMESPACES = mozilla/storage
+
+EXPORTS_mozilla/storage = \
+  Variant.h \
+  Variant_inl.h \
+  $(NULL)
+
+CPPSRCS = \
+  mozStorageService.cpp \
+  mozStorageConnection.cpp \
+  mozStorageStatement.cpp \
+  mozStorageStatementWrapper.cpp \
+  mozStorageStatementParams.cpp \
+  mozStorageStatementRow.cpp \
+  mozStorageArgValueArray.cpp \
+  mozStorageSQLFunctions.cpp \
+  mozStorageRow.cpp \
+  mozStorageResultSet.cpp \
+  mozStorageError.cpp \
+  mozStorageAsyncStatementExecution.cpp \
+  mozStorageStatementJSHelper.cpp \
+  mozStoragePrivateHelpers.cpp \
+  mozStorageBindingParamsArray.cpp \
+  mozStorageBindingParams.cpp \
+  mozStorageAsyncStatement.cpp \
+  mozStorageAsyncStatementJSHelper.cpp \
+  mozStorageAsyncStatementParams.cpp \
+  StorageBaseStatementInternal.cpp \
+  SQLCollations.cpp \
+  $(NULL)
+
+LOCAL_INCLUDES = \
+	$(SQLITE_CFLAGS)
+
+# This is the default value.  If we ever change it when compiling sqlite, we
+# will need to change it here as well.
+DEFINES += -DSQLITE_MAX_LIKE_PATTERN_LENGTH=50000
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/SQLCollations.cpp
@@ -0,0 +1,269 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Storage code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Drew Willcoxon <adw@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "SQLCollations.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// Local Helper Functions
+
+namespace {
+
+/**
+ * Helper function for the UTF-8 locale collations.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2 as provided by SQLite.  It
+ *         must be a non-null-terminated char* buffer.
+ * @param  aLen2
+ *         The number of bytes in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1 as provided by SQLite.  It
+ *         must be a non-null-terminated char* buffer.
+ * @param  aComparisonStrength
+ *         The sorting strength, one of the nsICollation constants.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+int
+localeCollationHelper8(void *aService,
+                       int aLen1,
+                       const void *aStr1,
+                       int aLen2,
+                       const void *aStr2,
+                       PRInt32 aComparisonStrength)
+{
+  NS_ConvertUTF8toUTF16 str1(static_cast<const char *>(aStr1), aLen1);
+  NS_ConvertUTF8toUTF16 str2(static_cast<const char *>(aStr2), aLen2);
+  Service *serv = static_cast<Service *>(aService);
+  return serv->localeCompareStrings(str1, str2, aComparisonStrength);
+}
+
+/**
+ * Helper function for the UTF-16 locale collations.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes (not characters) in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2 as provided by SQLite.  It
+ *         must be a non-null-terminated PRUnichar* buffer.
+ * @param  aLen2
+ *         The number of bytes (not characters) in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1 as provided by SQLite.  It
+ *         must be a non-null-terminated PRUnichar* buffer.
+ * @param  aComparisonStrength
+ *         The sorting strength, one of the nsICollation constants.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+int
+localeCollationHelper16(void *aService,
+                        int aLen1,
+                        const void *aStr1,
+                        int aLen2,
+                        const void *aStr2,
+                        PRInt32 aComparisonStrength)
+{
+  const PRUnichar *buf1 = static_cast<const PRUnichar *>(aStr1);
+  const PRUnichar *buf2 = static_cast<const PRUnichar *>(aStr2);
+
+  // The second argument to the nsDependentSubstring constructor is exclusive:
+  // It points to the PRUnichar immediately following the last one in the target
+  // substring.  Since aLen1 and aLen2 are in bytes, divide by sizeof(PRUnichar)
+  // so that the pointer arithmetic is correct.
+  nsDependentSubstring str1(buf1, buf1 + (aLen1 / sizeof(PRUnichar)));
+  nsDependentSubstring str2(buf2, buf2 + (aLen2 / sizeof(PRUnichar)));
+  Service *serv = static_cast<Service *>(aService);
+  return serv->localeCompareStrings(str1, str2, aComparisonStrength);
+}
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//// Exposed Functions
+
+int
+registerCollations(sqlite3 *aDB,
+                   Service *aService)
+{
+  struct Collations {
+    const char *zName;
+    int enc;
+    int(*xCompare)(void*, int, const void*, int, const void*);
+  } collations[] = {
+    {"locale",
+     SQLITE_UTF8,
+     localeCollation8},
+    {"locale_case_sensitive",
+     SQLITE_UTF8,
+     localeCollationCaseSensitive8},
+    {"locale_accent_sensitive",
+     SQLITE_UTF8,
+     localeCollationAccentSensitive8},
+    {"locale_case_accent_sensitive",
+     SQLITE_UTF8,
+     localeCollationCaseAccentSensitive8},
+    {"locale",
+     SQLITE_UTF16,
+     localeCollation16},
+    {"locale_case_sensitive",
+     SQLITE_UTF16,
+     localeCollationCaseSensitive16},
+    {"locale_accent_sensitive",
+     SQLITE_UTF16,
+     localeCollationAccentSensitive16},
+    {"locale_case_accent_sensitive",
+     SQLITE_UTF16,
+     localeCollationCaseAccentSensitive16},
+  };
+
+  int rv = SQLITE_OK;
+  for (size_t i = 0; SQLITE_OK == rv && i < NS_ARRAY_LENGTH(collations); ++i) {
+    struct Collations *p = &collations[i];
+    rv = ::sqlite3_create_collation(aDB, p->zName, p->enc, aService,
+                                    p->xCompare);
+  }
+
+  return rv;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//// SQL Collations
+
+int
+localeCollation8(void *aService,
+                 int aLen1,
+                 const void *aStr1,
+                 int aLen2,
+                 const void *aStr2)
+{
+  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
+                                nsICollation::kCollationCaseInSensitive);
+}
+
+int
+localeCollationCaseSensitive8(void *aService,
+                              int aLen1,
+                              const void *aStr1,
+                              int aLen2,
+                              const void *aStr2)
+{
+  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
+                                nsICollation::kCollationAccentInsenstive);
+}
+
+int
+localeCollationAccentSensitive8(void *aService,
+                                int aLen1,
+                                const void *aStr1,
+                                int aLen2,
+                                const void *aStr2)
+{
+  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
+                                nsICollation::kCollationCaseInsensitiveAscii);
+}
+
+int
+localeCollationCaseAccentSensitive8(void *aService,
+                                    int aLen1,
+                                    const void *aStr1,
+                                    int aLen2,
+                                    const void *aStr2)
+{
+  return localeCollationHelper8(aService, aLen1, aStr1, aLen2, aStr2,
+                                nsICollation::kCollationCaseSensitive);
+}
+
+int
+localeCollation16(void *aService,
+                  int aLen1,
+                  const void *aStr1,
+                  int aLen2,
+                  const void *aStr2)
+{
+  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
+                                 nsICollation::kCollationCaseInSensitive);
+}
+
+int
+localeCollationCaseSensitive16(void *aService,
+                               int aLen1,
+                               const void *aStr1,
+                               int aLen2,
+                               const void *aStr2)
+{
+  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
+                                 nsICollation::kCollationAccentInsenstive);
+}
+
+int
+localeCollationAccentSensitive16(void *aService,
+                                 int aLen1,
+                                 const void *aStr1,
+                                 int aLen2,
+                                 const void *aStr2)
+{
+  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
+                                 nsICollation::kCollationCaseInsensitiveAscii);
+}
+
+int
+localeCollationCaseAccentSensitive16(void *aService,
+                                     int aLen1,
+                                     const void *aStr1,
+                                     int aLen2,
+                                     const void *aStr2)
+{
+  return localeCollationHelper16(aService, aLen1, aStr1, aLen2, aStr2,
+                                 nsICollation::kCollationCaseSensitive);
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/SQLCollations.h
@@ -0,0 +1,282 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Storage code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Drew Willcoxon <adw@mozilla.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _mozilla_storage_SQLCollations_h_
+#define _mozilla_storage_SQLCollations_h_
+
+#include "mozStorageService.h"
+#include "nscore.h"
+#include "nsString.h"
+
+#include "sqlite3.h"
+
+namespace mozilla {
+namespace storage {
+
+/**
+ * Registers the collating sequences declared here with the specified
+ * database and Service.
+ *
+ * @param  aDB
+ *         The database we'll be registering the collations with.
+ * @param  aService
+ *         The Service that owns the nsICollation used by our collations.
+ * @return the SQLite status code indicating success or failure.
+ */
+NS_HIDDEN_(int) registerCollations(sqlite3 *aDB, Service *aService);
+
+////////////////////////////////////////////////////////////////////////////////
+//// Predefined Functions
+
+/**
+ * Custom UTF-8 collating sequence that respects the application's locale.
+ * Comparison is case- and accent-insensitive.  This is called by SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @param  aLen2
+ *         The number of bytes in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollation8(void *aService,
+                                 int aLen1,
+                                 const void *aStr1,
+                                 int aLen2,
+                                 const void *aStr2);
+
+/**
+ * Custom UTF-8 collating sequence that respects the application's locale.
+ * Comparison is case-sensitive and accent-insensitive.  This is called by
+ * SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @param  aLen2
+ *         The number of bytes in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollationCaseSensitive8(void *aService,
+                                              int aLen1,
+                                              const void *aStr1,
+                                              int aLen2,
+                                              const void *aStr2);
+
+/**
+ * Custom UTF-8 collating sequence that respects the application's locale.
+ * Comparison is case-insensitive and accent-sensitive.  This is called by
+ * SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @param  aLen2
+ *         The number of bytes in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollationAccentSensitive8(void *aService,
+                                                int aLen1,
+                                                const void *aStr1,
+                                                int aLen2,
+                                                const void *aStr2);
+
+/**
+ * Custom UTF-8 collating sequence that respects the application's locale.
+ * Comparison is case- and accent-sensitive.  This is called by SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @param  aLen2
+ *         The number of bytes in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated char* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollationCaseAccentSensitive8(void *aService,
+                                                    int aLen1,
+                                                    const void *aStr1,
+                                                    int aLen2,
+                                                    const void *aStr2);
+
+/**
+ * Custom UTF-16 collating sequence that respects the application's locale.
+ * Comparison is case- and accent-insensitive.  This is called by SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes (not characters) in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @param  aLen2
+ *         The number of bytes (not characters) in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollation16(void *aService,
+                                  int aLen1,
+                                  const void *aStr1,
+                                  int aLen2,
+                                  const void *aStr2);
+
+/**
+ * Custom UTF-16 collating sequence that respects the application's locale.
+ * Comparison is case-sensitive and accent-insensitive.  This is called by
+ * SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes (not characters) in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @param  aLen2
+ *         The number of bytes (not characters) in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollationCaseSensitive16(void *aService,
+                                               int aLen1,
+                                               const void *aStr1,
+                                               int aLen2,
+                                               const void *aStr2);
+
+/**
+ * Custom UTF-16 collating sequence that respects the application's locale.
+ * Comparison is case-insensitive and accent-sensitive.  This is called by
+ * SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes (not characters) in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @param  aLen2
+ *         The number of bytes (not characters) in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollationAccentSensitive16(void *aService,
+                                                 int aLen1,
+                                                 const void *aStr1,
+                                                 int aLen2,
+                                                 const void *aStr2);
+
+/**
+ * Custom UTF-16 collating sequence that respects the application's locale.
+ * Comparison is case- and accent-sensitive.  This is called by SQLite.
+ *
+ * @param  aService
+ *         The Service that owns the nsICollation used by this collation.
+ * @param  aLen1
+ *         The number of bytes (not characters) in aStr1.
+ * @param  aStr1
+ *         The string to be compared against aStr2.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @param  aLen2
+ *         The number of bytes (not characters) in aStr2.
+ * @param  aStr2
+ *         The string to be compared against aStr1.  It will be passed in by
+ *         SQLite as a non-null-terminated PRUnichar* buffer.
+ * @return aStr1 - aStr2.  That is, if aStr1 < aStr2, returns a negative number.
+ *         If aStr1 > aStr2, returns a positive number.  If aStr1 == aStr2,
+ *         returns 0.
+ */
+NS_HIDDEN_(int) localeCollationCaseAccentSensitive16(void *aService,
+                                                     int aLen1,
+                                                     const void *aStr1,
+                                                     int aLen2,
+                                                     const void *aStr2);
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // _mozilla_storage_SQLCollations_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/SQLiteMutex.h
@@ -0,0 +1,207 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_SQLiteMutex_h_
+#define mozilla_storage_SQLiteMutex_h_
+
+#include "mozilla/BlockingResourceBase.h"
+#include "sqlite3.h"
+
+namespace mozilla {
+namespace storage {
+
+/**
+ * Wrapper class for sqlite3_mutexes.  To be used whenever we want to use a
+ * sqlite3_mutex.
+ *
+ * @warning Never EVER wrap the same sqlite3_mutex with a different SQLiteMutex.
+ *          If you do this, you void the deadlock detector's warranty!
+ */
+class SQLiteMutex : private BlockingResourceBase
+{
+public:
+  /**
+   * Constructs a wrapper for a sqlite3_mutex that has deadlock detecting.
+   *
+   * @param aName
+   *        A name which can be used to reference this mutex.
+   */
+  SQLiteMutex(const char *aName)
+  : BlockingResourceBase(aName, eMutex)
+  , mMutex(NULL)
+  {
+  }
+
+  /**
+   * Sets the mutex that we are wrapping.  We generally do not have access to
+   * our mutex at class construction, so we have to set it once we get access to
+   * it.
+   *
+   * @param aMutex
+   *        The sqlite3_mutex that we are going to wrap.
+   */
+  void initWithMutex(sqlite3_mutex *aMutex)
+  {
+    NS_ASSERTION(aMutex, "You must pass in a valid mutex!");
+    NS_ASSERTION(!mMutex, "A mutex has already been set for this!");
+    mMutex = aMutex;
+  }
+
+#ifndef DEBUG
+  /**
+   * Acquires the mutex.
+   */
+  void lock()
+  {
+    sqlite3_mutex_enter(mMutex);
+  }
+
+  /**
+   * Releases the mutex.
+   */
+  void unlock()
+  {
+    sqlite3_mutex_leave(mMutex);
+  }
+
+  /**
+   * Asserts that the current thread owns the mutex.
+   */
+  void assertCurrentThreadOwns()
+  {
+  }
+
+  /**
+   * Asserts that the current thread does not own the mutex.
+   */
+  void assertNotCurrentThreadOwns()
+  {
+  }
+
+#else
+  void lock()
+  {
+    NS_ASSERTION(mMutex, "No mutex associated with this wrapper!");
+
+    // While SQLite Mutexes may be recursive, in our own code we do not want to
+    // treat them as such.
+    CallStack callContext = CallStack();
+
+    CheckAcquire(callContext);
+    sqlite3_mutex_enter(mMutex);
+    Acquire(callContext); // Call is protected by us holding the mutex.
+  }
+
+  void unlock()
+  {
+    NS_ASSERTION(mMutex, "No mutex associated with this wrapper!");
+
+    // While SQLite Mutexes may be recursive, in our own code we do not want to
+    // treat them as such.
+    Release(); // Call is protected by us holding the mutex.
+    sqlite3_mutex_leave(mMutex);
+  }
+
+  void assertCurrentThreadOwns()
+  {
+    NS_ASSERTION(mMutex, "No mutex associated with this wrapper!");
+    NS_ASSERTION(sqlite3_mutex_held(mMutex),
+                 "Mutex is not held, but we expect it to be!");
+  }
+
+  void assertNotCurrentThreadOwns()
+  {
+    NS_ASSERTION(mMutex, "No mutex associated with this wrapper!");
+    NS_ASSERTION(sqlite3_mutex_notheld(mMutex),
+                 "Mutex is held, but we expect it to not be!");
+  }
+#endif // ifndef DEBUG
+
+private:
+  sqlite3_mutex *mMutex;
+};
+
+/**
+ * Automatically acquires the mutex when it enters scope, and releases it when
+ * it leaves scope.
+ */
+class NS_STACK_CLASS SQLiteMutexAutoLock
+{
+public:
+  SQLiteMutexAutoLock(SQLiteMutex &aMutex)
+  : mMutex(aMutex)
+  {
+    mMutex.lock();
+  }
+
+  ~SQLiteMutexAutoLock()
+  {
+    mMutex.unlock();
+  }
+
+private:
+  SQLiteMutex &mMutex;
+};
+
+/**
+ * Automatically releases the mutex when it enters scope, and acquires it when
+ * it leaves scope.
+ */
+class NS_STACK_CLASS SQLiteMutexAutoUnlock
+{
+public:
+  SQLiteMutexAutoUnlock(SQLiteMutex &aMutex)
+  : mMutex(aMutex)
+  {
+    mMutex.unlock();
+  }
+
+  ~SQLiteMutexAutoUnlock()
+  {
+    mMutex.lock();
+  }
+
+private:
+  SQLiteMutex &mMutex;
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // mozilla_storage_SQLiteMutex_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/StorageBaseStatementInternal.cpp
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "StorageBaseStatementInternal.h"
+
+#include "nsProxyRelease.h"
+
+#include "mozStorageBindingParamsArray.h"
+#include "mozStorageStatementData.h"
+#include "mozStorageAsyncStatementExecution.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// Local Classes
+
+/**
+ * Used to finalize an asynchronous statement on the background thread.
+ */
+class AsyncStatementFinalizer : public nsRunnable
+{
+public:
+  /**
+   * Constructor for the event.
+   *
+   * @param aStatement
+   *        We need the AsyncStatement to be able to get at the sqlite3_stmt;
+   *        we only access/create it on the async thread.
+   * @param aConnection
+   *        We need the connection to know what thread to release the statement
+   *        on.  We release the statement on that thread since releasing the
+   *        statement might end up releasing the connection too.
+   */
+  AsyncStatementFinalizer(StorageBaseStatementInternal *aStatement,
+                          Connection *aConnection)
+  : mStatement(aStatement)
+  , mConnection(aConnection)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    mStatement->internalAsyncFinalize();
+    (void)::NS_ProxyRelease(mConnection->threadOpenedOn, mStatement);
+    return NS_OK;
+  }
+private:
+  // It is vital that this remain an nsCOMPtr for NS_ProxyRelease's benefit.
+  nsCOMPtr<StorageBaseStatementInternal> mStatement;
+  nsRefPtr<Connection> mConnection;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//// StorageBaseStatementInternal
+
+StorageBaseStatementInternal::StorageBaseStatementInternal()
+: mAsyncStatement(NULL)
+{
+}
+
+void
+StorageBaseStatementInternal::asyncFinalize()
+{
+  nsIEventTarget *target = mDBConnection->getAsyncExecutionTarget();
+  if (!target) {
+    // If we cannot get the background thread, we have to assume it has been
+    // shutdown (or is in the process of doing so).  As a result, we should
+    // just finalize it here and now.
+    internalAsyncFinalize();
+  }
+  else {
+    nsCOMPtr<nsIRunnable> event =
+      new AsyncStatementFinalizer(this, mDBConnection);
+
+    // If the dispatching did not go as planned, finalize now.
+    if (!event ||
+        NS_FAILED(target->Dispatch(event, NS_DISPATCH_NORMAL))) {
+      internalAsyncFinalize();
+    }
+  }
+}
+
+void
+StorageBaseStatementInternal::internalAsyncFinalize()
+{
+  if (mAsyncStatement) {
+    (void)::sqlite3_finalize(mAsyncStatement);
+    mAsyncStatement = nsnull;
+  }
+}
+
+NS_IMETHODIMP
+StorageBaseStatementInternal::NewBindingParamsArray(
+  mozIStorageBindingParamsArray **_array
+)
+{
+  nsCOMPtr<mozIStorageBindingParamsArray> array = new BindingParamsArray(this);
+  NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
+
+  array.forget(_array);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+StorageBaseStatementInternal::ExecuteAsync(
+  mozIStorageStatementCallback *aCallback,
+  mozIStoragePendingStatement **_stmt
+)
+{
+  // We used to call Connection::ExecuteAsync but it takes a
+  // mozIStorageBaseStatement signature because it is also a public API.  Since
+  // our 'this' has no static concept of mozIStorageBaseStatement and Connection
+  // would just QI it back across to a StorageBaseStatementInternal and the
+  // actual logic is very simple, we now roll our own.
+  nsTArray<StatementData> stmts(1);
+  StatementData data;
+  nsresult rv = getAsynchronousStatementData(data);
+  NS_ENSURE_SUCCESS(rv, rv);
+  NS_ENSURE_TRUE(stmts.AppendElement(data), NS_ERROR_OUT_OF_MEMORY);
+
+  // Dispatch to the background
+  return AsyncExecuteStatements::execute(stmts, mDBConnection, aCallback,
+                                         _stmt);
+}
+
+NS_IMETHODIMP
+StorageBaseStatementInternal::EscapeStringForLIKE(
+  const nsAString &aValue,
+  const PRUnichar aEscapeChar,
+  nsAString &_escapedString
+)
+{
+  const PRUnichar MATCH_ALL('%');
+  const PRUnichar MATCH_ONE('_');
+
+  _escapedString.Truncate(0);
+
+  for (PRUint32 i = 0; i < aValue.Length(); i++) {
+    if (aValue[i] == aEscapeChar || aValue[i] == MATCH_ALL ||
+        aValue[i] == MATCH_ONE) {
+      _escapedString += aEscapeChar;
+    }
+    _escapedString += aValue[i];
+  }
+  return NS_OK;
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/StorageBaseStatementInternal.h
@@ -0,0 +1,354 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 sts=2 expandtab
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_StorageBaseStatementInternal_h_
+#define mozilla_storage_StorageBaseStatementInternal_h_
+
+#include "nsISupports.h"
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+
+struct sqlite3_stmt;
+class mozIStorageError;
+class mozIStorageBindingParamsArray;
+class mozIStorageBindingParams;
+class mozIStorageStatementCallback;
+class mozIStoragePendingStatement;
+
+namespace mozilla {
+namespace storage {
+
+#define STORAGEBASESTATEMENTINTERNAL_IID \
+  {0xd18856c9, 0xbf07, 0x4ae2, {0x94, 0x5b, 0x1a, 0xdd, 0x49, 0x19, 0x55, 0x2a}}
+
+class Connection;
+struct StatementData;
+
+class AsyncStatementFinalizer;
+
+/**
+ * Implementation-only interface and shared logix mix-in corresponding to
+ * mozIStorageBaseStatement.  Both Statement and AsyncStatement inherit from
+ * this. The interface aspect makes them look the same to implementation innards
+ * that aren't publicly accessible.  The mix-in avoids code duplication in
+ * common implementations of mozIStorageBaseStatement, albeit with some minor
+ * performance/space overhead because we have to use defines to officially
+ * implement the methods on Statement/AsyncStatement (and proxy to this base
+ * class.)
+ */
+class StorageBaseStatementInternal : public nsISupports
+{
+public:
+  NS_DECLARE_STATIC_IID_ACCESSOR(STORAGEBASESTATEMENTINTERNAL_IID)
+
+  /**
+   * @return the connection that this statement belongs to.
+   */
+  Connection *getOwner()
+  {
+    return mDBConnection;
+  }
+
+  /**
+   * Return the asynchronous statement, creating it if required.
+   *
+   * This is for use by the asynchronous execution code for StatementData
+   * created by AsyncStatements.  Statement internally uses this method to
+   * prepopulate StatementData with the sqlite3_stmt.
+   *
+   * @param[out] stmt
+   *             The sqlite3_stmt for asynchronous use.
+   * @return The SQLite result code for creating the statement if created,
+   *         SQLITE_OK if creation was not required.
+   */
+  virtual int getAsyncStatement(sqlite3_stmt **_stmt) = 0;
+
+  /**
+   * Obtains the StatementData needed for asynchronous execution.
+   *
+   * This is for use by Connection to retrieve StatementData from statements
+   * when executeAsync is invoked.
+   *
+   * @param[out] _data
+   *             A reference to a StatementData object that will be populated
+   *             upon successful execution of this method.
+   * @return NS_OK if we were able to assemble the data, failure otherwise.
+   */
+  virtual nsresult getAsynchronousStatementData(StatementData &_data) = 0;
+
+  /**
+   * Construct a new BindingParams to be owned by the provided binding params
+   * array.  This method exists so that BindingParamsArray does not need
+   * factory logic to determine what type of BindingParams to instantiate.
+   *
+   * @param aOwner
+   *        The binding params array to own the newly created binding params.
+   * @return The new mozIStorageBindingParams instance appropriate to the
+   *         underlying statement type.
+   */
+  virtual already_AddRefed<mozIStorageBindingParams> newBindingParams(
+    mozIStorageBindingParamsArray *aOwner
+  ) = 0;
+
+protected: // mix-in bits are protected
+  StorageBaseStatementInternal();
+
+  nsRefPtr<Connection> mDBConnection;
+
+  /**
+   * Our asynchronous statement.
+   *
+   * For Statement this is populated by the first invocation to
+   * getAsyncStatement.
+   *
+   * For AsyncStatement, this is null at creation time and initialized by the
+   * async thread when it calls getAsyncStatement the first time the statement
+   * is executed.  (Or in the event of badly formed SQL, every time.)
+   */
+  sqlite3_stmt *mAsyncStatement;
+
+  /**
+   * Initiate asynchronous finalization by dispatching an event to the
+   * asynchronous thread to finalize mAsyncStatement.  This acquires a reference
+   * to this statement and proxies it back to the connection's owning thread
+   * for release purposes.
+   *
+   * In the event the asynchronous thread is already gone or we otherwise fail
+   * to dispatch an event to it we failover to invoking internalAsyncFinalize
+   * directly.  (That's what the asynchronous finalizer would have called.)
+   *
+   * @note You must not call this method from your destructor because its
+   *       operation assumes we are still alive.  Call internalAsyncFinalize
+   *       directly in that case.
+   */
+  void asyncFinalize();
+
+  /**
+   * Cleanup the async sqlite3_stmt stored in mAsyncStatement if it exists.
+   *
+   * @note Call this from your destructor, call asyncFinalize otherwise.
+   */
+  void internalAsyncFinalize();
+
+  NS_IMETHOD NewBindingParamsArray(mozIStorageBindingParamsArray **_array);
+  NS_IMETHOD ExecuteAsync(mozIStorageStatementCallback *aCallback,
+                          mozIStoragePendingStatement **_stmt);
+  NS_IMETHOD EscapeStringForLIKE(const nsAString &aValue,
+                                 const PRUnichar aEscapeChar,
+                                 nsAString &_escapedString);
+
+  // Needs access to internalAsyncFinalize
+  friend class AsyncStatementFinalizer;
+};
+
+NS_DEFINE_STATIC_IID_ACCESSOR(StorageBaseStatementInternal,
+                              STORAGEBASESTATEMENTINTERNAL_IID)
+
+#define NS_DECL_STORAGEBASESTATEMENTINTERNAL \
+  virtual Connection *getOwner(); \
+  virtual int getAsyncStatement(sqlite3_stmt **_stmt); \
+  virtual nsresult getAsynchronousStatementData(StatementData &_data); \
+  virtual already_AddRefed<mozIStorageBindingParams> newBindingParams( \
+    mozIStorageBindingParamsArray *aOwner);
+
+/**
+ * Helper macro to implement the proxying implementations.  Because we are
+ * implementing methods that are part of mozIStorageBaseStatement and the
+ * implementation classes already use NS_DECL_MOZISTORAGEBASESTATEMENT we don't
+ * need to provide declaration support.
+ */
+#define MIX_IMPL(_class, _optionalGuard, _method, _declArgs, _invokeArgs) \
+  NS_IMETHODIMP _class::_method _declArgs                                 \
+  {                                                                       \
+    _optionalGuard                                                        \
+    return StorageBaseStatementInternal::_method _invokeArgs;             \
+  }
+
+
+/**
+ * Define proxying implementation for the given _class.  If a state invariant
+ * needs to be checked and an early return possibly performed, pass the clause
+ * to use as _optionalGuard.
+ */
+#define MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(_class, _optionalGuard) \
+  MIX_IMPL(_class, _optionalGuard,                                      \
+           NewBindingParamsArray,                                       \
+           (mozIStorageBindingParamsArray **_array),                    \
+           (_array))                                                    \
+  MIX_IMPL(_class, _optionalGuard,                                      \
+           ExecuteAsync,                                                \
+           (mozIStorageStatementCallback *aCallback,                    \
+            mozIStoragePendingStatement **_stmt),                       \
+           (aCallback, _stmt))                                          \
+  MIX_IMPL(_class, _optionalGuard,                                      \
+           EscapeStringForLIKE,                                         \
+           (const nsAString &aValue, const PRUnichar aEscapeChar,       \
+            nsAString &_escapedString),                                 \
+           (aValue, aEscapeChar, _escapedString))
+
+/**
+ * Name-building helper for BIND_GEN_IMPL.
+ */
+#define BIND_NAME_CONCAT(_nameBit, _concatBit) \
+  Bind##_nameBit##_concatBit
+
+/**
+ * We have type-specific convenience methods for C++ implementations in
+ * 3 different forms; 2 by index, 1 by name.  The following macro allows
+ * us to avoid having to define repetitive things by hand.
+ *
+ * Because of limitations of macros and our desire to avoid requiring special
+ * permutations for the null and blob cases (whose argument count varies),
+ * we require that the argument declarations and corresponding invocation
+ * usages are passed in.
+ *
+ * @param _class The class name.
+ * @param _guard The guard clause to inject.
+ * @param _declName The argument list (with parens) for the ByName variants.
+ * @param _declIndex The argument list (with parens) for the index variants.
+ * @param _invArgs The invocation argumment list.
+ */
+#define BIND_GEN_IMPL(_class, _guard, _name, _declName, _declIndex, _invArgs) \
+  NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByName) _declName             \
+  {                                                                           \
+    _guard                                                                    \
+    mozIStorageBindingParams *params = getParams();                           \
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                           \
+    return params->BIND_NAME_CONCAT(_name, ByName) _invArgs;                  \
+  }                                                                           \
+  NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, ByIndex) _declIndex           \
+  {                                                                           \
+    _guard                                                                    \
+    mozIStorageBindingParams *params = getParams();                           \
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                           \
+    return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs;                 \
+  }                                                                           \
+  NS_IMETHODIMP _class::BIND_NAME_CONCAT(_name, Parameter) _declIndex         \
+  {                                                                           \
+    _guard                                                                    \
+    mozIStorageBindingParams *params = getParams();                           \
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);                           \
+    return params->BIND_NAME_CONCAT(_name, ByIndex) _invArgs;                 \
+  }
+
+/**
+ * Implement BindByName/BindByIndex for the given class.
+ *
+ * @param _class The class name.
+ * @param _optionalGuard The guard clause to inject.
+ */
+#define BIND_BASE_IMPLS(_class, _optionalGuard)             \
+  NS_IMETHODIMP _class::BindByName(const nsACString &aName, \
+                                   nsIVariant *aValue)      \
+  {                                                         \
+    _optionalGuard                                          \
+    mozIStorageBindingParams *params = getParams();         \
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);         \
+    return params->BindByName(aName, aValue);               \
+  }                                                         \
+  NS_IMETHODIMP _class::BindByIndex(PRUint32 aIndex,        \
+                                    nsIVariant *aValue)     \
+  {                                                         \
+    _optionalGuard                                          \
+    mozIStorageBindingParams *params = getParams();         \
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);         \
+    return params->BindByIndex(aIndex, aValue);             \
+  }
+
+/**
+ * Define the various Bind*Parameter, Bind*ByIndex, Bind*ByName stubs that just
+ * end up proxying to the params object.
+ */
+#define BOILERPLATE_BIND_PROXIES(_class, _optionalGuard) \
+  BIND_BASE_IMPLS(_class, _optionalGuard)                \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                UTF8String,                              \
+                (const nsACString &aWhere,               \
+                 const nsACString &aValue),              \
+                (PRUint32 aWhere,                        \
+                 const nsACString &aValue),              \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                String,                                  \
+                (const nsACString &aWhere,               \
+                 const nsAString  &aValue),              \
+                (PRUint32 aWhere,                        \
+                 const nsAString  &aValue),              \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                Double,                                  \
+                (const nsACString &aWhere,               \
+                 double aValue),                         \
+                (PRUint32 aWhere,                        \
+                 double aValue),                         \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                Int32,                                   \
+                (const nsACString &aWhere,               \
+                 PRInt32 aValue),                        \
+                (PRUint32 aWhere,                        \
+                 PRInt32 aValue),                        \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                Int64,                                   \
+                (const nsACString &aWhere,               \
+                 PRInt64 aValue),                        \
+                (PRUint32 aWhere,                        \
+                 PRInt64 aValue),                        \
+                (aWhere, aValue))                        \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                Null,                                    \
+                (const nsACString &aWhere),              \
+                (PRUint32 aWhere),                       \
+                (aWhere))                                \
+  BIND_GEN_IMPL(_class, _optionalGuard,                  \
+                Blob,                                    \
+                (const nsACString &aWhere,               \
+                 const PRUint8 *aValue,                  \
+                 PRUint32 aValueSize),                   \
+                (PRUint32 aWhere,                        \
+                 const PRUint8 *aValue,                  \
+                 PRUint32 aValueSize),                   \
+                (aWhere, aValue, aValueSize))
+
+  
+
+} // storage
+} // mozilla
+
+#endif // mozilla_storage_StorageBaseStatementInternal_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/Variant.h
@@ -0,0 +1,410 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *   Drew Willcoxon <adw@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_Variant_h__
+#define mozilla_storage_Variant_h__
+
+#include <utility>
+
+#include "nsIVariant.h"
+#include "nsString.h"
+#include "nsTArray.h"
+
+/**
+ * This class is used by the storage module whenever an nsIVariant needs to be
+ * returned.  We provide traits for the basic sqlite types to make use easier.
+ * The following types map to the indicated sqlite type:
+ * PRInt64   -> INTEGER (use IntegerVariant)
+ * double    -> FLOAT (use FloatVariant)
+ * nsString  -> TEXT (use TextVariant)
+ * nsCString -> TEXT (use UTF8TextVariant)
+ * PRUint8[] -> BLOB (use BlobVariant)
+ * nsnull    -> NULL (use NullVariant)
+ */
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// Base Class
+
+class Variant_base : public nsIVariant
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIVARIANT
+
+protected:
+  virtual ~Variant_base() { }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//// Traits
+
+/**
+ * Generics
+ */
+
+template <typename DataType>
+struct variant_traits
+{
+  static inline PRUint16 type() { return nsIDataType::VTYPE_EMPTY; }
+};
+
+template <typename DataType>
+struct variant_storage_traits
+{
+  typedef DataType ConstructorType;
+  typedef DataType StorageType;
+  static inline StorageType storage_conversion(ConstructorType aData) { return aData; }
+};
+
+#define NO_CONVERSION return NS_ERROR_CANNOT_CONVERT_DATA;
+
+template <typename DataType>
+struct variant_integer_traits
+{
+  typedef typename variant_storage_traits<DataType>::StorageType StorageType;
+  static inline nsresult asInt32(StorageType, PRInt32 *) { NO_CONVERSION }
+  static inline nsresult asInt64(StorageType, PRInt64 *) { NO_CONVERSION }
+};
+
+template <typename DataType>
+struct variant_float_traits
+{
+  typedef typename variant_storage_traits<DataType>::StorageType StorageType;
+  static inline nsresult asDouble(StorageType, double *) { NO_CONVERSION }
+};
+
+template <typename DataType>
+struct variant_text_traits
+{
+  typedef typename variant_storage_traits<DataType>::StorageType StorageType;
+  static inline nsresult asUTF8String(StorageType, nsACString &) { NO_CONVERSION }
+  static inline nsresult asString(StorageType, nsAString &) { NO_CONVERSION }
+};
+
+template <typename DataType>
+struct variant_blob_traits
+{
+  typedef typename variant_storage_traits<DataType>::StorageType StorageType;
+  static inline nsresult asArray(StorageType, PRUint16 *, PRUint32 *, void **)
+  { NO_CONVERSION }
+};
+
+#undef NO_CONVERSION
+
+/**
+ * INTEGER types
+ */
+
+template < >
+struct variant_traits<PRInt64>
+{
+  static inline PRUint16 type() { return nsIDataType::VTYPE_INT64; }
+};
+template < >
+struct variant_integer_traits<PRInt64>
+{
+  static inline nsresult asInt32(PRInt64 aValue,
+                                 PRInt32 *_result)
+  {
+    if (aValue > PR_INT32_MAX || aValue < PR_INT32_MIN)
+      return NS_ERROR_CANNOT_CONVERT_DATA;
+
+    *_result = static_cast<PRInt32>(aValue);
+    return NS_OK;
+  }
+  static inline nsresult asInt64(PRInt64 aValue,
+                                 PRInt64 *_result)
+  {
+    *_result = aValue;
+    return NS_OK;
+  }
+};
+// xpcvariant just calls get double for integers...
+template < >
+struct variant_float_traits<PRInt64>
+{
+  static inline nsresult asDouble(PRInt64 aValue,
+                                  double *_result)
+  {
+    *_result = double(aValue);
+    return NS_OK;
+  }
+};
+
+/**
+ * FLOAT types
+ */
+
+template < >
+struct variant_traits<double>
+{
+  static inline PRUint16 type() { return nsIDataType::VTYPE_DOUBLE; }
+};
+template < >
+struct variant_float_traits<double>
+{
+  static inline nsresult asDouble(double aValue,
+                                  double *_result)
+  {
+    *_result = aValue;
+    return NS_OK;
+  }
+};
+
+/**
+ * TEXT types
+ */
+
+template < >
+struct variant_traits<nsString>
+{
+  static inline PRUint16 type() { return nsIDataType::VTYPE_ASTRING; }
+};
+template < >
+struct variant_storage_traits<nsString>
+{
+  typedef const nsAString & ConstructorType;
+  typedef nsString StorageType;
+  static inline StorageType storage_conversion(ConstructorType aText)
+  {
+    return StorageType(aText);
+  }
+};
+template < >
+struct variant_text_traits<nsString>
+{
+  static inline nsresult asUTF8String(const nsString &aValue,
+                                      nsACString &_result)
+  {
+    CopyUTF16toUTF8(aValue, _result);
+    return NS_OK;
+  }
+  static inline nsresult asString(const nsString &aValue,
+                                  nsAString &_result)
+  {
+    _result = aValue;
+    return NS_OK;
+  }
+};
+
+template < >
+struct variant_traits<nsCString>
+{
+  static inline PRUint16 type() { return nsIDataType::VTYPE_UTF8STRING; }
+};
+template < >
+struct variant_storage_traits<nsCString>
+{
+  typedef const nsACString & ConstructorType;
+  typedef nsCString StorageType;
+  static inline StorageType storage_conversion(ConstructorType aText)
+  {
+    return StorageType(aText);
+  }
+};
+template < >
+struct variant_text_traits<nsCString>
+{
+  static inline nsresult asUTF8String(const nsCString &aValue,
+                                      nsACString &_result)
+  {
+    _result = aValue;
+    return NS_OK;
+  }
+  static inline nsresult asString(const nsCString &aValue,
+                                  nsAString &_result)
+  {
+    CopyUTF8toUTF16(aValue, _result);
+    return NS_OK;
+  }
+};
+
+/**
+ * BLOB types
+ */
+
+template < >
+struct variant_traits<PRUint8[]>
+{
+  static inline PRUint16 type() { return nsIDataType::VTYPE_ARRAY; }
+};
+template < >
+struct variant_storage_traits<PRUint8[]>
+{
+  typedef std::pair<const void *, int> ConstructorType;
+  typedef nsTArray<PRUint8> StorageType;
+  static inline StorageType storage_conversion(ConstructorType aBlob)
+  {
+    nsTArray<PRUint8> data(aBlob.second);
+    (void)data.AppendElements(static_cast<const PRUint8 *>(aBlob.first),
+                              aBlob.second);
+    return data;
+  }
+};
+template < >
+struct variant_blob_traits<PRUint8[]>
+{
+  static inline nsresult asArray(nsTArray<PRUint8> &aData,
+                                 PRUint16 *_type,
+                                 PRUint32 *_size,
+                                 void **_result)
+  {
+    // For empty blobs, we return nsnull.
+    if (aData.Length() == 0) {
+      *_result = nsnull;
+      *_type = nsIDataType::VTYPE_UINT8;
+      *_size = 0;
+      return NS_OK;
+    }
+
+    // Otherwise, we copy the array.
+    *_result = nsMemory::Clone(aData.Elements(), aData.Length() * sizeof(PRUint8));
+    NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
+
+    // Set type and size
+    *_type = nsIDataType::VTYPE_UINT8;
+    *_size = aData.Length();
+    return NS_OK;
+  }
+};
+
+/**
+ * NULL type
+ */
+
+class NullVariant : public Variant_base
+{
+public:
+  NS_IMETHOD GetDataType(PRUint16 *_type)
+  {
+    NS_ENSURE_ARG_POINTER(_type);
+    *_type = nsIDataType::VTYPE_EMPTY;
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetAsAUTF8String(nsACString &_str)
+  {
+    // Return a void string.
+    _str.Truncate(0);
+    _str.SetIsVoid(PR_TRUE);
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetAsAString(nsAString &_str)
+  {
+    // Return a void string.
+    _str.Truncate(0);
+    _str.SetIsVoid(PR_TRUE);
+    return NS_OK;
+  }
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//// Template Implementation
+
+template <typename DataType>
+class Variant : public Variant_base
+{
+public:
+  Variant(typename variant_storage_traits<DataType>::ConstructorType aData)
+    : mData(variant_storage_traits<DataType>::storage_conversion(aData))
+  {
+  }
+
+  NS_IMETHOD GetDataType(PRUint16 *_type)
+  {
+    *_type = variant_traits<DataType>::type();
+    return NS_OK;
+  }
+  NS_IMETHOD GetAsInt32(PRInt32 *_integer)
+  {
+    return variant_integer_traits<DataType>::asInt32(mData, _integer);
+  }
+
+  NS_IMETHOD GetAsInt64(PRInt64 *_integer)
+  {
+    return variant_integer_traits<DataType>::asInt64(mData, _integer);
+  }
+
+  NS_IMETHOD GetAsDouble(double *_double)
+  {
+    return variant_float_traits<DataType>::asDouble(mData, _double);
+  }
+
+  NS_IMETHOD GetAsAUTF8String(nsACString &_str)
+  {
+    return variant_text_traits<DataType>::asUTF8String(mData, _str);
+  }
+
+  NS_IMETHOD GetAsAString(nsAString &_str)
+  {
+    return variant_text_traits<DataType>::asString(mData, _str);
+  }
+
+  NS_IMETHOD GetAsArray(PRUint16 *_type,
+                        nsIID *,
+                        PRUint32 *_size,
+                        void **_data)
+  {
+    return variant_blob_traits<DataType>::asArray(mData, _type, _size, _data);
+  }
+
+private:
+  typename variant_storage_traits<DataType>::StorageType mData;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+//// Handy typedefs!  Use these for the right mapping.
+
+typedef Variant<PRInt64> IntegerVariant;
+typedef Variant<double> FloatVariant;
+typedef Variant<nsString> TextVariant;
+typedef Variant<nsCString> UTF8TextVariant;
+typedef Variant<PRUint8[]> BlobVariant;
+
+} // namespace storage
+} // namespace mozilla
+
+#include "Variant_inl.h"
+
+#endif // mozilla_storage_Variant_h__
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/Variant_inl.h
@@ -0,0 +1,262 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * Note: This file is included by Variant.h.
+ */
+
+#ifndef mozilla_storage_Variant_h__
+#error "Do not include this file directly!"
+#endif
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// Variant_base
+
+inline NS_IMPL_THREADSAFE_ADDREF(Variant_base)
+inline NS_IMPL_THREADSAFE_RELEASE(Variant_base)
+inline NS_IMPL_THREADSAFE_QUERY_INTERFACE1(
+  Variant_base,
+  nsIVariant
+)
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIVariant
+
+inline
+NS_IMETHODIMP
+Variant_base::GetDataType(PRUint16 *_type)
+{
+  NS_ENSURE_ARG_POINTER(_type);
+  *_type = nsIDataType::VTYPE_VOID;
+  return NS_OK;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsInt32(PRInt32 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsInt64(PRInt64 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsDouble(double *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsAUTF8String(nsACString &)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsAString(nsAString &)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsArray(PRUint16 *,
+                         nsIID *,
+                         PRUint32 *,
+                         void **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsInt8(PRUint8 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsInt16(PRInt16 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsUint8(PRUint8 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsUint16(PRUint16 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsUint32(PRUint32 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsUint64(PRUint64 *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsFloat(float *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsBool(PRBool *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsChar(char *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsWChar(PRUnichar *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsID(nsID *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsDOMString(nsAString &)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsString(char **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsWString(PRUnichar **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsISupports(nsISupports **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsInterface(nsIID **,
+                             void **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsACString(nsACString &)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsStringWithSize(PRUint32 *,
+                                  char **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsWStringWithSize(PRUint32 *,
+                                   PRUnichar **)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+inline
+NS_IMETHODIMP
+Variant_base::GetAsJSVal(jsval *)
+{
+  return NS_ERROR_CANNOT_CONVERT_DATA;
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageArgValueArray.cpp
@@ -0,0 +1,236 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsError.h"
+#include "nsMemory.h"
+#include "nsString.h"
+
+#include "mozStoragePrivateHelpers.h"
+#include "mozStorageArgValueArray.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// ArgValueArray
+
+ArgValueArray::ArgValueArray(PRInt32 aArgc,
+                             sqlite3_value **aArgv)
+: mArgc(aArgc)
+, mArgv(aArgv)
+{
+}
+
+NS_IMPL_ISUPPORTS1(
+  ArgValueArray,
+  mozIStorageValueArray
+)
+
+////////////////////////////////////////////////////////////////////////////////
+//// mozIStorageValueArray
+
+NS_IMETHODIMP
+ArgValueArray::GetNumEntries(PRUint32 *_size)
+{
+  *_size = mArgc;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetTypeOfIndex(PRUint32 aIndex,
+                              PRInt32 *_type)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  int t = ::sqlite3_value_type(mArgv[aIndex]);
+  switch (t) {
+    case SQLITE_INTEGER:
+      *_type = VALUE_TYPE_INTEGER;
+      break;
+    case SQLITE_FLOAT:
+      *_type = VALUE_TYPE_FLOAT;
+      break;
+    case SQLITE_TEXT:
+      *_type = VALUE_TYPE_TEXT;
+      break;
+    case SQLITE_BLOB:
+      *_type = VALUE_TYPE_BLOB;
+      break;
+    case SQLITE_NULL:
+      *_type = VALUE_TYPE_NULL;
+      break;
+    default:
+      return NS_ERROR_FAILURE;
+  }
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetInt32(PRUint32 aIndex,
+                        PRInt32 *_value)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  *_value = ::sqlite3_value_int(mArgv[aIndex]);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetInt64(PRUint32 aIndex,
+                        PRInt64 *_value)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  *_value = ::sqlite3_value_int64(mArgv[aIndex]);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetDouble(PRUint32 aIndex,
+                         double *_value)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  *_value = ::sqlite3_value_double(mArgv[aIndex]);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetUTF8String(PRUint32 aIndex,
+                             nsACString &_value)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  if (::sqlite3_value_type(mArgv[aIndex]) == SQLITE_NULL) {
+    // NULL columns should have IsVoid set to distinguish them from an empty
+    // string.
+    _value.Truncate(0);
+    _value.SetIsVoid(PR_TRUE);
+  }
+  else {
+    _value.Assign(reinterpret_cast<const char *>(::sqlite3_value_text(mArgv[aIndex])),
+                  ::sqlite3_value_bytes(mArgv[aIndex]));
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetString(PRUint32 aIndex,
+                         nsAString &_value)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  if (::sqlite3_value_type(mArgv[aIndex]) == SQLITE_NULL) {
+    // NULL columns should have IsVoid set to distinguish them from an empty
+    // string.
+    _value.Truncate(0);
+    _value.SetIsVoid(PR_TRUE);
+  } else {
+    _value.Assign(static_cast<const PRUnichar *>(::sqlite3_value_text16(mArgv[aIndex])),
+                  ::sqlite3_value_bytes16(mArgv[aIndex]) / 2);
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetBlob(PRUint32 aIndex,
+                       PRUint32 *_size,
+                       PRUint8 **_blob)
+{
+  ENSURE_INDEX_VALUE(aIndex, mArgc);
+
+  int size = ::sqlite3_value_bytes(mArgv[aIndex]);
+  void *blob = nsMemory::Clone(::sqlite3_value_blob(mArgv[aIndex]), size);
+  NS_ENSURE_TRUE(blob, NS_ERROR_OUT_OF_MEMORY);
+
+  *_blob = static_cast<PRUint8 *>(blob);
+  *_size = size;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetIsNull(PRUint32 aIndex,
+                         PRBool *_isNull)
+{
+  // GetTypeOfIndex will check aIndex for us, so we don't have to.
+  PRInt32 type;
+  nsresult rv = GetTypeOfIndex(aIndex, &type);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *_isNull = (type == VALUE_TYPE_NULL);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetSharedUTF8String(PRUint32 aIndex,
+                                   PRUint32 *_length,
+                                   const char **_string)
+{
+  if (_length)
+    *_length = ::sqlite3_value_bytes(mArgv[aIndex]);
+
+  *_string = reinterpret_cast<const char *>(::sqlite3_value_text(mArgv[aIndex]));
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetSharedString(PRUint32 aIndex,
+                               PRUint32 *_length,
+                               const PRUnichar **_string)
+{
+  if (_length)
+    *_length = ::sqlite3_value_bytes(mArgv[aIndex]);
+
+  *_string = static_cast<const PRUnichar *>(::sqlite3_value_text16(mArgv[aIndex]));
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+ArgValueArray::GetSharedBlob(PRUint32 aIndex,
+                             PRUint32 *_size,
+                             const PRUint8 **_blob)
+{
+  *_size = ::sqlite3_value_bytes(mArgv[aIndex]);
+  *_blob = static_cast<const PRUint8 *>(::sqlite3_value_blob(mArgv[aIndex]));
+  return NS_OK;
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageArgValueArray.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _mozStorageArgValueArray_h_
+#define _mozStorageArgValueArray_h_
+
+#include "mozIStorageValueArray.h"
+
+#include "sqlite3.h"
+
+namespace mozilla {
+namespace storage {
+
+class ArgValueArray : public mozIStorageValueArray
+{
+public:
+  ArgValueArray(PRInt32 aArgc, sqlite3_value **aArgv);
+
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGEVALUEARRAY
+
+private:
+  PRUint32 mArgc;
+  sqlite3_value **mArgv;
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // _mozStorageArgValueArray_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatement.cpp
@@ -0,0 +1,452 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozStorage.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *   John Zhang <jzhang@aptana.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <limits.h>
+#include <stdio.h>
+
+#include "nsError.h"
+#include "nsMemory.h"
+#include "nsProxyRelease.h"
+#include "nsThreadUtils.h"
+#include "nsIClassInfoImpl.h"
+#include "nsIProgrammingLanguage.h"
+#include "Variant.h"
+
+#include "mozIStorageError.h"
+
+#include "mozStorageBindingParams.h"
+#include "mozStorageConnection.h"
+#include "mozStorageAsyncStatementJSHelper.h"
+#include "mozStorageAsyncStatementParams.h"
+#include "mozStoragePrivateHelpers.h"
+#include "mozStorageStatementRow.h"
+#include "mozStorageStatement.h"
+
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+extern PRLogModuleInfo *gStorageLog;
+#endif
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIClassInfo
+
+NS_IMPL_CI_INTERFACE_GETTER4(
+  AsyncStatement
+, mozIStorageAsyncStatement
+, mozIStorageBaseStatement
+, mozIStorageBindingParams
+, mozilla::storage::StorageBaseStatementInternal
+)
+
+class AsyncStatementClassInfo : public nsIClassInfo
+{
+public:
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHODIMP
+  GetInterfaces(PRUint32 *_count, nsIID ***_array)
+  {
+    return NS_CI_INTERFACE_GETTER_NAME(AsyncStatement)(_count, _array);
+  }
+
+  NS_IMETHODIMP
+  GetHelperForLanguage(PRUint32 aLanguage, nsISupports **_helper)
+  {
+    if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
+      static AsyncStatementJSHelper sJSHelper;
+      *_helper = &sJSHelper;
+      return NS_OK;
+    }
+
+    *_helper = nsnull;
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  GetContractID(char **_contractID)
+  {
+    *_contractID = nsnull;
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  GetClassDescription(char **_desc)
+  {
+    *_desc = nsnull;
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  GetClassID(nsCID **_id)
+  {
+    *_id = nsnull;
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  GetImplementationLanguage(PRUint32 *_language)
+  {
+    *_language = nsIProgrammingLanguage::CPLUSPLUS;
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  GetFlags(PRUint32 *_flags)
+  {
+    *_flags = nsnull;
+    return NS_OK;
+  }
+
+  NS_IMETHODIMP
+  GetClassIDNoAlloc(nsCID *_cid)
+  {
+    return NS_ERROR_NOT_AVAILABLE;
+  }
+};
+
+NS_IMETHODIMP_(nsrefcnt) AsyncStatementClassInfo::AddRef() { return 2; }
+NS_IMETHODIMP_(nsrefcnt) AsyncStatementClassInfo::Release() { return 1; }
+NS_IMPL_QUERY_INTERFACE1(AsyncStatementClassInfo, nsIClassInfo)
+
+static AsyncStatementClassInfo sAsyncStatementClassInfo;
+
+////////////////////////////////////////////////////////////////////////////////
+//// AsyncStatement
+
+AsyncStatement::AsyncStatement()
+: StorageBaseStatementInternal()
+, mFinalized(false)
+{
+}
+
+nsresult
+AsyncStatement::initialize(Connection *aDBConnection,
+                           const nsACString &aSQLStatement)
+{
+  NS_ASSERTION(aDBConnection, "No database connection given!");
+  NS_ASSERTION(aDBConnection->GetNativeConnection(),
+               "We should never be called with a null sqlite3 database!");
+
+  mDBConnection = aDBConnection;
+  mSQLString = aSQLStatement;
+
+#ifdef PR_LOGGING
+  PR_LOG(gStorageLog, PR_LOG_NOTICE, ("Inited async statement '%s' (0x%p)",
+                                      mSQLString.get()));
+#endif
+
+#ifdef DEBUG
+  // We want to try and test for LIKE and that consumers are using
+  // escapeStringForLIKE instead of just trusting user input.  The idea to
+  // check to see if they are binding a parameter after like instead of just
+  // using a string.  We only do this in debug builds because it's expensive!
+  const nsCaseInsensitiveCStringComparator c;
+  nsACString::const_iterator start, end, e;
+  aSQLStatement.BeginReading(start);
+  aSQLStatement.EndReading(end);
+  e = end;
+  while (::FindInReadable(NS_LITERAL_CSTRING(" LIKE"), start, e, c)) {
+    // We have a LIKE in here, so we perform our tests
+    // FindInReadable moves the iterator, so we have to get a new one for
+    // each test we perform.
+    nsACString::const_iterator s1, s2, s3;
+    s1 = s2 = s3 = start;
+
+    if (!(::FindInReadable(NS_LITERAL_CSTRING(" LIKE ?"), s1, end, c) ||
+          ::FindInReadable(NS_LITERAL_CSTRING(" LIKE :"), s2, end, c) ||
+          ::FindInReadable(NS_LITERAL_CSTRING(" LIKE @"), s3, end, c))) {
+      // At this point, we didn't find a LIKE statement followed by ?, :,
+      // or @, all of which are valid characters for binding a parameter.
+      // We will warn the consumer that they may not be safely using LIKE.
+      NS_WARNING("Unsafe use of LIKE detected!  Please ensure that you "
+                 "are using mozIStorageAsyncStatement::escapeStringForLIKE "
+                 "and that you are binding that result to the statement "
+                 "to prevent SQL injection attacks.");
+    }
+
+    // resetting start and e
+    start = e;
+    e = end;
+  }
+#endif
+
+  return NS_OK;
+}
+
+mozIStorageBindingParams *
+AsyncStatement::getParams()
+{
+  nsresult rv;
+
+  // If we do not have an array object yet, make it.
+  if (!mParamsArray) {
+    nsCOMPtr<mozIStorageBindingParamsArray> array;
+    rv = NewBindingParamsArray(getter_AddRefs(array));
+    NS_ENSURE_SUCCESS(rv, nsnull);
+
+    mParamsArray = static_cast<BindingParamsArray *>(array.get());
+  }
+
+  // If there isn't already any rows added, we'll have to add one to use.
+  if (mParamsArray->length() == 0) {
+    nsRefPtr<AsyncBindingParams> params(new AsyncBindingParams(mParamsArray));
+    NS_ENSURE_TRUE(params, nsnull);
+
+    rv = mParamsArray->AddParams(params);
+    NS_ENSURE_SUCCESS(rv, nsnull);
+
+    // We have to unlock our params because AddParams locks them.  This is safe
+    // because no reference to the params object was, or ever will be given out.
+    params->unlock(nsnull);
+
+    // We also want to lock our array at this point - we don't want anything to
+    // be added to it.
+    mParamsArray->lock();
+  }
+
+  return *mParamsArray->begin();
+}
+
+/**
+ * If we are here then we know there are no pending async executions relying on
+ * us (StatementData holds a reference to us; this also goes for our own
+ * AsyncStatementFinalizer which proxies its release to the calling thread) and
+ * so it is always safe to destroy our sqlite3_stmt if one exists.  We can be
+ * destroyed on the caller thread by garbage-collection/reference counting or on
+ * the async thread by the last execution of a statement that already lost its
+ * main-thread refs.
+ */
+AsyncStatement::~AsyncStatement()
+{
+  internalAsyncFinalize();
+  cleanupJSHelpers();
+
+  // If we are getting destroyed on the wrong thread, proxy the connection
+  // release to the right thread.  I'm not sure why we do this.
+  PRBool onCallingThread = PR_FALSE;
+  (void)mDBConnection->threadOpenedOn->IsOnCurrentThread(&onCallingThread);
+  if (!onCallingThread) {
+    // NS_ProxyRelase only magic forgets for us if mDBConnection is an
+    // nsCOMPtr.  Which it is not; it's an nsRefPtr.
+    Connection *forgottenConn = nsnull;
+    mDBConnection.swap(forgottenConn);
+    (void)::NS_ProxyRelease(mDBConnection->threadOpenedOn, forgottenConn);
+  }
+}
+
+void
+AsyncStatement::cleanupJSHelpers()
+{
+  // We are considered dead at this point, so any wrappers for row or params
+  // need to lose their reference to us.
+  if (mStatementParamsHolder) {
+    nsCOMPtr<nsIXPConnectWrappedNative> wrapper =
+      do_QueryInterface(mStatementParamsHolder);
+    nsCOMPtr<mozIStorageStatementParams> iParams =
+      do_QueryWrappedNative(wrapper);
+    AsyncStatementParams *params =
+      static_cast<AsyncStatementParams *>(iParams.get());
+    params->mStatement = nsnull;
+    mStatementParamsHolder = nsnull;
+  }
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsISupports
+
+NS_IMPL_THREADSAFE_ADDREF(AsyncStatement)
+NS_IMPL_THREADSAFE_RELEASE(AsyncStatement)
+
+NS_INTERFACE_MAP_BEGIN(AsyncStatement)
+  NS_INTERFACE_MAP_ENTRY(mozIStorageAsyncStatement)
+  NS_INTERFACE_MAP_ENTRY(mozIStorageBaseStatement)
+  NS_INTERFACE_MAP_ENTRY(mozIStorageBindingParams)
+  NS_INTERFACE_MAP_ENTRY(mozilla::storage::StorageBaseStatementInternal)
+  if (aIID.Equals(NS_GET_IID(nsIClassInfo))) {
+    foundInterface = static_cast<nsIClassInfo *>(&sAsyncStatementClassInfo);
+  }
+  else
+  NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozIStorageAsyncStatement)
+NS_INTERFACE_MAP_END
+
+
+////////////////////////////////////////////////////////////////////////////////
+//// StorageBaseStatementInternal
+
+Connection *
+AsyncStatement::getOwner()
+{
+  return mDBConnection;
+}
+
+int
+AsyncStatement::getAsyncStatement(sqlite3_stmt **_stmt)
+{
+#ifdef DEBUG
+  // Make sure we are never called on the connection's owning thread.
+  PRBool onOpenedThread = PR_FALSE;
+  (void)mDBConnection->threadOpenedOn->IsOnCurrentThread(&onOpenedThread);
+  NS_ASSERTION(!onOpenedThread,
+               "We should only be called on the async thread!");
+#endif
+
+  if (!mAsyncStatement) {
+    int rc = ::sqlite3_prepare_v2(mDBConnection->GetNativeConnection(),
+                                  mSQLString.get(), -1,
+                                  &mAsyncStatement, NULL);
+    if (rc != SQLITE_OK) {
+#ifdef PR_LOGGING
+      PR_LOG(gStorageLog, PR_LOG_ERROR,
+             ("Sqlite statement prepare error: %d '%s'", rc,
+              ::sqlite3_errmsg(mDBConnection->GetNativeConnection())));
+      PR_LOG(gStorageLog, PR_LOG_ERROR,
+             ("Statement was: '%s'", mSQLString.get()));
+#endif
+      *_stmt = nsnull;
+      return rc;
+    }
+
+#ifdef PR_LOGGING
+    PR_LOG(gStorageLog, PR_LOG_NOTICE, ("Initialized statement '%s' (0x%p)",
+                                        mSQLString.get(),
+                                        mAsyncStatement));
+#endif
+  }
+
+  *_stmt = mAsyncStatement;
+  return SQLITE_OK;
+}
+
+nsresult
+AsyncStatement::getAsynchronousStatementData(StatementData &_data)
+{
+  if (mFinalized)
+    return NS_ERROR_UNEXPECTED;
+
+  // Pass null for the sqlite3_stmt; it will be requested on demand from the
+  // async thread.
+  _data = StatementData(nsnull, bindingParamsArray(), this);
+
+  return NS_OK;
+}
+
+already_AddRefed<mozIStorageBindingParams>
+AsyncStatement::newBindingParams(mozIStorageBindingParamsArray *aOwner)
+{
+  if (mFinalized)
+    return nsnull;
+
+  nsCOMPtr<mozIStorageBindingParams> params(new AsyncBindingParams(aOwner));
+  return params.forget();
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//// mozIStorageAsyncStatement
+
+// (nothing is specific to mozIStorageAsyncStatement)
+
+////////////////////////////////////////////////////////////////////////////////
+//// StorageBaseStatementInternal
+
+// proxy to StorageBaseStatementInternal using its define helper.
+MIXIN_IMPL_STORAGEBASESTATEMENTINTERNAL(
+  AsyncStatement,
+  if (mFinalized) return NS_ERROR_UNEXPECTED;)
+
+NS_IMETHODIMP
+AsyncStatement::Finalize()
+{
+  if (mFinalized)
+    return NS_OK;
+
+  mFinalized = true;
+
+#ifdef PR_LOGGING
+  PR_LOG(gStorageLog, PR_LOG_NOTICE, ("Finalizing statement '%s'",
+                                      mSQLString.get()));
+#endif
+
+  asyncFinalize();
+  cleanupJSHelpers();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncStatement::BindParameters(mozIStorageBindingParamsArray *aParameters)
+{
+  if (mFinalized)
+    return NS_ERROR_UNEXPECTED;
+
+  BindingParamsArray *array = static_cast<BindingParamsArray *>(aParameters);
+  if (array->getOwner() != this)
+    return NS_ERROR_UNEXPECTED;
+
+  mParamsArray = array;
+  mParamsArray->lock();
+
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncStatement::GetState(PRInt32 *_state)
+{
+  if (mFinalized)
+    *_state = MOZ_STORAGE_STATEMENT_INVALID;
+  else
+    *_state = MOZ_STORAGE_STATEMENT_READY;
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//// mozIStorageBindingParams
+
+BOILERPLATE_BIND_PROXIES(
+  AsyncStatement, 
+  if (mFinalized) return NS_ERROR_UNEXPECTED;)
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatement.h
@@ -0,0 +1,145 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_mozStorageAsyncStatement_h_
+#define mozilla_storage_mozStorageAsyncStatement_h_
+
+#include "nsAutoPtr.h"
+#include "nsString.h"
+
+#include "nsTArray.h"
+
+#include "mozStorageBindingParamsArray.h"
+#include "mozStorageStatementData.h"
+#include "mozIStorageAsyncStatement.h"
+#include "StorageBaseStatementInternal.h"
+
+class nsIXPConnectJSObjectHolder;
+struct sqlite3_stmt;
+
+namespace mozilla {
+namespace storage {
+
+class AsyncStatementJSHelper;
+class Connection;
+
+class AsyncStatement : public mozIStorageAsyncStatement
+                     , public StorageBaseStatementInternal
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGEASYNCSTATEMENT
+  NS_DECL_MOZISTORAGEBASESTATEMENT
+  NS_DECL_MOZISTORAGEBINDINGPARAMS
+  NS_DECL_STORAGEBASESTATEMENTINTERNAL
+
+  AsyncStatement();
+
+  /**
+   * Initializes the object on aDBConnection by preparing the SQL statement
+   * given by aSQLStatement.
+   *
+   * @param aDBConnection
+   *        The Connection object this statement is associated with.
+   * @param aSQLStatement
+   *        The SQL statement to prepare that this object will represent.
+   */
+  nsresult initialize(Connection *aDBConnection,
+                      const nsACString &aSQLStatement);
+
+  /**
+   * Obtains and transfers ownership of the array of parameters that are bound
+   * to this statment.  This can be null.
+   */
+  inline already_AddRefed<BindingParamsArray> bindingParamsArray()
+  {
+    return mParamsArray.forget();
+  }
+
+
+private:
+  ~AsyncStatement();
+
+  /**
+   * Clean up the references JS helpers hold to us.  For cycle-avoidance reasons
+   * they do not hold reference-counted references to us, so it is important
+   * we do this.
+   */
+  void cleanupJSHelpers();
+
+  /**
+   * @return a pointer to the BindingParams object to use with our Bind*
+   *         method.
+   */
+  mozIStorageBindingParams *getParams();
+
+  /**
+   * The SQL string as passed by the user.  We store it because we create the
+   * async statement on-demand on the async thread.
+   */
+  nsCString mSQLString;
+
+  /**
+   * Holds the array of parameters to bind to this statement when we execute
+   * it asynchronously.
+   */
+  nsRefPtr<BindingParamsArray> mParamsArray;
+
+  /**
+   * Caches the JS 'params' helper for this statement.
+   */
+  nsCOMPtr<nsIXPConnectJSObjectHolder> mStatementParamsHolder;
+
+  /**
+   * Have we been explicitly finalized by the user?
+   */
+  bool mFinalized;
+
+  /**
+   * Required for access to private mStatementParamsHolder field by
+   * AsyncStatementJSHelper::getParams.
+   */
+  friend class AsyncStatementJSHelper;
+};
+
+} // storage
+} // mozilla
+
+#endif // mozilla_storage_mozStorageAsyncStatement_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatementExecution.cpp
@@ -0,0 +1,615 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation. 
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsAutoPtr.h"
+#include "prtime.h"
+
+#include "sqlite3.h"
+
+#include "mozIStorageStatementCallback.h"
+#include "mozStorageBindingParams.h"
+#include "mozStorageHelper.h"
+#include "mozStorageResultSet.h"
+#include "mozStorageRow.h"
+#include "mozStorageConnection.h"
+#include "mozStorageError.h"
+#include "mozStoragePrivateHelpers.h"
+#include "mozStorageStatementData.h"
+#include "mozStorageAsyncStatementExecution.h"
+
+namespace mozilla {
+namespace storage {
+
+/**
+ * The following constants help batch rows into result sets.
+ * MAX_MILLISECONDS_BETWEEN_RESULTS was chosen because any user-based task that
+ * takes less than 200 milliseconds is considered to feel instantaneous to end
+ * users.  MAX_ROWS_PER_RESULT was arbitrarily chosen to reduce the number of
+ * dispatches to calling thread, while also providing reasonably-sized sets of
+ * data for consumers.  Both of these constants are used because we assume that
+ * consumers are trying to avoid blocking their execution thread for long
+ * periods of time, and dispatching many small events to the calling thread will
+ * end up blocking it.
+ */
+#define MAX_MILLISECONDS_BETWEEN_RESULTS 75
+#define MAX_ROWS_PER_RESULT 15
+
+////////////////////////////////////////////////////////////////////////////////
+//// Local Classes
+
+namespace {
+
+typedef AsyncExecuteStatements::ExecutionState ExecutionState;
+
+/**
+ * Notifies a callback with a result set.
+ */
+class CallbackResultNotifier : public nsRunnable
+{
+public:
+  CallbackResultNotifier(mozIStorageStatementCallback *aCallback,
+                         mozIStorageResultSet *aResults,
+                         AsyncExecuteStatements *aEventStatus) :
+      mCallback(aCallback)
+    , mResults(aResults)
+    , mEventStatus(aEventStatus)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    NS_ASSERTION(mCallback, "Trying to notify about results without a callback!");
+
+    if (mEventStatus->shouldNotify())
+      (void)mCallback->HandleResult(mResults);
+
+    return NS_OK;
+  }
+
+private:
+  mozIStorageStatementCallback *mCallback;
+  nsCOMPtr<mozIStorageResultSet> mResults;
+  nsRefPtr<AsyncExecuteStatements> mEventStatus;
+};
+
+/**
+ * Notifies the calling thread that an error has occurred.
+ */
+class ErrorNotifier : public nsRunnable
+{
+public:
+  ErrorNotifier(mozIStorageStatementCallback *aCallback,
+                mozIStorageError *aErrorObj,
+                AsyncExecuteStatements *aEventStatus) :
+      mCallback(aCallback)
+    , mErrorObj(aErrorObj)
+    , mEventStatus(aEventStatus)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    if (mEventStatus->shouldNotify() && mCallback)
+      (void)mCallback->HandleError(mErrorObj);
+
+    return NS_OK;
+  }
+
+private:
+  mozIStorageStatementCallback *mCallback;
+  nsCOMPtr<mozIStorageError> mErrorObj;
+  nsRefPtr<AsyncExecuteStatements> mEventStatus;
+};
+
+/**
+ * Notifies the calling thread that the statement has finished executing.  Keeps
+ * the AsyncExecuteStatements instance alive long enough so that it does not
+ * get destroyed on the async thread if there are no other references alive.
+ */
+class CompletionNotifier : public nsRunnable
+{
+public:
+  /**
+   * This takes ownership of the callback.  It is released on the thread this is
+   * dispatched to (which should always be the calling thread).
+   */
+  CompletionNotifier(mozIStorageStatementCallback *aCallback,
+                     ExecutionState aReason,
+                     AsyncExecuteStatements *aKeepAsyncAlive)
+    : mKeepAsyncAlive(aKeepAsyncAlive)
+    , mCallback(aCallback)
+    , mReason(aReason)
+  {
+  }
+
+  NS_IMETHOD Run()
+  {
+    if (mCallback) {
+      (void)mCallback->HandleCompletion(mReason);
+      NS_RELEASE(mCallback);
+    }
+
+    return NS_OK;
+  }
+
+private:
+  nsRefPtr<AsyncExecuteStatements> mKeepAsyncAlive;
+  mozIStorageStatementCallback *mCallback;
+  ExecutionState mReason;
+};
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//// AsyncExecuteStatements
+
+/* static */
+nsresult
+AsyncExecuteStatements::execute(StatementDataArray &aStatements,
+                                Connection *aConnection,
+                                mozIStorageStatementCallback *aCallback,
+                                mozIStoragePendingStatement **_stmt)
+{
+  // Create our event to run in the background
+  nsRefPtr<AsyncExecuteStatements> event =
+    new AsyncExecuteStatements(aStatements, aConnection, aCallback);
+  NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
+
+  // Dispatch it to the background
+  nsIEventTarget *target = aConnection->getAsyncExecutionTarget();
+  NS_ENSURE_TRUE(target, NS_ERROR_NOT_AVAILABLE);
+  nsresult rv = target->Dispatch(event, NS_DISPATCH_NORMAL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Return it as the pending statement object and track it.
+  NS_ADDREF(*_stmt = event);
+  return NS_OK;
+}
+
+AsyncExecuteStatements::AsyncExecuteStatements(StatementDataArray &aStatements,
+                                               Connection *aConnection,
+                                               mozIStorageStatementCallback *aCallback)
+: mConnection(aConnection)
+, mTransactionManager(nsnull)
+, mCallback(aCallback)
+, mCallingThread(::do_GetCurrentThread())
+, mMaxWait(TimeDuration::FromMilliseconds(MAX_MILLISECONDS_BETWEEN_RESULTS))
+, mIntervalStart(TimeStamp::Now())
+, mState(PENDING)
+, mCancelRequested(false)
+, mMutex(aConnection->sharedAsyncExecutionMutex)
+, mDBMutex(aConnection->sharedDBMutex)
+{
+  (void)mStatements.SwapElements(aStatements);
+  NS_ASSERTION(mStatements.Length(), "We weren't given any statements!");
+  NS_IF_ADDREF(mCallback);
+}
+
+bool
+AsyncExecuteStatements::shouldNotify()
+{
+#ifdef DEBUG
+  mMutex.AssertNotCurrentThreadOwns();
+
+  PRBool onCallingThread = PR_FALSE;
+  (void)mCallingThread->IsOnCurrentThread(&onCallingThread);
+  NS_ASSERTION(onCallingThread, "runEvent not running on the calling thread!");
+#endif
+
+  // We do not need to acquire mMutex here because it can only ever be written
+  // to on the calling thread, and the only thread that can call us is the
+  // calling thread, so we know that our access is serialized.
+  return !mCancelRequested;
+}
+
+bool
+AsyncExecuteStatements::bindExecuteAndProcessStatement(StatementData &aData,
+                                                       bool aLastStatement)
+{
+  mMutex.AssertNotCurrentThreadOwns();
+
+  sqlite3_stmt *aStatement;
+  // This cannot fail; we are only called if it's available.
+  (void)aData.getSqliteStatement(&aStatement);
+  BindingParamsArray *paramsArray(aData);
+
+  // Iterate through all of our parameters, bind them, and execute.
+  bool continueProcessing = true;
+  BindingParamsArray::iterator itr = paramsArray->begin();
+  BindingParamsArray::iterator end = paramsArray->end();
+  while (itr != end && continueProcessing) {
+    // Bind the data to our statement.
+    nsCOMPtr<IStorageBindingParamsInternal> bindingInternal = 
+      do_QueryInterface(*itr);
+    nsCOMPtr<mozIStorageError> error = bindingInternal->bind(aStatement);
+    if (error) {
+      // Set our error state.
+      mState = ERROR;
+
+      // And notify.
+      (void)notifyError(error);
+      return false;
+    }
+
+    // Advance our iterator, execute, and then process the statement.
+    itr++;
+    bool lastStatement = aLastStatement && itr == end;
+    continueProcessing = executeAndProcessStatement(aStatement, lastStatement);
+
+    // Always reset our statement.
+    (void)::sqlite3_reset(aStatement);
+  }
+
+  return continueProcessing;
+}
+
+bool
+AsyncExecuteStatements::executeAndProcessStatement(sqlite3_stmt *aStatement,
+                                                   bool aLastStatement)
+{
+  mMutex.AssertNotCurrentThreadOwns();
+
+  // Execute our statement
+  bool hasResults;
+  do {
+    hasResults = executeStatement(aStatement);
+
+    // If we had an error, bail.
+    if (mState == ERROR)
+      return false;
+
+    // If we have been canceled, there is no point in going on...
+    {
+      MutexAutoLock lockedScope(mMutex);
+      if (mCancelRequested) {
+        mState = CANCELED;
+        return false;
+      }
+    }
+
+    // Build our result set and notify if we got anything back and have a
+    // callback to notify.
+    if (mCallback && hasResults &&
+        NS_FAILED(buildAndNotifyResults(aStatement))) {
+      // We had an error notifying, so we notify on error and stop processing.
+      mState = ERROR;
+
+      // Notify, and stop processing statements.
+      (void)notifyError(mozIStorageError::ERROR,
+                        "An error occurred while notifying about results");
+
+      return false;
+    }
+  } while (hasResults);
+
+#ifdef DEBUG
+  // Check to make sure that this statement was smart about what it did.
+  checkAndLogStatementPerformance(aStatement);
+#endif
+
+  // If we are done, we need to set our state accordingly while we still hold
+  // our mutex.  We would have already returned if we were canceled or had
+  // an error at this point.
+  if (aLastStatement)
+    mState = COMPLETED;
+
+  return true;
+}
+
+bool
+AsyncExecuteStatements::executeStatement(sqlite3_stmt *aStatement)
+{
+  mMutex.AssertNotCurrentThreadOwns();
+
+  while (true) {
+    // lock the sqlite mutex so sqlite3_errmsg cannot change
+    SQLiteMutexAutoLock lockedScope(mDBMutex);
+
+    int rc = ::sqlite3_step(aStatement);
+    // Stop if we have no more results.
+    if (rc == SQLITE_DONE)
+      return false;
+
+    // If we got results, we can return now.
+    if (rc == SQLITE_ROW)
+      return true;
+
+    // Some errors are not fatal, and we can handle them and continue.
+    if (rc == SQLITE_BUSY) {
+      // Don't hold the lock while we call outside our module.
+      SQLiteMutexAutoUnlock unlockedScope(mDBMutex);
+
+      // Yield, and try again
+      (void)::PR_Sleep(PR_INTERVAL_NO_WAIT);
+      continue;
+    }
+
+    // Set an error state.
+    mState = ERROR;
+
+    // Construct the error message before giving up the mutex (which we cannot
+    // hold during the call to notifyError).
+    sqlite3 *db = mConnection->GetNativeConnection();
+    nsCOMPtr<mozIStorageError> errorObj(new Error(rc, ::sqlite3_errmsg(db)));
+    // We cannot hold the DB mutex while calling notifyError.
+    SQLiteMutexAutoUnlock unlockedScope(mDBMutex);
+    (void)notifyError(errorObj);
+
+    // Finally, indicate that we should stop processing.
+    return false;
+  }
+}
+
+nsresult
+AsyncExecuteStatements::buildAndNotifyResults(sqlite3_stmt *aStatement)
+{
+  NS_ASSERTION(mCallback, "Trying to dispatch results without a callback!");
+  mMutex.AssertNotCurrentThreadOwns();
+
+  // Build result object if we need it.
+  if (!mResultSet)
+    mResultSet = new ResultSet();
+  NS_ENSURE_TRUE(mResultSet, NS_ERROR_OUT_OF_MEMORY);
+
+  nsRefPtr<Row> row(new Row());
+  NS_ENSURE_TRUE(row, NS_ERROR_OUT_OF_MEMORY);
+
+  nsresult rv = row->initialize(aStatement);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = mResultSet->add(row);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // If we have hit our maximum number of allowed results, or if we have hit
+  // the maximum amount of time we want to wait for results, notify the
+  // calling thread about it.
+  TimeStamp now = TimeStamp::Now();
+  TimeDuration delta = now - mIntervalStart;
+  if (mResultSet->rows() >= MAX_ROWS_PER_RESULT || delta > mMaxWait) {
+    // Notify the caller
+    rv = notifyResults();
+    if (NS_FAILED(rv))
+      return NS_OK; // we'll try again with the next result
+
+    // Reset our start time
+    mIntervalStart = now;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+AsyncExecuteStatements::notifyComplete()
+{
+  mMutex.AssertNotCurrentThreadOwns();
+  NS_ASSERTION(mState != PENDING,
+               "Still in a pending state when calling Complete!");
+
+  // Finalize our statements before we try to commit or rollback.  If we are
+  // canceling and have statements that think they have pending work, the
+  // rollback will fail.
+  for (PRUint32 i = 0; i < mStatements.Length(); i++)
+    mStatements[i].finalize();
+
+  // Handle our transaction, if we have one
+  if (mTransactionManager) {
+    if (mState == COMPLETED) {
+      nsresult rv = mTransactionManager->Commit();
+      if (NS_FAILED(rv)) {
+        mState = ERROR;
+        (void)notifyError(mozIStorageError::ERROR,
+                          "Transaction failed to commit");
+      }
+    }
+    else {
+      (void)mTransactionManager->Rollback();
+    }
+    delete mTransactionManager;
+    mTransactionManager = nsnull;
+  }
+
+  // Always generate a completion notification; it is what guarantees that our
+  // destruction does not happen here on the async thread.
+  nsRefPtr<CompletionNotifier> completionEvent =
+    new CompletionNotifier(mCallback, mState, this);
+  NS_ENSURE_TRUE(completionEvent, NS_ERROR_OUT_OF_MEMORY);
+
+  // We no longer own mCallback (the CompletionNotifier takes ownership).
+  mCallback = nsnull;
+
+  (void)mCallingThread->Dispatch(completionEvent, NS_DISPATCH_NORMAL);
+
+  return NS_OK;
+}
+
+nsresult
+AsyncExecuteStatements::notifyError(PRInt32 aErrorCode,
+                                    const char *aMessage)
+{
+  mMutex.AssertNotCurrentThreadOwns();
+  mDBMutex.assertNotCurrentThreadOwns();
+
+  if (!mCallback)
+    return NS_OK;
+
+  nsCOMPtr<mozIStorageError> errorObj(new Error(aErrorCode, aMessage));
+  NS_ENSURE_TRUE(errorObj, NS_ERROR_OUT_OF_MEMORY);
+
+  return notifyError(errorObj);
+}
+
+nsresult
+AsyncExecuteStatements::notifyError(mozIStorageError *aError)
+{
+  mMutex.AssertNotCurrentThreadOwns();
+  mDBMutex.assertNotCurrentThreadOwns();
+
+  if (!mCallback)
+    return NS_OK;
+
+  nsRefPtr<ErrorNotifier> notifier =
+    new ErrorNotifier(mCallback, aError, this);
+  NS_ENSURE_TRUE(notifier, NS_ERROR_OUT_OF_MEMORY);
+
+  return mCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
+}
+
+nsresult
+AsyncExecuteStatements::notifyResults()
+{
+  mMutex.AssertNotCurrentThreadOwns();
+  NS_ASSERTION(mCallback, "notifyResults called without a callback!");
+
+  nsRefPtr<CallbackResultNotifier> notifier =
+    new CallbackResultNotifier(mCallback, mResultSet, this);
+  NS_ENSURE_TRUE(notifier, NS_ERROR_OUT_OF_MEMORY);
+
+  nsresult rv = mCallingThread->Dispatch(notifier, NS_DISPATCH_NORMAL);
+  if (NS_SUCCEEDED(rv))
+    mResultSet = nsnull; // we no longer own it on success
+  return rv;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(
+  AsyncExecuteStatements,
+  nsIRunnable,
+  mozIStoragePendingStatement
+)
+
+////////////////////////////////////////////////////////////////////////////////
+//// mozIStoragePendingStatement
+
+NS_IMETHODIMP
+AsyncExecuteStatements::Cancel()
+{
+#ifdef DEBUG
+  PRBool onCallingThread = PR_FALSE;
+  (void)mCallingThread->IsOnCurrentThread(&onCallingThread);
+  NS_ASSERTION(onCallingThread, "Not canceling from the calling thread!");
+#endif
+
+  // If we have already canceled, we have an error, but always indicate that
+  // we are trying to cancel.
+  NS_ENSURE_FALSE(mCancelRequested, NS_ERROR_UNEXPECTED);
+
+  {
+    MutexAutoLock lockedScope(mMutex);
+
+    // We need to indicate that we want to try and cancel now.
+    mCancelRequested = true;
+  }
+
+  return NS_OK;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIRunnable
+
+NS_IMETHODIMP
+AsyncExecuteStatements::Run()
+{
+  // Do not run if we have been canceled.
+  {
+    MutexAutoLock lockedScope(mMutex);
+    if (mCancelRequested)
+      mState = CANCELED;
+  }
+  if (mState == CANCELED)
+    return notifyComplete();
+
+  // If there is more than one statement, run it in a transaction.  We assume
+  // that we have been given write statements since getting a batch of read
+  // statements doesn't make a whole lot of sense.
+  // Additionally, if we have only one statement and it needs a transaction, we
+  // will wrap it in one.
+  if (mStatements.Length() > 1 || mStatements[0].needsTransaction()) {
+    // We don't error if this failed because it's not terrible if it does.
+    mTransactionManager = new mozStorageTransaction(mConnection, PR_FALSE,
+                                                    mozIStorageConnection::TRANSACTION_IMMEDIATE);
+  }
+
+  // Execute each statement, giving the callback results if it returns any.
+  for (PRUint32 i = 0; i < mStatements.Length(); i++) {
+    bool finished = (i == (mStatements.Length() - 1));
+
+    sqlite3_stmt *stmt;
+    { // lock the sqlite mutex so sqlite3_errmsg cannot change
+      SQLiteMutexAutoLock lockedScope(mDBMutex);
+
+      int rc = mStatements[i].getSqliteStatement(&stmt);
+      if (rc != SQLITE_OK) {
+        // Set our error state.
+        mState = ERROR;
+
+        // Build the error object; can't call notifyError with the lock held
+        sqlite3 *db = mConnection->GetNativeConnection();
+        nsCOMPtr<mozIStorageError> errorObj(
+          new Error(rc, ::sqlite3_errmsg(db))
+        );
+        {
+          // We cannot hold the DB mutex and call notifyError.
+          SQLiteMutexAutoUnlock unlockedScope(mDBMutex);
+          (void)notifyError(errorObj);
+        }
+        break;
+      }
+    }
+
+    // If we have parameters to bind, bind them, execute, and process.
+    if (mStatements[i].hasParametersToBeBound()) {
+      if (!bindExecuteAndProcessStatement(mStatements[i], finished))
+        break;
+    }
+    // Otherwise, just execute and process the statement.
+    else if (!executeAndProcessStatement(stmt, finished)) {
+      break;
+    }
+  }
+
+  // If we still have results that we haven't notified about, take care of
+  // them now.
+  if (mResultSet)
+    (void)notifyResults();
+
+  // Notify about completion
+  return notifyComplete();
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatementExecution.h
@@ -0,0 +1,254 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _mozStorageAsyncStatementExecution_h_
+#define _mozStorageAsyncStatementExecution_h_
+
+#include "nscore.h"
+#include "nsTArray.h"
+#include "nsAutoPtr.h"
+#include "nsThreadUtils.h"
+#include "mozilla/Mutex.h"
+#include "mozilla/TimeStamp.h"
+
+#include "SQLiteMutex.h"
+#include "mozIStoragePendingStatement.h"
+#include "mozIStorageStatementCallback.h"
+
+struct sqlite3_stmt;
+class mozStorageTransaction;
+
+namespace mozilla {
+namespace storage {
+
+class Connection;
+class ResultSet;
+class StatementData;
+
+class AsyncExecuteStatements : public nsIRunnable
+                             , public mozIStoragePendingStatement
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIRUNNABLE
+  NS_DECL_MOZISTORAGEPENDINGSTATEMENT
+
+  /**
+   * Describes the state of execution.
+   */
+  enum ExecutionState {
+    PENDING = -1,
+    COMPLETED = mozIStorageStatementCallback::REASON_FINISHED,
+    CANCELED = mozIStorageStatementCallback::REASON_CANCELED,
+    ERROR = mozIStorageStatementCallback::REASON_ERROR
+  };
+
+  typedef nsTArray<StatementData> StatementDataArray;
+
+  /**
+   * Executes a statement in the background, and passes results back to the
+   * caller.
+   *
+   * @param aStatements
+   *        The statements to execute and possibly bind in the background.
+   *        Ownership is transfered from the caller.
+   * @param aConnection
+   *        The connection that created the statements to execute.
+   * @param aCallback
+   *        The callback that is notified of results, completion, and errors.
+   * @param _stmt
+   *        The handle to control the execution of the statements.
+   */
+  static nsresult execute(StatementDataArray &aStatements,
+                          Connection *aConnection,
+                          mozIStorageStatementCallback *aCallback,
+                          mozIStoragePendingStatement **_stmt);
+
+  /**
+   * Indicates when events on the calling thread should run or not.  Certain
+   * events posted back to the calling thread should call this see if they
+   * should run or not.
+   *
+   * @pre mMutex is not held
+   *
+   * @returns true if the event should notify still, false otherwise.
+   */
+  bool shouldNotify();
+
+private:
+  AsyncExecuteStatements(StatementDataArray &aStatements,
+                         Connection *aConnection,
+                         mozIStorageStatementCallback *aCallback);
+
+  /**
+   * Binds and then executes a given statement until completion, an error
+   * occurs, or we are canceled.  If aLastStatement is true, we should set
+   * mState accordingly.
+   *
+   * @pre mMutex is not held
+   *
+   * @param aData
+   *        The StatementData to bind, execute, and then process.
+   * @param aLastStatement
+   *        Indicates if this is the last statement or not.  If it is, we have
+   *        to set the proper state.
+   * @returns true if we should continue to process statements, false otherwise.
+   */
+  bool bindExecuteAndProcessStatement(StatementData &aData,
+                                      bool aLastStatement);
+
+  /**
+   * Executes a given statement until completion, an error occurs, or we are
+   * canceled.  If aLastStatement is true, we should set mState accordingly.
+   *
+   * @pre mMutex is not held
+   *
+   * @param aStatement
+   *        The statement to execute and then process.
+   * @param aLastStatement
+   *        Indicates if this is the last statement or not.  If it is, we have
+   *        to set the proper state.
+   * @returns true if we should continue to process statements, false otherwise.
+   */
+  bool executeAndProcessStatement(sqlite3_stmt *aStatement,
+                                  bool aLastStatement);
+
+  /**
+   * Executes a statement to completion, properly handling any error conditions.
+   *
+   * @pre mMutex is not held
+   *
+   * @param aStatement
+   *        The statement to execute to completion.
+   * @returns true if results were obtained, false otherwise.
+   */
+  bool executeStatement(sqlite3_stmt *aStatement);
+
+  /**
+   * Builds a result set up with a row from a given statement.  If we meet the
+   * right criteria, go ahead and notify about this results too.
+   *
+   * @pre mMutex is not held
+   *
+   * @param aStatement
+   *        The statement to get the row data from.
+   */
+  nsresult buildAndNotifyResults(sqlite3_stmt *aStatement);
+
+  /**
+   * Notifies callback about completion, and does any necessary cleanup.
+   *
+   * @pre mMutex is not held
+   */
+  nsresult notifyComplete();
+
+  /**
+   * Notifies callback about an error.
+   *
+   * @pre mMutex is not held
+   * @pre mDBMutex is not held
+   *
+   * @param aErrorCode
+   *        The error code defined in mozIStorageError for the error.
+   * @param aMessage
+   *        The error string, if any.
+   * @param aError
+   *        The error object to notify the caller with.
+   */
+  nsresult notifyError(PRInt32 aErrorCode, const char *aMessage);
+  nsresult notifyError(mozIStorageError *aError);
+
+  /**
+   * Notifies the callback about a result set.
+   *
+   * @pre mMutex is not held
+   */
+  nsresult notifyResults();
+
+  StatementDataArray mStatements;
+  nsRefPtr<Connection> mConnection;
+  mozStorageTransaction *mTransactionManager;
+  mozIStorageStatementCallback *mCallback;
+  nsCOMPtr<nsIThread> mCallingThread;
+  nsRefPtr<ResultSet> mResultSet;
+
+  /**
+   * The maximum amount of time we want to wait between results.  Defined by
+   * MAX_MILLISECONDS_BETWEEN_RESULTS and set at construction.
+   */
+  const TimeDuration mMaxWait;
+
+  /**
+   * The start time since our last set of results.
+   */
+  TimeStamp mIntervalStart;
+
+  /**
+   * Indicates our state of execution.
+   */
+  ExecutionState mState;
+
+  /**
+   * Indicates if we should try to cancel at a cancelation point.
+   */
+  bool mCancelRequested;
+
+  /**
+   * This is the mutex that protects our state from changing between threads.
+   * This includes the following variables:
+   *   - mCancelRequested is only set on the calling thread while the lock is
+   *     held.  It is always read from within the lock on the background thread,
+   *     but not on the calling thread (see shouldNotify for why).
+   */
+  Mutex &mMutex;
+
+  /**
+   * The wrapped SQLite recursive connection mutex used by sqlite3_step.  We use
+   * it whenever we call sqlite3_step and care about having reliable error
+   * messages.  By taking it prior to the call and holding it until the point
+   * where we no longer care about the error message, the user gets reliable
+   * error messages.
+   */
+  SQLiteMutex &mDBMutex;
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // _mozStorageAsyncStatementExecution_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatementJSHelper.cpp
@@ -0,0 +1,148 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozStorage code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsIXPConnect.h"
+#include "mozStorageAsyncStatement.h"
+#include "mozStorageService.h"
+
+#include "nsMemory.h"
+#include "nsString.h"
+#include "nsServiceManagerUtils.h"
+
+#include "mozStorageAsyncStatementJSHelper.h"
+
+#include "mozStorageAsyncStatementParams.h"
+
+#include "jsapi.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// AsyncStatementJSHelper
+
+nsresult
+AsyncStatementJSHelper::getParams(AsyncStatement *aStatement,
+                                  JSContext *aCtx,
+                                  JSObject *aScopeObj,
+                                  jsval *_params)
+{
+  nsresult rv;
+
+#ifdef DEBUG
+  PRInt32 state;
+  (void)aStatement->GetState(&state);
+  NS_ASSERTION(state == mozIStorageAsyncStatement::MOZ_STORAGE_STATEMENT_READY,
+               "Invalid state to get the params object - all calls will fail!");
+#endif
+
+  if (!aStatement->mStatementParamsHolder) {
+    nsCOMPtr<mozIStorageStatementParams> params =
+      new AsyncStatementParams(aStatement);
+    NS_ENSURE_TRUE(params, NS_ERROR_OUT_OF_MEMORY);
+
+    nsCOMPtr<nsIXPConnect> xpc(Service::getXPConnect());
+    rv = xpc->WrapNative(
+      aCtx,
+      ::JS_GetGlobalForObject(aCtx, aScopeObj),
+      params,
+      NS_GET_IID(mozIStorageStatementParams),
+      getter_AddRefs(aStatement->mStatementParamsHolder)
+    );
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+
+  JSObject *obj = nsnull;
+  rv = aStatement->mStatementParamsHolder->GetJSObject(&obj);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  *_params = OBJECT_TO_JSVAL(obj);
+  return NS_OK;
+}
+
+NS_IMETHODIMP_(nsrefcnt) AsyncStatementJSHelper::AddRef() { return 2; }
+NS_IMETHODIMP_(nsrefcnt) AsyncStatementJSHelper::Release() { return 1; }
+NS_INTERFACE_MAP_BEGIN(AsyncStatementJSHelper)
+  NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIXPCScriptable
+
+#define XPC_MAP_CLASSNAME AsyncStatementJSHelper
+#define XPC_MAP_QUOTED_CLASSNAME "AsyncStatementJSHelper"
+#define XPC_MAP_WANT_GETPROPERTY
+#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
+#include "xpc_map_end.h"
+
+NS_IMETHODIMP
+AsyncStatementJSHelper::GetProperty(nsIXPConnectWrappedNative *aWrapper,
+                                    JSContext *aCtx,
+                                    JSObject *aScopeObj,
+                                    jsval aId,
+                                    jsval *_result,
+                                    PRBool *_retval)
+{
+  if (!JSVAL_IS_STRING(aId))
+    return NS_OK;
+
+  // Cast to async via mozI* since direct from nsISupports is ambiguous.
+  mozIStorageAsyncStatement *iAsyncStmt =
+    static_cast<mozIStorageAsyncStatement *>(aWrapper->Native());
+  AsyncStatement *stmt = static_cast<AsyncStatement *>(iAsyncStmt);
+
+#ifdef DEBUG
+  {
+    nsISupports *supp = aWrapper->Native();
+    nsCOMPtr<mozIStorageAsyncStatement> isStatement(do_QueryInterface(supp));
+    NS_ASSERTION(isStatement, "How is this not an async statement?!");
+  }
+#endif
+
+  const char *propName = ::JS_GetStringBytes(JSVAL_TO_STRING(aId));
+  if (::strcmp(propName, "params") == 0)
+    return getParams(stmt, aCtx, aScopeObj, _result);
+
+  return NS_OK;
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatementJSHelper.h
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozStorage code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_mozStorageAsyncStatementJSHelper_h_
+#define mozilla_storage_mozStorageAsyncStatementJSHelper_h_
+
+#include "nsIXPCScriptable.h"
+
+class AsyncStatement;
+
+namespace mozilla {
+namespace storage {
+
+/**
+ * A modified version of StatementJSHelper that only exposes the async-specific
+ * 'params' helper.  We do not expose 'row' or 'step' as they do not apply to
+ * us.
+ */
+class AsyncStatementJSHelper : public nsIXPCScriptable
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIXPCSCRIPTABLE
+
+private:
+  nsresult getParams(AsyncStatement *, JSContext *, JSObject *, jsval *);
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // mozilla_storage_mozStorageAsyncStatementJSHelper_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatementParams.cpp
@@ -0,0 +1,165 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "nsMemory.h"
+#include "nsString.h"
+#include "nsCOMPtr.h"
+
+#include "mozStoragePrivateHelpers.h"
+#include "mozStorageAsyncStatement.h"
+#include "mozStorageAsyncStatementParams.h"
+#include "mozIStorageStatement.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// AsyncStatementParams
+
+AsyncStatementParams::AsyncStatementParams(AsyncStatement *aStatement)
+: mStatement(aStatement)
+{
+  NS_ASSERTION(mStatement != nsnull, "mStatement is null");
+}
+
+NS_IMPL_ISUPPORTS2(
+  AsyncStatementParams
+, mozIStorageStatementParams
+, nsIXPCScriptable
+)
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsIXPCScriptable
+
+#define XPC_MAP_CLASSNAME AsyncStatementParams
+#define XPC_MAP_QUOTED_CLASSNAME "AsyncStatementParams"
+#define XPC_MAP_WANT_SETPROPERTY
+#define XPC_MAP_WANT_NEWRESOLVE
+#define XPC_MAP_FLAGS nsIXPCScriptable::ALLOW_PROP_MODS_DURING_RESOLVE
+#include "xpc_map_end.h"
+
+NS_IMETHODIMP
+AsyncStatementParams::SetProperty(
+  nsIXPConnectWrappedNative *aWrapper,
+  JSContext *aCtx,
+  JSObject *aScopeObj,
+  jsval aId,
+  jsval *_vp,
+  PRBool *_retval
+)
+{
+  NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
+
+  if (JSVAL_IS_INT(aId)) {
+    int idx = JSVAL_TO_INT(aId);
+
+    nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
+    NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
+    nsresult rv = mStatement->BindByIndex(idx, variant);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  else if (JSVAL_IS_STRING(aId)) {
+    JSString *str = JSVAL_TO_STRING(aId);
+    NS_ConvertUTF16toUTF8 name(reinterpret_cast<const PRUnichar *>
+                                   (::JS_GetStringChars(str)),
+                               ::JS_GetStringLength(str));
+
+    nsCOMPtr<nsIVariant> variant(convertJSValToVariant(aCtx, *_vp));
+    NS_ENSURE_TRUE(variant, NS_ERROR_UNEXPECTED);
+    nsresult rv = mStatement->BindByName(name, variant);
+    NS_ENSURE_SUCCESS(rv, rv);
+  }
+  else {
+    return NS_ERROR_INVALID_ARG;
+  }
+
+  *_retval = PR_TRUE;
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncStatementParams::NewResolve(
+  nsIXPConnectWrappedNative *aWrapper,
+  JSContext *aCtx,
+  JSObject *aScopeObj,
+  jsval aId,
+  PRUint32 aFlags,
+  JSObject **_objp,
+  PRBool *_retval
+)
+{
+  NS_ENSURE_TRUE(mStatement, NS_ERROR_NOT_INITIALIZED);
+  // We do not throw at any point after this unless our index is out of range
+  // because we want to allow the prototype chain to be checked for the
+  // property.
+
+  PRUint32 idx;
+
+  if (JSVAL_IS_INT(aId)) {
+    idx = JSVAL_TO_INT(aId);
+    // All indexes are good because we don't know how many parameters there
+    // really are.
+  }
+  else if (JSVAL_IS_STRING(aId)) {
+    JSString *str = JSVAL_TO_STRING(aId);
+    jschar *nameChars = ::JS_GetStringChars(str);
+    size_t nameLength = ::JS_GetStringLength(str);
+
+    // We are unable to tell if there's a parameter with this name and so
+    // we must assume that there is.  This screws the rest of the prototype
+    // chain, but people really shouldn't be depending on this anyways.
+    *_retval = ::JS_DefineUCProperty(aCtx, aScopeObj, nameChars, nameLength,
+                                     JSVAL_VOID, nsnull, nsnull, 0);
+    NS_ENSURE_TRUE(*_retval, NS_OK);
+  }
+  else {
+    // We do not handle other types.
+    return NS_OK;
+  }
+
+  *_retval = ::JS_DefineElement(aCtx, aScopeObj, idx, JSVAL_VOID, nsnull,
+                                nsnull, 0);
+  if (*_retval)
+    *_objp = aScopeObj;
+  return NS_OK;
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageAsyncStatementParams.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef mozilla_storage_mozStorageAsyncStatementParams_h_
+#define mozilla_storage_mozStorageAsyncStatementParams_h_
+
+#include "mozIStorageStatementWrapper.h"
+#include "nsIXPCScriptable.h"
+
+class mozIStorageAsyncStatement;
+
+namespace mozilla {
+namespace storage {
+
+class AsyncStatement;
+
+/*
+ * Since mozIStorageStatementParams is just a tagging interface we do not have
+ * an async variant.
+ */
+class AsyncStatementParams : public mozIStorageStatementParams
+                           , public nsIXPCScriptable
+{
+public:
+  AsyncStatementParams(AsyncStatement *aStatement);
+
+  // interfaces
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGESTATEMENTPARAMS
+  NS_DECL_NSIXPCSCRIPTABLE
+
+protected:
+  AsyncStatement *mStatement;
+
+  friend class AsyncStatement;
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // mozilla_storage_mozStorageAsyncStatementParams_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageBindingParams.cpp
@@ -0,0 +1,497 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <limits.h>
+
+#include "nsString.h"
+
+#include "mozStorageError.h"
+#include "mozStoragePrivateHelpers.h"
+#include "mozStorageBindingParams.h"
+#include "mozStorageBindingParamsArray.h"
+#include "Variant.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// Local Helper Objects
+
+namespace {
+
+struct BindingColumnData
+{
+  BindingColumnData(sqlite3_stmt *aStmt,
+                    int aColumn)
+  : stmt(aStmt)
+  , column(aColumn)
+  {
+  }
+  sqlite3_stmt *stmt;
+  int column;
+};
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//// Variant Specialization Functions (variantToSQLiteT)
+
+static int
+sqlite3_T_int(BindingColumnData aData,
+              int aValue)
+{
+  return ::sqlite3_bind_int(aData.stmt, aData.column + 1, aValue);
+}
+
+static int
+sqlite3_T_int64(BindingColumnData aData,
+                sqlite3_int64 aValue)
+{
+  return ::sqlite3_bind_int64(aData.stmt, aData.column + 1, aValue);
+}
+
+static int
+sqlite3_T_double(BindingColumnData aData,
+                 double aValue)
+{
+  return ::sqlite3_bind_double(aData.stmt, aData.column + 1, aValue);
+}
+
+static int
+sqlite3_T_text(BindingColumnData aData,
+               const nsCString& aValue)
+{
+  return ::sqlite3_bind_text(aData.stmt,
+                             aData.column + 1,
+                             aValue.get(),
+                             aValue.Length(),
+                             SQLITE_TRANSIENT);
+}
+
+static int
+sqlite3_T_text16(BindingColumnData aData,
+                 const nsString& aValue)
+{
+  return ::sqlite3_bind_text16(aData.stmt,
+                               aData.column + 1,
+                               aValue.get(),
+                               aValue.Length() * 2, // Length in bytes!
+                               SQLITE_TRANSIENT);
+}
+
+static int
+sqlite3_T_null(BindingColumnData aData)
+{
+  return ::sqlite3_bind_null(aData.stmt, aData.column + 1);
+}
+
+static int
+sqlite3_T_blob(BindingColumnData aData,
+               const void *aBlob,
+               int aSize)
+{
+  return ::sqlite3_bind_blob(aData.stmt, aData.column + 1, aBlob, aSize,
+                             NS_Free);
+
+}
+
+#include "variantToSQLiteT_impl.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//// BindingParams
+
+BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray,
+                             Statement *aOwningStatement)
+: mLocked(false)
+, mOwningArray(aOwningArray)
+, mOwningStatement(aOwningStatement)
+{
+  (void)mOwningStatement->GetParameterCount(&mParamCount);
+  (void)mParameters.SetCapacity(mParamCount);
+}
+
+BindingParams::BindingParams(mozIStorageBindingParamsArray *aOwningArray)
+: mLocked(false)
+, mOwningArray(aOwningArray)
+, mOwningStatement(nsnull)
+, mParamCount(0)
+{
+}
+
+AsyncBindingParams::AsyncBindingParams(
+  mozIStorageBindingParamsArray *aOwningArray
+)
+: BindingParams(aOwningArray)
+{
+  mNamedParameters.Init();
+}
+
+void
+BindingParams::lock()
+{
+  NS_ASSERTION(mLocked == false, "Parameters have already been locked!");
+  mLocked = true;
+
+  // We no longer need to hold a reference to our statement or our owning array.
+  // The array owns us at this point, and it will own a reference to the
+  // statement.
+  mOwningStatement = nsnull;
+  mOwningArray = nsnull;
+}
+
+void
+BindingParams::unlock(Statement *aOwningStatement)
+{
+  NS_ASSERTION(mLocked == true, "Parameters were not yet locked!");
+  mLocked = false;
+  mOwningStatement = aOwningStatement;
+}
+
+const mozIStorageBindingParamsArray *
+BindingParams::getOwner() const
+{
+  return mOwningArray;
+}
+
+PLDHashOperator
+AsyncBindingParams::iterateOverNamedParameters(const nsACString &aName,
+                                               nsIVariant *aValue,
+                                               void *voidClosureThunk)
+{
+  NamedParameterIterationClosureThunk *closureThunk =
+    static_cast<NamedParameterIterationClosureThunk *>(voidClosureThunk);
+
+  // We do not accept any forms of names other than ":name", but we need to add
+  // the colon for SQLite.
+  nsCAutoString name(":");
+  name.Append(aName);
+  int oneIdx = ::sqlite3_bind_parameter_index(closureThunk->statement,
+                                              PromiseFlatCString(name).get());
+
+  if (oneIdx == 0) {
+    nsCAutoString errMsg(aName);
+    errMsg.Append(NS_LITERAL_CSTRING(" is not a valid named parameter."));
+    closureThunk->err = new Error(SQLITE_RANGE,
+                                  PromiseFlatCString(errMsg).get());
+    return PL_DHASH_STOP;
+  }
+
+  // XPCVariant's AddRef and Release are not thread-safe and so we must not do
+  // anything that would invoke them here on the async thread.  As such we can't
+  // cram aValue into self->mParameters using ReplaceObjectAt so that we can
+  // freeload off of the BindingParams::Bind implementation.
+  int rc = variantToSQLiteT(BindingColumnData(closureThunk->statement,
+                                              oneIdx - 1),
+                            aValue);
+  if (rc != SQLITE_OK) {
+    // We had an error while trying to bind.  Now we need to create an error
+    // object with the right message.  Note that we special case
+    // SQLITE_MISMATCH, but otherwise get the message from SQLite.
+    const char *msg = "Could not covert nsIVariant to SQLite type.";
+    if (rc != SQLITE_MISMATCH)
+      msg = ::sqlite3_errmsg(::sqlite3_db_handle(closureThunk->statement));
+
+    closureThunk->err = new Error(rc, msg);
+    return PL_DHASH_STOP;
+  }
+  return PL_DHASH_NEXT;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//// nsISupports
+
+NS_IMPL_THREADSAFE_ISUPPORTS2(
+  BindingParams
+, mozIStorageBindingParams
+, IStorageBindingParamsInternal
+)
+
+
+////////////////////////////////////////////////////////////////////////////////
+//// IStorageBindingParamsInternal
+
+already_AddRefed<mozIStorageError>
+BindingParams::bind(sqlite3_stmt *aStatement)
+{
+  // Iterate through all of our stored data, and bind it.
+  for (PRInt32 i = 0; i < mParameters.Count(); i++) {
+    int rc = variantToSQLiteT(BindingColumnData(aStatement, i), mParameters[i]);
+    if (rc != SQLITE_OK) {
+      // We had an error while trying to bind.  Now we need to create an error
+      // object with the right message.  Note that we special case
+      // SQLITE_MISMATCH, but otherwise get the message from SQLite.
+      const char *msg = "Could not covert nsIVariant to SQLite type.";
+      if (rc != SQLITE_MISMATCH)
+        msg = ::sqlite3_errmsg(::sqlite3_db_handle(aStatement));
+
+      nsCOMPtr<mozIStorageError> err(new Error(rc, msg));
+      return err.forget();
+    }
+  }
+
+  return nsnull;
+}
+
+already_AddRefed<mozIStorageError>
+AsyncBindingParams::bind(sqlite3_stmt * aStatement)
+{
+  // We should bind by index using the super-class if there is nothing in our
+  // hashtable.
+  if (!mNamedParameters.Count())
+    return BindingParams::bind(aStatement);
+
+  // Enumerate over everyone in the map, propagating them into mParameters if
+  // we can and creating an error immediately when we cannot.
+  NamedParameterIterationClosureThunk closureThunk = {this, aStatement, nsnull};
+  (void)mNamedParameters.EnumerateRead(iterateOverNamedParameters,
+                                       (void *)&closureThunk);
+
+  return closureThunk.err.forget();
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+//// mozIStorageBindingParams
+
+NS_IMETHODIMP
+BindingParams::BindByName(const nsACString &aName,
+                          nsIVariant *aValue)
+{
+  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
+
+  // Get the column index that we need to store this at.
+  PRUint32 index;
+  nsresult rv = mOwningStatement->GetParameterIndex(aName, &index);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return BindByIndex(index, aValue);
+}
+
+NS_IMETHODIMP
+AsyncBindingParams::BindByName(const nsACString &aName,
+                               nsIVariant *aValue)
+{
+  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
+
+  if (!mNamedParameters.Put(aName, aValue))
+    return NS_ERROR_OUT_OF_MEMORY;
+  return NS_OK;
+}
+
+
+NS_IMETHODIMP
+BindingParams::BindUTF8StringByName(const nsACString &aName,
+                                    const nsACString &aValue)
+{
+  nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindStringByName(const nsACString &aName,
+                                const nsAString &aValue)
+{
+  nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindDoubleByName(const nsACString &aName,
+                                double aValue)
+{
+  nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindInt32ByName(const nsACString &aName,
+                               PRInt32 aValue)
+{
+  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindInt64ByName(const nsACString &aName,
+                               PRInt64 aValue)
+{
+  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindNullByName(const nsACString &aName)
+{
+  nsCOMPtr<nsIVariant> value(new NullVariant());
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindBlobByName(const nsACString &aName,
+                              const PRUint8 *aValue,
+                              PRUint32 aValueSize)
+{
+  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
+  std::pair<const void *, int> data(
+    static_cast<const void *>(aValue),
+    int(aValueSize)
+  );
+  nsCOMPtr<nsIVariant> value(new BlobVariant(data));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByName(aName, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindByIndex(PRUint32 aIndex,
+                           nsIVariant *aValue)
+{
+  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
+  ENSURE_INDEX_VALUE(aIndex, mParamCount);
+
+  // Store the variant for later use.
+  NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
+                 NS_ERROR_OUT_OF_MEMORY);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+AsyncBindingParams::BindByIndex(PRUint32 aIndex,
+                                nsIVariant *aValue)
+{
+  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
+  // In the asynchronous case we do not know how many parameters there are to
+  // bind to, so we cannot check the validity of aIndex.
+
+  // Store the variant for later use.
+  NS_ENSURE_TRUE(mParameters.ReplaceObjectAt(aValue, aIndex),
+                 NS_ERROR_OUT_OF_MEMORY);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BindingParams::BindUTF8StringByIndex(PRUint32 aIndex,
+                                     const nsACString &aValue)
+{
+  nsCOMPtr<nsIVariant> value(new UTF8TextVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindStringByIndex(PRUint32 aIndex,
+                                 const nsAString &aValue)
+{
+  nsCOMPtr<nsIVariant> value(new TextVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindDoubleByIndex(PRUint32 aIndex,
+                                 double aValue)
+{
+  nsCOMPtr<nsIVariant> value(new FloatVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindInt32ByIndex(PRUint32 aIndex,
+                                PRInt32 aValue)
+{
+  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindInt64ByIndex(PRUint32 aIndex,
+                                PRInt64 aValue)
+{
+  nsCOMPtr<nsIVariant> value(new IntegerVariant(aValue));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindNullByIndex(PRUint32 aIndex)
+{
+  nsCOMPtr<nsIVariant> value(new NullVariant());
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+NS_IMETHODIMP
+BindingParams::BindBlobByIndex(PRUint32 aIndex,
+                               const PRUint8 *aValue,
+                               PRUint32 aValueSize)
+{
+  NS_ENSURE_ARG_MAX(aValueSize, INT_MAX);
+  std::pair<const void *, int> data(
+    static_cast<const void *>(aValue),
+    int(aValueSize)
+  );
+  nsCOMPtr<nsIVariant> value(new BlobVariant(data));
+  NS_ENSURE_TRUE(value, NS_ERROR_OUT_OF_MEMORY);
+
+  return BindByIndex(aIndex, value);
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageBindingParams.h
@@ -0,0 +1,154 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *   Andrew Sutherland <asutherland@asutherland.org>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _mozStorageBindingParams_h_
+#define _mozStorageBindingParams_h_
+
+#include "nsCOMArray.h"
+#include "nsIVariant.h"
+#include "nsTHashtable.h"
+
+#include "mozStorageBindingParamsArray.h"
+#include "mozStorageStatement.h"
+#include "mozStorageAsyncStatement.h"
+
+#include "mozIStorageBindingParams.h"
+#include "IStorageBindingParamsInternal.h"
+
+namespace mozilla {
+namespace storage {
+
+class BindingParams : public mozIStorageBindingParams
+                    , public IStorageBindingParamsInternal
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGEBINDINGPARAMS
+  NS_DECL_ISTORAGEBINDINGPARAMSINTERNAL
+
+  /**
+   * Locks the parameters and prevents further modification to it (such as
+   * binding more elements to it).
+   */
+  void lock();
+
+  /**
+   * Unlocks the parameters and allows modification to it again.
+   *
+   * @param aOwningStatement The statement that owns us.  We cleared this when
+   *        we were locked, and our invariant requires us to have this, so you
+   *        need to tell us again.
+   */
+  void unlock(Statement *aOwningStatement);
+
+  /**
+   * @returns the pointer to the owning BindingParamsArray.  Used by a
+   *          BindingParamsArray to verify that we belong to it when added.
+   */
+  const mozIStorageBindingParamsArray *getOwner() const;
+
+  BindingParams(mozIStorageBindingParamsArray *aOwningArray,
+                Statement *aOwningStatement);
+  virtual ~BindingParams() {}
+
+protected:
+  BindingParams(mozIStorageBindingParamsArray *aOwningArray);
+  nsCOMArray<nsIVariant> mParameters;
+  bool mLocked;
+
+private:
+
+  /**
+   * Track the BindingParamsArray that created us until we are added to it.
+   * (Once we are added we are locked and no one needs to look up our owner.)
+   * Ref-counted since there is no invariant that guarantees it stays alive
+   * otherwise.  This keeps mOwningStatement alive for us too since the array
+   * also holds a reference.
+   */
+  nsCOMPtr<mozIStorageBindingParamsArray> mOwningArray;
+  /**
+   * Used in the synchronous binding case to map parameter names to indices.
+   * Not reference-counted because this is only non-null as long as mOwningArray
+   * is non-null and mOwningArray also holds a statement reference.
+   */
+  Statement *mOwningStatement;
+  PRUint32 mParamCount;
+};
+
+/**
+ * Adds late resolution of named parameters so they don't get resolved until we
+ * try and bind the parameters on the async thread.  We also stop checking
+ * parameter indices for being too big since we just just don't know how many
+ * there are.
+ *
+ * We support *either* binding by name or binding by index.  Trying to do both
+ * results in only binding by name at sqlite3_stmt bind time.
+ */
+class AsyncBindingParams : public BindingParams
+{
+public:
+  NS_SCRIPTABLE NS_IMETHOD BindByName(const nsACString & aName,
+                                      nsIVariant *aValue);
+  NS_SCRIPTABLE NS_IMETHOD BindByIndex(PRUint32 aIndex, nsIVariant *aValue);
+
+  virtual already_AddRefed<mozIStorageError> bind(sqlite3_stmt * aStatement);
+
+  AsyncBindingParams(mozIStorageBindingParamsArray *aOwningArray);
+  virtual ~AsyncBindingParams() {}
+
+private:
+  nsInterfaceHashtable<nsCStringHashKey, nsIVariant> mNamedParameters;
+
+  struct NamedParameterIterationClosureThunk
+  {
+    AsyncBindingParams *self;
+    sqlite3_stmt *statement;
+    nsCOMPtr<mozIStorageError> err;
+  };
+
+  static PLDHashOperator iterateOverNamedParameters(const nsACString &aName,
+                                                    nsIVariant *aValue,
+                                                    void *voidClosureThunk);
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // _mozStorageBindingParams_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageBindingParamsArray.cpp
@@ -0,0 +1,116 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "mozStorageBindingParamsArray.h"
+#include "mozStorageBindingParams.h"
+#include "StorageBaseStatementInternal.h"
+
+namespace mozilla {
+namespace storage {
+
+////////////////////////////////////////////////////////////////////////////////
+//// BindingParamsArray
+
+BindingParamsArray::BindingParamsArray(
+  StorageBaseStatementInternal *aOwningStatement
+)
+: mOwningStatement(aOwningStatement)
+, mLocked(false)
+{
+}
+
+void
+BindingParamsArray::lock()
+{
+  NS_ASSERTION(mLocked == false, "Array has already been locked!");
+  mLocked = true;
+
+  // We also no longer need to hold a reference to our statement since it owns
+  // us.
+  mOwningStatement = nsnull;
+}
+
+const StorageBaseStatementInternal *
+BindingParamsArray::getOwner() const
+{
+  return mOwningStatement;
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(
+  BindingParamsArray,
+  mozIStorageBindingParamsArray
+)
+
+///////////////////////////////////////////////////////////////////////////////
+//// mozIStorageBindingParamsArray
+
+NS_IMETHODIMP
+BindingParamsArray::NewBindingParams(mozIStorageBindingParams **_params)
+{
+  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
+
+  nsCOMPtr<mozIStorageBindingParams> params(
+    mOwningStatement->newBindingParams(this));
+  NS_ENSURE_TRUE(params, NS_ERROR_UNEXPECTED);
+
+  params.forget(_params);
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+BindingParamsArray::AddParams(mozIStorageBindingParams *aParameters)
+{
+  NS_ENSURE_FALSE(mLocked, NS_ERROR_UNEXPECTED);
+
+  BindingParams *params = static_cast<BindingParams *>(aParameters);
+
+  // Check to make sure that this set of parameters was created with us.
+  if (params->getOwner() != this)
+    return NS_ERROR_UNEXPECTED;
+
+  NS_ENSURE_TRUE(mArray.AppendElement(params), NS_ERROR_OUT_OF_MEMORY);
+
+  // Lock the parameters only after we've successfully added them.
+  params->lock();
+
+  return NS_OK;
+}
+
+} // namespace storage
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageBindingParamsArray.h
@@ -0,0 +1,144 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Shawn Wilsher <me@shawnwilsher.com> (Original Author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _mozStorageBindingParamsArray_h_
+#define _mozStorageBindingParamsArray_h_
+
+#include "nsAutoPtr.h"
+#include "nsTArray.h"
+
+#include "mozIStorageBindingParamsArray.h"
+
+namespace mozilla {
+namespace storage {
+
+class StorageBaseStatementInternal;
+
+class BindingParamsArray : public mozIStorageBindingParamsArray
+{
+public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_MOZISTORAGEBINDINGPARAMSARRAY
+
+  BindingParamsArray(StorageBaseStatementInternal *aOwningStatement);
+
+  typedef nsTArray_base::size_type size_type;
+
+  /**
+   * Locks the array and prevents further modification to it (such as adding
+   * more elements to it).
+   */
+  void lock();
+
+  /**
+   * @return the pointer to the owning BindingParamsArray.
+   */
+  const StorageBaseStatementInternal *getOwner() const;
+
+  /**
+   * @return the number of elemets the array contains.
+   */
+  const size_type length() const { return mArray.Length(); }
+
+  class iterator {
+  public:
+    iterator(BindingParamsArray *aArray,
+             PRUint32 aIndex)
+    : mArray(aArray)
+    , mIndex(aIndex)
+    {
+    }
+
+    iterator &operator++(int)
+    {
+      mIndex++;
+      return *this;
+    }
+
+    bool operator==(const iterator &aOther) const
+    {
+      return mIndex == aOther.mIndex;
+    }
+    bool operator!=(const iterator &aOther) const
+    {
+      return !(*this == aOther);
+    }
+    mozIStorageBindingParams *operator*()
+    {
+      NS_ASSERTION(mIndex < mArray->length(),
+                   "Dereferenceing an invalid value!");
+      return mArray->mArray[mIndex].get();
+    }
+  private:
+    void operator--() { }
+    BindingParamsArray *mArray;
+    PRUint32 mIndex;
+  };
+
+  /**
+   * Obtains an iterator pointing to the beginning of the array.
+   */
+  inline iterator begin()
+  {
+    NS_ASSERTION(length() != 0,
+                 "Obtaining an iterator to the beginning with no elements!");
+    return iterator(this, 0);
+  }
+
+  /**
+   * Obtains an iterator pointing to the end of the array.
+   */
+  inline iterator end()
+  {
+    NS_ASSERTION(mLocked,
+                 "Obtaining an iterator to the end when we are not locked!");
+    return iterator(this, length());
+  }
+private:
+  nsCOMPtr<StorageBaseStatementInternal> mOwningStatement;
+  nsTArray< nsCOMPtr<mozIStorageBindingParams> > mArray;
+  bool mLocked;
+
+  friend class iterator;
+};
+
+} // namespace storage
+} // namespace mozilla
+
+#endif // _mozStorageBindingParamsArray_h_
new file mode 100644
--- /dev/null
+++ b/storage-backport/src/mozStorageConnection.cpp
@@ -0,0 +1,1043 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is
+ *  Oracle Corporation
+ * Portions created by the Initial Developer are Copyright (C) 2004
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Vladimir Vukicevic <vladimir.vukicevic@oracle.com>
+ *   Brett Wilson <brettw@gmail.com>
+ *   Shawn Wilsher <me@shawnwilsher.com>
+ *   Lev Serebryakov <lev@serebryakov.spb.ru>
+ *   Drew Willcoxon <adw@mozilla.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdio.h>
+
+#include "nsError.h"
+#include "nsIMutableArray.h"
+#include "nsHashSets.h"
+#include "nsAutoPtr.h"
+#include "nsIFile.h"
+#include "nsIPrefService.h"
+#include "nsIPrefBranch.h"
+#include "nsThreadUtils.h"
+#include "nsAutoLock.h"
+
+#include "mozIStorageAggregateFunction.h"
+#include "mozIStorageCompletionCallback.h"
+#include "mozIStorageFunction.h"
+
+#include "mozStorageAsyncStatementExecution.h"
+#include "mozStorageSQLFunctions.h"
+#include "mozStorageConnection.h"
+#include "mozStorageService.h"
+#include "mozStorageStatement.h"
+#include "mozStorageAsyncStatement.h"
+#include "mozStorageArgValueArray.h"
+#include "mozStoragePrivateHelpers.h"
+#include "mozStorageStatementData.h"
+#include "StorageBaseStatementInternal.h"
+#include "SQLCollations.h"
+
+#include "prlog.h"
+#include "prprf.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo* gStorageLog = nsnull;
+#endif
+
+namespace mozilla {
+namespace storage {
+
+#define PREF_TS_SYNCHRONOUS "toolkit.storage.synchronous"
+
+////////////////////////////////////////////////////////////////////////////////
+//// Variant Specialization Functions (variantToSQLiteT)
+
+static int
+sqlite3_T_int(sqlite3_context *aCtx,
+              int aValue)
+{
+  ::sqlite3_result_int(aCtx, aValue);
+  return SQLITE_OK;
+}
+
+static int
+sqlite3_T_int64(sqlite3_context *aCtx,
+                sqlite3_int64 aValue)
+{
+  ::sqlite3_result_int64(aCtx, aValue);
+  return SQLITE_OK;
+}
+
+static int
+sqlite3_T_double(sqlite3_context *aCtx,
+                 double aValue)
+{
+  ::sqlite3_result_double(aCtx, aValue);
+  return SQLITE_OK;
+}
+
+static int
+sqlite3_T_text(sqlite3_context *aCtx,
+               const nsCString &aValue)
+{
+  ::sqlite3_result_text(aCtx,
+                        aValue.get(),
+                        aValue.Length(),
+                        SQLITE_TRANSIENT);
+  return SQLITE_OK;
+}
+
+static int
+sqlite3_T_text16(sqlite3_context *aCtx,
+                 const nsString &aValue)
+{
+  ::sqlite3_result_text16(aCtx,
+                          aValue.get(),
+                          aValue.Length() * 2, // Number of bytes.
+                          SQLITE_TRANSIENT);
+  return SQLITE_OK;
+}
+
+static int
+sqlite3_T_null(sqlite3_context *aCtx)
+{
+  ::sqlite3_result_null(aCtx);
+  return SQLITE_OK;
+}
+
+static int
+sqlite3_T_blob(sqlite3_context *aCtx,
+               const void *aData,
+               int aSize)
+{
+  ::sqlite3_result_blob(aCtx, aData, aSize, NS_Free);
+  return SQLITE_OK;
+}
+
+#include "variantToSQLiteT_impl.h"
+
+////////////////////////////////////////////////////////////////////////////////
+//// Local Functions
+
+namespace {
+#ifdef PR_LOGGING
+void tracefunc (void *aClosure, const char *aStmt)
+{
+  PR_LOG(gStorageLog, PR_LOG_DEBUG, ("sqlite3_trace on %p for '%s'", aClosure,
+                                     aStmt));
+}
+#endif
+
+struct FFEArguments
+{
+    nsISupports *target;
+    bool found;
+};
+PLDHashOperator
+findFunctionEnumerator(const nsACString &aKey,
+                       nsISupports *aData,
+                       void *aUserArg)
+{
+  FFEArguments *args = static_cast<FFEArguments *>(aUserArg);
+  if (aData == args->target) {
+    args->found = PR_TRUE;
+    return PL_DHASH_STOP;
+  }
+  return PL_DHASH_NEXT;
+}
+
+void
+basicFunctionHelper(sqlite3_context *aCtx,
+                    int aArgc,
+                    sqlite3_value **aArgv)
+{
+  void *userData = ::sqlite3_user_data(aCtx);
+
+  mozIStorageFunction *func = static_cast<mozIStorageFunction *>(userData);
+
+  nsRefPtr<ArgValueArray> arguments(new ArgValueArray(aArgc, aArgv));
+  if (!arguments)
+      return;
+
+  nsCOMPtr<nsIVariant> result;
+  if (NS_FAILED(func->OnFunctionCall(arguments, getter_AddRefs(result)))) {
+    NS_WARNING("User function returned error code!");
+    ::sqlite3_result_error(aCtx,
+                           "User function returned error code",
+                           -1);
+    return;
+  }
+  if (variantToSQLiteT(aCtx, result) != SQLITE_OK) {
+    NS_WARNING("User function returned invalid data type!");
+    ::sqlite3_result_error(aCtx,
+                           "User function returned invalid data type",
+                           -1);
+  }
+}
+
+void
+aggregateFunctionStepHelper(sqlite3_context *aCtx,
+                            int aArgc,
+                            sqlite3_value **aArgv)
+{
+  void *userData = ::sqlite3_user_data(aCtx);
+  mozIStorageAggregateFunction *func =
+    static_cast<mozIStorageAggregateFunction *>(userData);
+
+  nsRefPtr<ArgValueArray> arguments(new ArgValueArray(aArgc, aArgv));
+  if (!arguments)
+    return;
+
+  if (NS_FAILED(func->OnStep(arguments)))
+    NS_WARNING("User aggregate step function returned error code!");
+}
+
+void
+aggregateFunctionFinalHelper(sqlite3_context *aCtx)
+{
+  void *userData = ::sqlite3_user_data(aCtx);
+  mozIStorageAggregateFunction *func =
+    static_cast<mozIStorageAggregateFunction *>(userData);
+
+  nsRefPtr<nsIVariant> result;
+  if (NS_FAILED(func->OnFinal(getter_AddRefs(result)))) {
+    NS_WARNING("User aggregate final function returned error code!");
+    ::sqlite3_result_error(aCtx,
+                           "User aggregate final function returned error code",
+                           -1);
+    return;
+  }
+
+  if (variantToSQLiteT(aCtx, result) != SQLITE_OK) {
+    NS_WARNING("User aggregate final function returned invalid data type!");
+    ::sqlite3_result_error(aCtx,
+                           "User aggregate final function returned invalid data type",
+                           -1);
+  }
+}
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//// Local Classes
+
+namespace {
+
+class AsyncCloseConnection : public nsRunnable
+{
+public:
+  AsyncCloseConnection(Connection *aConnection,
+                       nsIEventTarget *aCallingThread,
+                       nsIRunnable *aCallbackEvent,
+                       nsIThread *aAsyncThread)
+  : mConnection(aConnection)
+  , mCallingThread(aCallingThread)
+  , mCallbackEvent(aCallbackEvent)
+  , mAsyncThread(aAsyncThread)
+  {
+  }
+
+  NS_METHOD Run()
+  {
+    // This event is first dispatched to the background thread to ensure that
+    // all pending asynchronous events are completed, and then back to the
+    // calling thread to actually close and notify.
+    PRBool onCallingThread = PR_FALSE;
+    (void)mCallingThread->IsOnCurrentThread(&onCallingThread);
+    if (!onCallingThread) {
+      (void)mCallingThread->Dispatch(this, NS_DISPATCH_NORMAL);
+      return NS_OK;
+    }
+
+    if (mConnection)
+      (void)mConnection->internalClose();
+    if (mCallbackEvent)
+      (void)mCallingThread->Dispatch(mCallbackEvent, NS_DISPATCH_NORMAL);
+    mAsyncThread->Shutdown();
+
+    return NS_OK;
+  }
+private:
+  nsCOMPtr<Connection> mConnection;
+  nsCOMPtr<nsIEventTarget> mCallingThread;
+  nsCOMPtr<nsIRunnable> mCallbackEvent;
+  nsCOMPtr<nsIThread> mAsyncThread;
+};
+
+} // anonymous namespace
+
+////////////////////////////////////////////////////////////////////////////////
+//// Connection
+
+Connection::Connection(Service *aService)
+: sharedAsyncExecutionMutex("Connection::sharedAsyncExecutionMutex")
+, sharedDBMutex("Connection::sharedDBMutex")
+, threadOpenedOn(do_GetCurrentThread())
+, mDBConn(nsnull)
+, mAsyncExecutionThreadShuttingDown(false)
+, mTransactionInProgress(PR_FALSE)
+, mProgressHandler(nsnull)
+, mStorageService(aService)
+{
+  mFunctions.Init();
+}
+
+Connection::~Connection()
+{
+  (void)Close();
+
+  // If we know about an async execution thread then we need to take steps to
+  // trigger its shutdown.  (AsyncClose is the only other code to trigger
+  // something like this and it nulls out our reference so there is no risk of
+  // double triggering.)
+  if (mAsyncExecutionThread) {
+    // Note: Obviously, we can't tell it about us since we are dying.  We also
+    // skimp on using a mutex since there's no point.
+    nsCOMPtr<nsIRunnable> closeEvent =
+      new AsyncCloseConnection(nsnull, NS_GetCurrentThread(), nsnull,
+                               mAsyncExecutionThread);
+    if (!closeEvent)
+      return;
+
+    (void)mAsyncExecutionThread->Dispatch(closeEvent, NS_DISPATCH_NORMAL);
+  }
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(
+  Connection,
+  mozIStorageConnection
+)
+
+nsIEventTarget *
+Connection::getAsyncExecutionTarget()
+{
+  MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
+
+  // If we are shutting down the asynchronous thread, don't hand out any more
+  // references to the thread.
+  if (mAsyncExecutionThreadShuttingDown)
+    return nsnull;
+
+  if (!mAsyncExecutionThread) {
+    nsresult rv = ::NS_NewThread(getter_AddRefs(mAsyncExecutionThread));
+    if (NS_FAILED(rv)) {
+      NS_WARNING("Failed to create async thread.");
+      return nsnull;
+    }
+  }
+
+  return mAsyncExecutionThread;
+}
+
+nsresult
+Connection::initialize(nsIFile *aDatabaseFile)
+{
+  NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
+
+  int srv;
+  nsresult rv;
+
+  mDatabaseFile = aDatabaseFile;
+
+  if (aDatabaseFile) {
+    nsAutoString path;
+    rv = aDatabaseFile->GetPath(path);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    srv = ::sqlite3_open(NS_ConvertUTF16toUTF8(path).get(), &mDBConn);
+  }
+  else {
+    // in memory database requested, sqlite uses a magic file name
+    srv = ::sqlite3_open(":memory:", &mDBConn);
+  }
+  if (srv != SQLITE_OK) {
+    mDBConn = nsnull;
+    return convertResultCode(srv);
+  }
+
+  // Properly wrap the database handle's mutex.
+  sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn));
+
+#ifdef PR_LOGGING
+  if (!gStorageLog)
+    gStorageLog = ::PR_NewLogModule("mozStorage");
+
+  ::sqlite3_trace(mDBConn, tracefunc, this);
+
+  nsCAutoString leafName(":memory");
+  if (aDatabaseFile)
+    (void)aDatabaseFile->GetNativeLeafName(leafName);
+  PR_LOG(gStorageLog, PR_LOG_NOTICE, ("Opening connection to '%s' (%p)",
+                                      leafName.get(), this));
+#endif
+
+  // Register our built-in SQL functions.
+  srv = registerFunctions(mDBConn);
+  if (srv != SQLITE_OK) {
+    ::sqlite3_close(mDBConn);
+    mDBConn = nsnull;
+    return convertResultCode(srv);
+  }
+
+  // Register our built-in SQL collating sequences.
+  srv = registerCollations(mDBConn, mStorageService);
+  if (srv != SQLITE_OK) {
+    ::sqlite3_close(mDBConn);
+    mDBConn = nsnull;
+    return convertResultCode(srv);
+  }
+
+  // Execute a dummy statement to force the db open, and to verify if it is
+  // valid or not.
+  sqlite3_stmt *stmt;
+  srv = ::sqlite3_prepare_v2(mDBConn, "SELECT * FROM sqlite_master", -1, &stmt,
+                             NULL);
+  if (srv == SQLITE_OK) {
+    srv = ::sqlite3_step(stmt);
+
+    if (srv == SQLITE_DONE || srv == SQLITE_ROW)
+        srv = SQLITE_OK;
+    ::sqlite3_finalize(stmt);
+  }
+
+  if (srv != SQLITE_OK) {
+    ::sqlite3_close(mDBConn);
+    mDBConn = nsnull;
+
+    return convertResultCode(srv);
+  }
+
+  // Set the synchronous PRAGMA, according to the pref
+  nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID));
+  PRInt32 synchronous = 1; // Default to NORMAL if pref not set
+  if (pref)
+    (void)pref->GetIntPref(PREF_TS_SYNCHRONOUS, &synchronous);
+
+  switch (synchronous) {
+    case 2:
+      (void)ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          "PRAGMA synchronous = FULL;"));
+      break;
+    case 0:
+      (void)ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          "PRAGMA synchronous = OFF;"));
+      break;
+    case 1:
+    default:
+      (void)ExecuteSimpleSQL(NS_LITERAL_CSTRING(
+          "PRAGMA synchronous = NORMAL;"));
+      break;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+Connection::databaseElementExists(enum DatabaseElementType aElementType,
+                                  const nsACString &aElementName,
+                                  PRBool *_exists)
+{
+  if (!mDBConn) return NS_ERROR_NOT_INITIALIZED;
+
+  nsCAutoString query("SELECT name FROM sqlite_master WHERE type = '");
+  switch (aElementType) {
+    case INDEX:
+      query.Append("index");
+      break;
+    case TABLE:
+      query.Append("table");
+      break;
+  }
+  query.Append("' AND name ='");
+  query.Append(aElementName);
+  query.Append("'");
+
+  sqlite3_stmt *stmt;
+  int srv = ::sqlite3_prepare_v2(mDBConn, query.get(), -1, &stmt, NULL);
+  if (srv != SQLITE_OK)
+    return convertResultCode(srv);
+
+  srv = ::sqlite3_step(stmt);
+  // we just care about the return value from step
+  (void)::sqlite3_finalize(stmt);
+
+  if (srv == SQLITE_ROW) {
+    *_exists = PR_TRUE;
+    return NS_OK;
+  }
+  if (srv == SQLITE_DONE) {
+    *_exists = PR_FALSE;
+    return NS_OK;
+  }
+
+  return convertResultCode(srv);
+}
+
+bool
+Connection::findFunctionByInstance(nsISupports *aInstance)
+{
+  sharedDBMutex.assertCurrentThreadOwns();
+  FFEArguments args = { aInstance, false };
+  mFunctions.EnumerateRead(findFunctionEnumerator, &args);
+  return args.found;
+}
+
+/* static */ int
+Connection::sProgressHelper(void *aArg)
+{
+  Connection *_this = static_cast<Connection *>(aArg);
+  return _this->progressHandler();
+}
+
+int
+Connection::progressHandler()
+{
+  sharedDBMutex.assertCurrentThreadOwns();
+  if (mProgressHandler) {
+    PRBool result;
+    nsresult rv = mProgressHandler->OnProgress(this, &result);
+    if (NS_FAILED(rv)) return 0; // Don't break request
+    return result ? 1 : 0;
+  }
+  return 0;
+}
+
+nsresult
+Connection::setClosedState()
+{
+  // Ensure that we are on the correct thread to close the database.
+  PRBool onOpenedThread;
+  nsresult rv = threadOpenedOn->IsOnCurrentThread(&onOpenedThread);
+  NS_ENSURE_SUCCESS(rv, rv);
+  if (!onOpenedThread) {
+    NS_ERROR("Must close the database on the thread that you opened it with!");
+    return NS_ERROR_UNEXPECTED;
+  }
+
+  // Flag that we are shutting down the async thread, so that
+  // getAsyncExecutionTarget knows not to expose/create the async thread.
+  {
+    MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
+    NS_ENSURE_FALSE(mAsyncExecutionThreadShuttingDown, NS_ERROR_UNEXPECTED);
+    mAsyncExecutionThreadShuttingDown = true;
+  }
+
+  return NS_OK;
+}
+
+nsresult
+Connection::internalClose()
+{
+#ifdef DEBUG
+  // Sanity checks to make sure we are in the proper state before calling this.
+  NS_ASSERTION(mDBConn, "Database connection is already null!");
+
+  { // Make sure we have marked our async thread as shutting down.
+    MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
+    NS_ASSERTION(mAsyncExecutionThreadShuttingDown,
+                 "Did not call setClosedState!");
+  }
+
+  { // Ensure that we are being called on the thread we were opened with.
+    PRBool onOpenedThread = PR_FALSE;
+    (void)threadOpenedOn->IsOnCurrentThread(&onOpenedThread);
+    NS_ASSERTION(onOpenedThread,
+                 "Not called on the thread the database was opened on!");
+  }
+#endif
+
+#ifdef PR_LOGGING
+  nsCAutoString leafName(":memory");
+  if (mDatabaseFile)
+      (void)mDatabaseFile->GetNativeLeafName(leafName);
+  PR_LOG(gStorageLog, PR_LOG_NOTICE, ("Closing connection to '%s'",
+                                      leafName.get()));
+#endif
+
+#ifdef DEBUG
+  // Notify about any non-finalized statements.
+  sqlite3_stmt *stmt = NULL;
+  while ((stmt = ::sqlite3_next_stmt(mDBConn, stmt))) {
+    char *msg = ::PR_smprintf("SQL statement '%s' was not finalized",
+                              ::sqlite3_sql(stmt));
+    NS_WARNING(msg);
+    ::PR_smprintf_free(msg);
+  }
+#endif
+
+  int srv = ::sqlite3_close(mDBConn);
+  NS_ASSERTION(srv == SQLITE_OK,
+               "sqlite3_close failed. There are probably outstanding statements that are listed above!");
+
+  mDBConn = NULL;
+  return convertResultCode(srv);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//// mozIStorageConnection
+
+NS_IMETHODIMP
+Connection::Close()
+{
+  if (!mDBConn)
+    return NS_ERROR_NOT_INITIALIZED;
+
+  { // Make sure we have not executed any asynchronous statements.
+    MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
+    NS_ENSURE_FALSE(mAsyncExecutionThread, NS_ERROR_UNEXPECTED);
+  }
+
+  nsresult rv = setClosedState();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return internalClose();
+}
+
+NS_IMETHODIMP
+Connection::AsyncClose(mozIStorageCompletionCallback *aCallback)
+{
+  if (!mDBConn)
+    return NS_ERROR_NOT_INITIALIZED;
+
+  nsIEventTarget *asyncThread = getAsyncExecutionTarget();
+  NS_ENSURE_TRUE(asyncThread, NS_ERROR_UNEXPECTED);
+
+  nsresult rv = setClosedState();
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Create our callback event if we were given a callback.
+  nsCOMPtr<nsIRunnable> completeEvent;
+  if (aCallback) {
+    completeEvent = newCompletionEvent(aCallback);
+    NS_ENSURE_TRUE(completeEvent, NS_ERROR_OUT_OF_MEMORY);
+  }
+
+  // Create and dispatch our close event to the background thread.
+  nsCOMPtr<nsIRunnable> closeEvent;
+  {
+    MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
+    closeEvent = new AsyncCloseConnection(this, NS_GetCurrentThread(),
+                                          completeEvent,
+                                          mAsyncExecutionThread);
+    // forget about the async thread (this is why we're holding the mutex)
+    mAsyncExecutionThread = nsnull;
+  }
+  NS_ENSURE_TRUE(closeEvent, NS_ERROR_OUT_OF_MEMORY);
+
+  rv = asyncThread->Dispatch(closeEvent, NS_DISPATCH_NORMAL);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  return NS_OK;
+}
+