/* 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" 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 nsAString& aSpec, const nsACString& aMode, uint64_t* _hash); 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* aTokens); void TokensToQueryString(const nsTArray& aTokens, nsACString& aQuery); /** * Used to finalize a statementCache on a specified thread. */ template 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& 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& mStatementCache; nsCOMPtr mOwner; nsCOMPtr 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_