Source code

Revision control

Copy as Markdown

Other Tools

/* 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/. */
#ifndef mozilla_places_Helpers_h_
#define mozilla_places_Helpers_h_
/**
* This file contains helper classes used by various bits of Places code.
*/
#include "mozilla/storage.h"
#include "nsIURI.h"
#include "nsThreadUtils.h"
#include "nsProxyRelease.h"
#include "prtime.h"
#include "mozilla/Telemetry.h"
#include "mozIStorageStatementCallback.h"
class nsIFile;
namespace mozilla {
namespace places {
////////////////////////////////////////////////////////////////////////////////
//// Asynchronous Statement Callback Helper
class WeakAsyncStatementCallback : public mozIStorageStatementCallback {
public:
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
WeakAsyncStatementCallback() = default;
protected:
virtual ~WeakAsyncStatementCallback() = default;
};
class AsyncStatementCallback : public WeakAsyncStatementCallback {
public:
NS_DECL_ISUPPORTS
AsyncStatementCallback() = default;
protected:
virtual ~AsyncStatementCallback() = default;
};
/**
* Macros to use in place of NS_DECL_MOZISTORAGESTATEMENTCALLBACK to declare the
* methods this class assumes silent or notreached.
*/
#define NS_DECL_ASYNCSTATEMENTCALLBACK \
NS_IMETHOD HandleResult(mozIStorageResultSet*) override; \
NS_IMETHOD HandleCompletion(uint16_t) override;
/**
* Utils to bind a specified URI (or URL) to a statement or binding params, at
* the specified index or name.
* @note URIs are always bound as UTF8.
*/
class URIBinder // static
{
public:
// Bind URI to statement by index.
static nsresult Bind(mozIStorageStatement* statement, int32_t index,
nsIURI* aURI);
// Statement URLCString to statement by index.
static nsresult Bind(mozIStorageStatement* statement, int32_t index,
const nsACString& aURLString);
// Bind URI to statement by name.
static nsresult Bind(mozIStorageStatement* statement, const nsACString& aName,
nsIURI* aURI);
// Bind URLCString to statement by name.
static nsresult Bind(mozIStorageStatement* statement, const nsACString& aName,
const nsACString& aURLString);
// Bind URI to params by index.
static nsresult Bind(mozIStorageBindingParams* aParams, int32_t index,
nsIURI* aURI);
// Bind URLCString to params by index.
static nsresult Bind(mozIStorageBindingParams* aParams, int32_t index,
const nsACString& aURLString);
// Bind URI to params by name.
static nsresult Bind(mozIStorageBindingParams* aParams,
const nsACString& aName, nsIURI* aURI);
// Bind URLCString to params by name.
static nsresult Bind(mozIStorageBindingParams* aParams,
const nsACString& aName, const nsACString& aURLString);
};
/**
* This extracts the hostname from the URI and reverses it in the
* form that we use (always ending with a "."). So
* "http://microsoft.com/" becomes "moc.tfosorcim."
*
* The idea behind this is that we can create an index over the items in
* the reversed host name column, and then query for as much or as little
* of the host name as we feel like.
*
* For example, the query "host >= 'gro.allizom.' AND host < 'gro.allizom/'
* Matches all host names ending in '.mozilla.org', including
* 'developer.mozilla.org' and just 'mozilla.org' (since we define all
* reversed host names to end in a period, even 'mozilla.org' matches).
* The important thing is that this operation uses the index. Any substring
* calls in a select statement (even if it's for the beginning of a string)
* will bypass any indices and will be slow).
*
* @param aURI
* URI that contains spec to reverse
* @param aRevHost
* Out parameter
*/
nsresult GetReversedHostname(nsIURI* aURI, nsString& aRevHost);
/**
* Similar method to GetReversedHostName but for strings
*/
void GetReversedHostname(const nsString& aForward, nsString& aRevHost);
/**
* Reverses a string.
*
* @param aInput
* The string to be reversed
* @param aReversed
* Output parameter will contain the reversed string
*/
void ReverseString(const nsString& aInput, nsString& aReversed);
/**
* Generates an 12 character guid to be used by bookmark and history entries.
*
* @note This guid uses the characters a-z, A-Z, 0-9, '-', and '_'.
*/
nsresult GenerateGUID(nsACString& _guid);
/**
* Determines if the string is a valid guid or not.
*
* @param aGUID
* The guid to test.
* @return true if it is a valid guid, false otherwise.
*/
bool IsValidGUID(const nsACString& aGUID);
/**
* Truncates the title if it's longer than TITLE_LENGTH_MAX.
*
* @param aTitle
* The title to truncate (if necessary)
* @param aTrimmed
* Output parameter to return the trimmed string
*/
void TruncateTitle(const nsACString& aTitle, nsACString& aTrimmed);
/**
* Round down a PRTime value to milliseconds precision (...000).
*
* @param aTime
* a PRTime value.
* @return aTime rounded down to milliseconds precision.
*/
PRTime RoundToMilliseconds(PRTime aTime);
/**
* Round down PR_Now() to milliseconds precision.
*
* @return @see PR_Now, RoundToMilliseconds.
*/
PRTime RoundedPRNow();
nsresult HashURL(const nsACString& aSpec, const nsACString& aMode,
uint64_t* _hash);
/**
* Return exposable URL from given URI.
*
* @param aURI The URI to be converted.
* @return already_AddRefed<nsIURI> The converted, exposable URI.
*/
already_AddRefed<nsIURI> GetExposableURI(nsIURI* aURI);
class QueryKeyValuePair final {
public:
QueryKeyValuePair(const nsACString& aKey, const nsACString& aValue) {
key = aKey;
value = aValue;
};
// QueryKeyValuePair
//
// 01234567890
// input : qwerty&key=value&qwerty
// ^ ^ ^
// aKeyBegin | aPastEnd (may point to null terminator)
// aEquals
//
// Special case: if aKeyBegin == aEquals, then there is only one string
// and no equal sign, so we treat the entire thing as a key with no value
QueryKeyValuePair(const nsACString& aSource, int32_t aKeyBegin,
int32_t aEquals, int32_t aPastEnd) {
if (aEquals == aKeyBegin) aEquals = aPastEnd;
key = Substring(aSource, aKeyBegin, aEquals - aKeyBegin);
if (aPastEnd - aEquals > 0)
value = Substring(aSource, aEquals + 1, aPastEnd - aEquals - 1);
}
nsCString key;
nsCString value;
};
/**
* Tokenizes a QueryString.
*
* @param aQuery The string to tokenize.
* @param aTokens The tokenized result.
*/
nsresult TokenizeQueryString(const nsACString& aQuery,
nsTArray<QueryKeyValuePair>* aTokens);
void TokensToQueryString(const nsTArray<QueryKeyValuePair>& aTokens,
nsACString& aQuery);
/**
* 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. This utility is meant
* to be used on database files with no open connections. Using this on database
* files with open connections may result in a corrupt backup file.
*
* @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.
* @param backup
* An outparam for the nsIFile pointing to the backup copy.
*/
nsresult BackupDatabaseFile(nsIFile* aDBFile, const nsAString& aBackupFileName,
nsIFile* aBackupParentDirectory, nsIFile** backup);
/**
* Used to finalize a statementCache on a specified thread.
*/
template <typename StatementType>
class FinalizeStatementCacheProxy : public Runnable {
public:
/**
* Constructor.
*
* @param aStatementCache
* The statementCache that should be finalized.
* @param aOwner
* The object that owns the statement cache. This runnable will hold
* a strong reference to it so aStatementCache will not disappear from
* under us.
*/
FinalizeStatementCacheProxy(
mozilla::storage::StatementCache<StatementType>& aStatementCache,
nsISupports* aOwner)
: Runnable("places::FinalizeStatementCacheProxy"),
mStatementCache(aStatementCache),
mOwner(aOwner),
mCallingThread(do_GetCurrentThread()) {}
NS_IMETHOD Run() override {
mStatementCache.FinalizeStatements();
// Release the owner back on the calling thread.
NS_ProxyRelease("FinalizeStatementCacheProxy::mOwner", mCallingThread,
mOwner.forget());
return NS_OK;
}
protected:
mozilla::storage::StatementCache<StatementType>& mStatementCache;
nsCOMPtr<nsISupports> mOwner;
nsCOMPtr<nsIThread> mCallingThread;
};
/**
* Determines if a visit should be marked as hidden given its transition type
* and whether or not it was a redirect.
*
* @param aIsRedirect
* True if this visit was a redirect, false otherwise.
* @param aTransitionType
* The transition type of the visit.
* @return true if this visit should be hidden.
*/
bool GetHiddenState(bool aIsRedirect, uint32_t aTransitionType);
/**
* Used to notify a topic to system observers on async execute completion.
*/
class AsyncStatementTelemetryTimer : public AsyncStatementCallback {
public:
explicit AsyncStatementTelemetryTimer(Telemetry::HistogramID aHistogramId,
TimeStamp aStart = TimeStamp::Now())
: mHistogramId(aHistogramId), mStart(aStart) {}
NS_IMETHOD HandleCompletion(uint16_t aReason) override;
private:
const Telemetry::HistogramID mHistogramId;
const TimeStamp mStart;
};
} // namespace places
} // namespace mozilla
#endif // mozilla_places_Helpers_h_