Bug 1305563 - Expose `PlacesUtils.history.hashURL`.
MozReview-Commit-ID: C4Zj4FyMZpq
--- a/toolkit/components/places/Helpers.cpp
+++ b/toolkit/components/places/Helpers.cpp
@@ -4,16 +4,17 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "Helpers.h"
#include "mozIStorageError.h"
#include "prio.h"
#include "nsString.h"
#include "nsNavHistory.h"
#include "mozilla/Base64.h"
+#include "mozilla/HashFunctions.h"
#include "mozilla/Services.h"
// The length of guids that are used by history and bookmarks.
#define GUID_LENGTH 12
namespace mozilla {
namespace places {
@@ -306,16 +307,58 @@ RoundToMilliseconds(PRTime aTime) {
return aTime - (aTime % PR_USEC_PER_MSEC);
}
PRTime
RoundedPRNow() {
return RoundToMilliseconds(PR_Now());
}
+nsresult
+HashURL(const nsAString& aSpec, const nsACString& aMode, uint64_t *_hash)
+{
+ NS_ENSURE_ARG_POINTER(_hash);
+
+ if (aMode.IsEmpty()) {
+ // URI-like strings (having a prefix before a colon), are handled specially,
+ // as a 48 bit hash, where first 16 bits are the prefix hash, while the
+ // other 32 are the string hash.
+ // The 16 bits have been decided based on the fact hashing all of the IANA
+ // known schemes, plus "places", does not generate collisions.
+ nsAString::const_iterator start, tip, end;
+ aSpec.BeginReading(tip);
+ start = tip;
+ aSpec.EndReading(end);
+ if (FindInReadable(NS_LITERAL_STRING(":"), tip, end)) {
+ const nsDependentSubstring& prefix = Substring(start, tip);
+ uint64_t prefixHash = static_cast<uint64_t>(HashString(prefix) & 0x0000FFFF);
+ // The second half of the url is more likely to be unique, so we add it.
+ uint32_t srcHash = HashString(aSpec);
+ *_hash = (prefixHash << 32) + srcHash;
+ } else {
+ *_hash = HashString(aSpec);
+ }
+ return NS_OK;
+ }
+ if (aMode.Equals(NS_LITERAL_CSTRING("prefix_lo"))) {
+ // Keep only 16 bits.
+ *_hash = static_cast<uint64_t>(HashString(aSpec) & 0x0000FFFF) << 32;
+ return NS_OK;
+ }
+ if (aMode.Equals(NS_LITERAL_CSTRING("prefix_hi"))) {
+ // Keep only 16 bits.
+ *_hash = static_cast<uint64_t>(HashString(aSpec) & 0x0000FFFF) << 32;
+ // Make this a prefix upper bound by filling the lowest 32 bits.
+ *_hash += 0xFFFFFFFF;
+ return NS_OK;
+ }
+
+ return NS_ERROR_FAILURE;
+}
+
bool
GetHiddenState(bool aIsRedirect,
uint32_t aTransitionType)
{
return aTransitionType == nsINavHistoryService::TRANSITION_FRAMED_LINK ||
aTransitionType == nsINavHistoryService::TRANSITION_EMBED ||
aIsRedirect;
}
--- a/toolkit/components/places/Helpers.h
+++ b/toolkit/components/places/Helpers.h
@@ -169,16 +169,19 @@ PRTime RoundToMilliseconds(PRTime aTime)
/**
* Round down PR_Now() to milliseconds precision.
*
* @return @see PR_Now, RoundToMilliseconds.
*/
PRTime RoundedPRNow();
+nsresult HashURL(const nsAString& aSpec, const nsACString& aMode,
+ uint64_t *_hash);
+
/**
* Used to finalize a statementCache on a specified thread.
*/
template<typename StatementType>
class FinalizeStatementCacheProxy : public Runnable
{
public:
/**
--- a/toolkit/components/places/SQLFunctions.cpp
+++ b/toolkit/components/places/SQLFunctions.cpp
@@ -13,17 +13,16 @@
#include "nsMathUtils.h"
#include "nsUnicodeProperties.h"
#include "nsUTF8Utils.h"
#include "nsINavHistoryService.h"
#include "nsPrintfCString.h"
#include "nsNavHistory.h"
#include "mozilla/Likely.h"
#include "nsVariant.h"
-#include "mozilla/HashFunctions.h"
// Maximum number of chars to search through.
// MatchAutoCompleteFunction won't look for matches over this threshold.
#define MAX_CHARS_TO_SEARCH_THROUGH 255
using namespace mozilla::storage;
////////////////////////////////////////////////////////////////////////////////
@@ -1007,49 +1006,20 @@ namespace places {
nsString str;
aArguments->GetString(0, str);
nsAutoCString mode;
if (numEntries > 1) {
aArguments->GetUTF8String(1, mode);
}
RefPtr<nsVariant> result = new nsVariant();
- if (mode.IsEmpty()) {
- // URI-like strings (having a prefix before a colon), are handled specially,
- // as a 48 bit hash, where first 16 bits are the prefix hash, while the
- // other 32 are the string hash.
- // The 16 bits have been decided based on the fact hashing all of the IANA
- // known schemes, plus "places", does not generate collisions.
- nsAString::const_iterator start, tip, end;
- str.BeginReading(tip);
- start = tip;
- str.EndReading(end);
- if (FindInReadable(NS_LITERAL_STRING(":"), tip, end)) {
- const nsDependentSubstring& prefix = Substring(start, tip);
- uint64_t prefixHash = static_cast<uint64_t>(HashString(prefix) & 0x0000FFFF);
- // The second half of the url is more likely to be unique, so we add it.
- uint32_t srcHash = HashString(str);
- uint64_t hash = (prefixHash << 32) + srcHash;
- result->SetAsInt64(hash);
- } else {
- uint32_t hash = HashString(str);
- result->SetAsInt64(hash);
- }
- } else if (mode.Equals(NS_LITERAL_CSTRING("prefix_lo"))) {
- // Keep only 16 bits.
- uint64_t hash = static_cast<uint64_t>(HashString(str) & 0x0000FFFF) << 32;
- result->SetAsInt64(hash);
- } else if (mode.Equals(NS_LITERAL_CSTRING("prefix_hi"))) {
- // Keep only 16 bits.
- uint64_t hash = static_cast<uint64_t>(HashString(str) & 0x0000FFFF) << 32;
- // Make this a prefix upper bound by filling the lowest 32 bits.
- hash += 0xFFFFFFFF;
- result->SetAsInt64(hash);
- } else {
- return NS_ERROR_FAILURE;
- }
+ uint64_t hash;
+ rv = HashURL(str, mode, &hash);
+ NS_ENSURE_SUCCESS(rv, rv);
+ rv = result->SetAsInt64(hash);
+ NS_ENSURE_SUCCESS(rv, rv);
result.forget(_result);
return NS_OK;
}
} // namespace places
} // namespace mozilla
--- a/toolkit/components/places/nsINavHistoryService.idl
+++ b/toolkit/components/places/nsINavHistoryService.idl
@@ -1431,16 +1431,18 @@ interface nsINavHistoryService : nsISupp
void clearEmbedVisits();
/**
* Generate a guid.
* Guids can be used for any places purposes (history, bookmarks, etc.)
* Returns null if the generation of the guid failed.
*/
ACString makeGuid();
+
+ uint64_t hashURL(in AString aSpec, [optional] in ACString mode);
};
/**
* @see runInBatchMode of nsINavHistoryService/nsINavBookmarksService
*/
[scriptable, function, uuid(5a5a9154-95ac-4e3d-90df-558816297407)]
interface nsINavHistoryBatchCallback : nsISupports {
void runBatched(in nsISupports aUserData);
--- a/toolkit/components/places/nsNavHistory.cpp
+++ b/toolkit/components/places/nsNavHistory.cpp
@@ -3756,16 +3756,22 @@ NS_IMETHODIMP
nsNavHistory::MakeGuid(nsACString& aGuid) {
if (NS_FAILED(GenerateGUID(aGuid))) {
MOZ_ASSERT(false, "Shouldn't fail to create a guid!");
aGuid.SetIsVoid(true);
}
return NS_OK;
}
+NS_IMETHODIMP
+nsNavHistory::HashURL(const nsAString& aSpec, const nsACString& aMode,
+ uint64_t* aHash) {
+ return places::HashURL(aSpec, aMode, aHash);
+}
+
// nsNavHistory::CheckIsRecentEvent
//
// Sees if this URL happened "recently."
//
// It is always removed from our recent list no matter what. It only counts
// as "recent" if the event happened more recently than our event
// threshold ago.