summaryrefslogtreecommitdiffstats
path: root/toolkit/components/places/Helpers.h
blob: 6719fdded29b2b489b426c73e58f66237929877e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
/* 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);

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_