Bug 1293445 - 1 - Add a get_query_param SQL function. r=mak
MozReview-Commit-ID: 12r5GyhoYgi
--- a/toolkit/components/places/Database.cpp
+++ b/toolkit/components/places/Database.cpp
@@ -1440,16 +1440,18 @@ Database::InitFunctions()
rv = FixupURLFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
rv = FrecencyNotificationFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
rv = StoreLastInsertedIdFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
rv = HashFunction::create(mMainConn);
NS_ENSURE_SUCCESS(rv, rv);
+ rv = GetQueryParamFunction::create(mMainConn);
+ NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;
}
nsresult
Database::InitTempEntities()
{
MOZ_ASSERT(NS_IsMainThread());
--- a/toolkit/components/places/SQLFunctions.cpp
+++ b/toolkit/components/places/SQLFunctions.cpp
@@ -1,14 +1,15 @@
/* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/storage.h"
+#include "mozilla/dom/URLSearchParams.h"
#include "nsString.h"
#include "nsUnicharUtils.h"
#include "nsWhitespaceTokenizer.h"
#include "nsEscape.h"
#include "mozIPlacesAutoComplete.h"
#include "SQLFunctions.h"
#include "nsMathUtils.h"
#include "nsUnicodeProperties.h"
@@ -241,16 +242,41 @@ namespace {
uint32_t len;
const char* str = aValues->AsSharedUTF8String(aIndex, &len);
if (!str) {
return nsDependentCString("", (uint32_t)0);
}
return nsDependentCString(str, len);
}
+ class MOZ_STACK_CLASS GetQueryParamIterator final :
+ public URLParams::ForEachIterator
+ {
+ public:
+ explicit GetQueryParamIterator(const nsCString& aParamName,
+ nsVariant* aResult)
+ : mParamName(aParamName)
+ , mResult(aResult)
+ {}
+
+ bool URLParamsIterator(const nsAString& aName,
+ const nsAString& aValue) override
+ {
+ NS_ConvertUTF16toUTF8 name(aName);
+ if (!mParamName.Equals(name)) {
+ return true;
+ }
+ mResult->SetAsAString(aValue);
+ return false;
+ }
+ private:
+ const nsCString& mParamName;
+ nsVariant* mResult;
+ };
+
} // End anonymous namespace
namespace mozilla {
namespace places {
////////////////////////////////////////////////////////////////////////////////
//// AutoComplete Matching Function
@@ -1002,16 +1028,54 @@ namespace places {
RefPtr<nsVariant> result = new nsVariant();
rv = result->SetAsInt64(lastInsertedId);
NS_ENSURE_SUCCESS(rv, rv);
result.forget(_result);
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
+//// Get Query Param Function
+
+ /* static */
+ nsresult
+ GetQueryParamFunction::create(mozIStorageConnection *aDBConn)
+ {
+ RefPtr<GetQueryParamFunction> function = new GetQueryParamFunction();
+ return aDBConn->CreateFunction(
+ NS_LITERAL_CSTRING("get_query_param"), 2, function
+ );
+ }
+
+ NS_IMPL_ISUPPORTS(
+ GetQueryParamFunction,
+ mozIStorageFunction
+ )
+
+ NS_IMETHODIMP
+ GetQueryParamFunction::OnFunctionCall(mozIStorageValueArray *aArguments,
+ nsIVariant **_result)
+ {
+ // Must have non-null function arguments.
+ MOZ_ASSERT(aArguments);
+
+ nsDependentCString queryString = getSharedUTF8String(aArguments, 0);
+ nsDependentCString paramName = getSharedUTF8String(aArguments, 1);
+
+ RefPtr<nsVariant> result = new nsVariant();
+ if (!queryString.IsEmpty() && !paramName.IsEmpty()) {
+ GetQueryParamIterator iterator(paramName, result);
+ URLParams::Parse(queryString, iterator);
+ }
+
+ result.forget(_result);
+ return NS_OK;
+ }
+
+////////////////////////////////////////////////////////////////////////////////
//// Hash Function
/* static */
nsresult
HashFunction::create(mozIStorageConnection *aDBConn)
{
RefPtr<HashFunction> function = new HashFunction();
return aDBConn->CreateFunction(
--- a/toolkit/components/places/SQLFunctions.h
+++ b/toolkit/components/places/SQLFunctions.h
@@ -411,12 +411,41 @@ public:
* @param aDBConn
* The database connection to register with.
*/
static nsresult create(mozIStorageConnection *aDBConn);
private:
~HashFunction() {}
};
+////////////////////////////////////////////////////////////////////////////////
+//// Get Query Param Function
+
+/**
+ * Extracts and returns the value of a parameter from a query string.
+ *
+ * @param string
+ * A string.
+ * @return
+ * The value of the query parameter as a string, or NULL if not set.
+ */
+class GetQueryParamFunction final : public mozIStorageFunction
+{
+public:
+ NS_DECL_THREADSAFE_ISUPPORTS
+ NS_DECL_MOZISTORAGEFUNCTION
+
+ /**
+ * Registers the function with the specified database connection.
+ *
+ * @param aDBConn
+ * The database connection to register with.
+ */
+ static nsresult create(mozIStorageConnection *aDBConn);
+private:
+ ~GetQueryParamFunction() {}
+};
+
+
} // namespace places
} // namespace mozilla
#endif // mozilla_places_SQLFunctions_h_
new file mode 100644
--- /dev/null
+++ b/toolkit/components/places/tests/unit/test_get_query_param_sql_function.js
@@ -0,0 +1,19 @@
+add_task(async function test_get_query_param_sql_function() {
+ let db = await PlacesUtils.promiseDBConnection();
+ await Assert.rejects(db.execute(`SELECT get_query_param()`),
+ /wrong number of arguments/);
+ let rows = await db.execute(`SELECT
+ get_query_param('a=b&c=d', 'a'),
+ get_query_param('a=b&c=d', 'c'),
+ get_query_param('a=b&a=c', 'a'),
+ get_query_param('a=b&c=d', 'e'),
+ get_query_param('a', 'a'),
+ get_query_param(NULL, NULL),
+ get_query_param('a=b&c=d', NULL),
+ get_query_param(NULL, 'a')`);
+ let results = ["b", "d", "b", null, "", null, null, null];
+ equal(rows[0].numEntries, results.length);
+ for (let i = 0; i < results.length; ++i) {
+ equal(rows[0].getResultByIndex(i), results[i]);
+ }
+});
--- a/toolkit/components/places/tests/unit/xpcshell.ini
+++ b/toolkit/components/places/tests/unit/xpcshell.ini
@@ -107,8 +107,9 @@ skip-if = (os == "win" && os_version ==
[test_tag_autocomplete_search.js]
[test_tagging.js]
[test_telemetry.js]
[test_update_frecency_after_delete.js]
[test_utils_backups_create.js]
[test_utils_getURLsForContainerNode.js]
[test_utils_setAnnotationsForItem.js]
[test_visitsInDB.js]
+[test_get_query_param_sql_function.js]