Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/toolkit/components/places/nsNavHistoryQuery.cpp
Line
Count
Source (jump to first uncovered line)
1
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
/**
7
 * This file contains the definitions of nsNavHistoryQuery,
8
 * nsNavHistoryQueryOptions, and those functions in nsINavHistory that directly
9
 * support queries (specifically QueryStringToQuery and QueryToQueryString).
10
 */
11
12
#include "mozilla/DebugOnly.h"
13
14
#include "nsNavHistory.h"
15
#include "nsNavBookmarks.h"
16
#include "nsEscape.h"
17
#include "nsCOMArray.h"
18
#include "nsNetUtil.h"
19
#include "nsTArray.h"
20
#include "prprf.h"
21
#include "nsVariant.h"
22
23
using namespace mozilla;
24
using namespace mozilla::places;
25
26
static nsresult ParseQueryBooleanString(const nsCString& aString,
27
                                        bool* aValue);
28
29
// query getters
30
typedef decltype(&nsINavHistoryQuery::GetOnlyBookmarked) BoolQueryGetter;
31
typedef decltype(&nsINavHistoryQuery::GetBeginTimeReference) Uint32QueryGetter;
32
typedef decltype(&nsINavHistoryQuery::GetBeginTime) Int64QueryGetter;
33
static void AppendBoolKeyValueIfTrue(nsACString& aString,
34
                                     const nsCString& aName,
35
                                     nsINavHistoryQuery* aQuery,
36
                                     BoolQueryGetter getter);
37
static void AppendUint32KeyValueIfNonzero(nsACString& aString,
38
                                          const nsCString& aName,
39
                                          nsINavHistoryQuery* aQuery,
40
                                          Uint32QueryGetter getter);
41
static void AppendInt64KeyValueIfNonzero(nsACString& aString,
42
                                         const nsCString& aName,
43
                                         nsINavHistoryQuery* aQuery,
44
                                         Int64QueryGetter getter);
45
46
// query setters
47
typedef decltype(&nsINavHistoryQuery::SetOnlyBookmarked) BoolQuerySetter;
48
typedef decltype(&nsINavHistoryQuery::SetBeginTimeReference) Uint32QuerySetter;
49
typedef decltype(&nsINavHistoryQuery::SetBeginTime) Int64QuerySetter;
50
static void SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
51
                            BoolQuerySetter setter);
52
static void SetQueryKeyUint32(const nsCString& aValue, nsINavHistoryQuery* aQuery,
53
                              Uint32QuerySetter setter);
54
static void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery,
55
                             Int64QuerySetter setter);
56
57
// options setters
58
typedef decltype(&nsINavHistoryQueryOptions::SetExpandQueries) BoolOptionsSetter;
59
typedef decltype(&nsINavHistoryQueryOptions::SetMaxResults) Uint32OptionsSetter;
60
typedef decltype(&nsINavHistoryQueryOptions::SetResultType) Uint16OptionsSetter;
61
static void SetOptionsKeyBool(const nsCString& aValue,
62
                              nsINavHistoryQueryOptions* aOptions,
63
                              BoolOptionsSetter setter);
64
static void SetOptionsKeyUint16(const nsCString& aValue,
65
                                nsINavHistoryQueryOptions* aOptions,
66
                                Uint16OptionsSetter setter);
67
static void SetOptionsKeyUint32(const nsCString& aValue,
68
                                nsINavHistoryQueryOptions* aOptions,
69
                                Uint32OptionsSetter setter);
70
71
// Components of a query string.
72
// Note that query strings are also generated in nsNavBookmarks::GetFolderURI
73
// for performance reasons, so if you change these values, change that, too.
74
0
#define QUERYKEY_BEGIN_TIME "beginTime"
75
0
#define QUERYKEY_BEGIN_TIME_REFERENCE "beginTimeRef"
76
0
#define QUERYKEY_END_TIME "endTime"
77
0
#define QUERYKEY_END_TIME_REFERENCE "endTimeRef"
78
0
#define QUERYKEY_SEARCH_TERMS "terms"
79
0
#define QUERYKEY_MIN_VISITS "minVisits"
80
0
#define QUERYKEY_MAX_VISITS "maxVisits"
81
0
#define QUERYKEY_ONLY_BOOKMARKED "onlyBookmarked"
82
0
#define QUERYKEY_DOMAIN_IS_HOST "domainIsHost"
83
0
#define QUERYKEY_DOMAIN "domain"
84
0
#define QUERYKEY_PARENT "parent"
85
0
#define QUERYKEY_NOTANNOTATION "!annotation"
86
0
#define QUERYKEY_ANNOTATION "annotation"
87
0
#define QUERYKEY_URI "uri"
88
#define QUERYKEY_GROUP "group"
89
0
#define QUERYKEY_SORT "sort"
90
0
#define QUERYKEY_RESULT_TYPE "type"
91
0
#define QUERYKEY_EXCLUDE_ITEMS "excludeItems"
92
0
#define QUERYKEY_EXCLUDE_QUERIES "excludeQueries"
93
0
#define QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS "excludeReadOnlyFolders"
94
0
#define QUERYKEY_EXPAND_QUERIES "expandQueries"
95
#define QUERYKEY_FORCE_ORIGINAL_TITLE "originalTitle"
96
0
#define QUERYKEY_INCLUDE_HIDDEN "includeHidden"
97
0
#define QUERYKEY_MAX_RESULTS "maxResults"
98
0
#define QUERYKEY_QUERY_TYPE "queryType"
99
0
#define QUERYKEY_TAG "tag"
100
0
#define QUERYKEY_NOTTAGS "!tags"
101
0
#define QUERYKEY_ASYNC_ENABLED "asyncEnabled"
102
0
#define QUERYKEY_TRANSITION "transition"
103
104
inline void AppendAmpersandIfNonempty(nsACString& aString)
105
0
{
106
0
  if (! aString.IsEmpty())
107
0
    aString.Append('&');
108
0
}
109
inline void AppendInt16(nsACString& str, int16_t i)
110
0
{
111
0
  nsAutoCString tmp;
112
0
  tmp.AppendInt(i);
113
0
  str.Append(tmp);
114
0
}
115
inline void AppendInt32(nsACString& str, int32_t i)
116
0
{
117
0
  nsAutoCString tmp;
118
0
  tmp.AppendInt(i);
119
0
  str.Append(tmp);
120
0
}
121
inline void AppendInt64(nsACString& str, int64_t i)
122
0
{
123
0
  nsCString tmp;
124
0
  tmp.AppendInt(i);
125
0
  str.Append(tmp);
126
0
}
127
128
NS_IMETHODIMP
129
nsNavHistory::QueryStringToQuery(const nsACString& aQueryString,
130
                                 nsINavHistoryQuery** _query,
131
                                 nsINavHistoryQueryOptions** _options)
132
0
{
133
0
  NS_ENSURE_ARG_POINTER(_query);
134
0
  NS_ENSURE_ARG_POINTER(_options);
135
0
136
0
  nsTArray<QueryKeyValuePair> tokens;
137
0
  nsresult rv = TokenizeQueryString(aQueryString, &tokens);
138
0
  NS_ENSURE_SUCCESS(rv, rv);
139
0
140
0
  RefPtr<nsNavHistoryQueryOptions> options = new nsNavHistoryQueryOptions();
141
0
  RefPtr<nsNavHistoryQuery> query = new nsNavHistoryQuery();
142
0
  rv = TokensToQuery(tokens, query, options);
143
0
  MOZ_ASSERT(NS_SUCCEEDED(rv), "The query string should be valid");
144
0
  if (NS_FAILED(rv)) {
145
0
    NS_WARNING("Unable to parse the query string: ");
146
0
    NS_WARNING(PromiseFlatCString(aQueryString).get());
147
0
  }
148
0
149
0
  options.forget(_options);
150
0
  query.forget(_query);
151
0
  return NS_OK;
152
0
}
153
154
NS_IMETHODIMP
155
nsNavHistory::QueryToQueryString(nsINavHistoryQuery *aQuery,
156
                                 nsINavHistoryQueryOptions* aOptions,
157
                                 nsACString& aQueryString)
158
0
{
159
0
  NS_ENSURE_ARG(aQuery);
160
0
  NS_ENSURE_ARG(aOptions);
161
0
162
0
  RefPtr<nsNavHistoryQuery> query = do_QueryObject(aQuery);
163
0
  NS_ENSURE_STATE(query);
164
0
  RefPtr<nsNavHistoryQueryOptions> options = do_QueryObject(aOptions);
165
0
  NS_ENSURE_STATE(options);
166
0
167
0
  nsAutoCString queryString;
168
0
  bool hasIt;
169
0
170
0
  // begin time
171
0
  query->GetHasBeginTime(&hasIt);
172
0
  if (hasIt) {
173
0
    AppendInt64KeyValueIfNonzero(queryString,
174
0
                                 NS_LITERAL_CSTRING(QUERYKEY_BEGIN_TIME),
175
0
                                 query, &nsINavHistoryQuery::GetBeginTime);
176
0
    AppendUint32KeyValueIfNonzero(queryString,
177
0
                                  NS_LITERAL_CSTRING(QUERYKEY_BEGIN_TIME_REFERENCE),
178
0
                                  query, &nsINavHistoryQuery::GetBeginTimeReference);
179
0
  }
180
0
181
0
  // end time
182
0
  query->GetHasEndTime(&hasIt);
183
0
  if (hasIt) {
184
0
    AppendInt64KeyValueIfNonzero(queryString,
185
0
                                 NS_LITERAL_CSTRING(QUERYKEY_END_TIME),
186
0
                                 query, &nsINavHistoryQuery::GetEndTime);
187
0
    AppendUint32KeyValueIfNonzero(queryString,
188
0
                                  NS_LITERAL_CSTRING(QUERYKEY_END_TIME_REFERENCE),
189
0
                                  query, &nsINavHistoryQuery::GetEndTimeReference);
190
0
  }
191
0
192
0
  // search terms
193
0
  if (!query->SearchTerms().IsEmpty()) {
194
0
    const nsString& searchTerms = query->SearchTerms();
195
0
    nsCString escapedTerms;
196
0
    if (! NS_Escape(NS_ConvertUTF16toUTF8(searchTerms), escapedTerms,
197
0
                    url_XAlphas))
198
0
      return NS_ERROR_OUT_OF_MEMORY;
199
0
200
0
    AppendAmpersandIfNonempty(queryString);
201
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_SEARCH_TERMS "=");
202
0
    queryString += escapedTerms;
203
0
  }
204
0
205
0
  // min and max visits
206
0
  int32_t minVisits;
207
0
  if (NS_SUCCEEDED(query->GetMinVisits(&minVisits)) && minVisits >= 0) {
208
0
    AppendAmpersandIfNonempty(queryString);
209
0
    queryString.AppendLiteral(QUERYKEY_MIN_VISITS "=");
210
0
    AppendInt32(queryString, minVisits);
211
0
  }
212
0
213
0
  int32_t maxVisits;
214
0
  if (NS_SUCCEEDED(query->GetMaxVisits(&maxVisits)) && maxVisits >= 0) {
215
0
    AppendAmpersandIfNonempty(queryString);
216
0
    queryString.AppendLiteral(QUERYKEY_MAX_VISITS "=");
217
0
    AppendInt32(queryString, maxVisits);
218
0
  }
219
0
220
0
  // only bookmarked
221
0
  AppendBoolKeyValueIfTrue(queryString,
222
0
                           NS_LITERAL_CSTRING(QUERYKEY_ONLY_BOOKMARKED),
223
0
                           query, &nsINavHistoryQuery::GetOnlyBookmarked);
224
0
225
0
  // domain (+ is host), only call if hasDomain, which means non-IsVoid
226
0
  // this means we may get an empty string for the domain in the result,
227
0
  // which is valid
228
0
  if (!query->Domain().IsVoid()) {
229
0
    AppendBoolKeyValueIfTrue(queryString,
230
0
                             NS_LITERAL_CSTRING(QUERYKEY_DOMAIN_IS_HOST),
231
0
                             query, &nsINavHistoryQuery::GetDomainIsHost);
232
0
    const nsCString& domain = query->Domain();
233
0
    nsCString escapedDomain;
234
0
    bool success = NS_Escape(domain, escapedDomain, url_XAlphas);
235
0
    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
236
0
237
0
    AppendAmpersandIfNonempty(queryString);
238
0
    queryString.AppendLiteral(QUERYKEY_DOMAIN "=");
239
0
    queryString.Append(escapedDomain);
240
0
  }
241
0
242
0
  // uri
243
0
  if (query->Uri()) {
244
0
    nsCOMPtr<nsIURI> uri = query->Uri();
245
0
    nsAutoCString uriSpec;
246
0
    nsresult rv = uri->GetSpec(uriSpec);
247
0
    NS_ENSURE_SUCCESS(rv, rv);
248
0
    nsAutoCString escaped;
249
0
    bool success = NS_Escape(uriSpec, escaped, url_XAlphas);
250
0
    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
251
0
252
0
    AppendAmpersandIfNonempty(queryString);
253
0
    queryString.AppendLiteral(QUERYKEY_URI "=");
254
0
    queryString.Append(escaped);
255
0
  }
256
0
257
0
  // annotation
258
0
  if (!query->Annotation().IsEmpty()) {
259
0
    AppendAmpersandIfNonempty(queryString);
260
0
    if (query->AnnotationIsNot()) {
261
0
      queryString.AppendLiteral(QUERYKEY_NOTANNOTATION "=");
262
0
    } else {
263
0
      queryString.AppendLiteral(QUERYKEY_ANNOTATION "=");
264
0
    }
265
0
    const nsCString& annot = query->Annotation();
266
0
    nsAutoCString escaped;
267
0
    bool success = NS_Escape(annot, escaped, url_XAlphas);
268
0
    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
269
0
    queryString.Append(escaped);
270
0
  }
271
0
272
0
  // parents
273
0
  const nsTArray<nsCString>& parents = query->Parents();
274
0
  for (uint32_t i = 0; i < parents.Length(); ++i) {
275
0
    AppendAmpersandIfNonempty(queryString);
276
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_PARENT "=");
277
0
    queryString += parents[i];
278
0
  }
279
0
280
0
  // tags
281
0
  const nsTArray<nsString>& tags = query->Tags();
282
0
  for (uint32_t i = 0; i < tags.Length(); ++i) {
283
0
    nsAutoCString escapedTag;
284
0
    if (!NS_Escape(NS_ConvertUTF16toUTF8(tags[i]), escapedTag, url_XAlphas))
285
0
      return NS_ERROR_OUT_OF_MEMORY;
286
0
287
0
    AppendAmpersandIfNonempty(queryString);
288
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_TAG "=");
289
0
    queryString += escapedTag;
290
0
  }
291
0
  AppendBoolKeyValueIfTrue(queryString,
292
0
                           NS_LITERAL_CSTRING(QUERYKEY_NOTTAGS),
293
0
                           query,
294
0
                           &nsINavHistoryQuery::GetTagsAreNot);
295
0
296
0
  // transitions
297
0
  const nsTArray<uint32_t>& transitions = query->Transitions();
298
0
  for (uint32_t i = 0; i < transitions.Length(); ++i) {
299
0
    AppendAmpersandIfNonempty(queryString);
300
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_TRANSITION "=");
301
0
    AppendInt64(queryString, transitions[i]);
302
0
  }
303
0
304
0
  // sorting
305
0
  if (options->SortingMode() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
306
0
    AppendAmpersandIfNonempty(queryString);
307
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_SORT "=");
308
0
    AppendInt16(queryString, options->SortingMode());
309
0
  }
310
0
311
0
  // result type
312
0
  if (options->ResultType() != nsINavHistoryQueryOptions::RESULTS_AS_URI) {
313
0
    AppendAmpersandIfNonempty(queryString);
314
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_RESULT_TYPE "=");
315
0
    AppendInt16(queryString, options->ResultType());
316
0
  }
317
0
318
0
  // exclude items
319
0
  if (options->ExcludeItems()) {
320
0
    AppendAmpersandIfNonempty(queryString);
321
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_ITEMS "=1");
322
0
  }
323
0
324
0
  // exclude queries
325
0
  if (options->ExcludeQueries()) {
326
0
    AppendAmpersandIfNonempty(queryString);
327
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_QUERIES "=1");
328
0
  }
329
0
330
0
  // exclude read only folders
331
0
  if (options->ExcludeReadOnlyFolders()) {
332
0
    AppendAmpersandIfNonempty(queryString);
333
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS "=1");
334
0
  }
335
0
336
0
  // expand queries
337
0
  if (!options->ExpandQueries()) {
338
0
    AppendAmpersandIfNonempty(queryString);
339
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_EXPAND_QUERIES "=0");
340
0
  }
341
0
342
0
  // include hidden
343
0
  if (options->IncludeHidden()) {
344
0
    AppendAmpersandIfNonempty(queryString);
345
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_INCLUDE_HIDDEN "=1");
346
0
  }
347
0
348
0
  // max results
349
0
  if (options->MaxResults()) {
350
0
    AppendAmpersandIfNonempty(queryString);
351
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_MAX_RESULTS "=");
352
0
    AppendInt32(queryString, options->MaxResults());
353
0
  }
354
0
355
0
  // queryType
356
0
  if (options->QueryType() !=  nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY) {
357
0
    AppendAmpersandIfNonempty(queryString);
358
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_QUERY_TYPE "=");
359
0
    AppendInt16(queryString, options->QueryType());
360
0
  }
361
0
362
0
  // async enabled
363
0
  if (options->AsyncEnabled()) {
364
0
    AppendAmpersandIfNonempty(queryString);
365
0
    queryString += NS_LITERAL_CSTRING(QUERYKEY_ASYNC_ENABLED "=1");
366
0
  }
367
0
368
0
  aQueryString.AssignLiteral("place:");
369
0
  aQueryString.Append(queryString);
370
0
  return NS_OK;
371
0
}
372
373
374
nsresult
375
nsNavHistory::TokensToQuery(const nsTArray<QueryKeyValuePair>& aTokens,
376
                            nsNavHistoryQuery* aQuery,
377
                            nsNavHistoryQueryOptions* aOptions)
378
0
{
379
0
  nsresult rv;
380
0
381
0
  if (aTokens.Length() == 0)
382
0
    return NS_OK;
383
0
384
0
  nsTArray<nsCString> parents;
385
0
  nsTArray<nsString> tags;
386
0
  nsTArray<uint32_t> transitions;
387
0
  for (uint32_t i = 0; i < aTokens.Length(); i ++) {
388
0
    const QueryKeyValuePair& kvp = aTokens[i];
389
0
390
0
    // begin time
391
0
    if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME)) {
392
0
      SetQueryKeyInt64(kvp.value, aQuery, &nsINavHistoryQuery::SetBeginTime);
393
0
394
0
    // begin time reference
395
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME_REFERENCE)) {
396
0
      SetQueryKeyUint32(kvp.value, aQuery, &nsINavHistoryQuery::SetBeginTimeReference);
397
0
398
0
    // end time
399
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME)) {
400
0
      SetQueryKeyInt64(kvp.value, aQuery, &nsINavHistoryQuery::SetEndTime);
401
0
402
0
    // end time reference
403
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME_REFERENCE)) {
404
0
      SetQueryKeyUint32(kvp.value, aQuery, &nsINavHistoryQuery::SetEndTimeReference);
405
0
406
0
    // search terms
407
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_SEARCH_TERMS)) {
408
0
      nsCString unescapedTerms = kvp.value;
409
0
      NS_UnescapeURL(unescapedTerms); // modifies input
410
0
      rv = aQuery->SetSearchTerms(NS_ConvertUTF8toUTF16(unescapedTerms));
411
0
      NS_ENSURE_SUCCESS(rv, rv);
412
0
413
0
    // min visits
414
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_MIN_VISITS)) {
415
0
      int32_t visits = kvp.value.ToInteger(&rv);
416
0
      if (NS_SUCCEEDED(rv))
417
0
        aQuery->SetMinVisits(visits);
418
0
      else
419
0
        NS_WARNING("Bad number for minVisits in query");
420
0
421
0
    // max visits
422
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_VISITS)) {
423
0
      int32_t visits = kvp.value.ToInteger(&rv);
424
0
      if (NS_SUCCEEDED(rv))
425
0
        aQuery->SetMaxVisits(visits);
426
0
      else
427
0
        NS_WARNING("Bad number for maxVisits in query");
428
0
429
0
    // onlyBookmarked flag
430
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_ONLY_BOOKMARKED)) {
431
0
      SetQueryKeyBool(kvp.value, aQuery, &nsINavHistoryQuery::SetOnlyBookmarked);
432
0
433
0
    // domainIsHost flag
434
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN_IS_HOST)) {
435
0
      SetQueryKeyBool(kvp.value, aQuery, &nsINavHistoryQuery::SetDomainIsHost);
436
0
437
0
    // domain string
438
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN)) {
439
0
      nsAutoCString unescapedDomain(kvp.value);
440
0
      NS_UnescapeURL(unescapedDomain); // modifies input
441
0
      rv = aQuery->SetDomain(unescapedDomain);
442
0
      NS_ENSURE_SUCCESS(rv, rv);
443
0
444
0
    // parent folders (guids)
445
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_PARENT)) {
446
0
      NS_ENSURE_TRUE(parents.AppendElement(kvp.value), NS_ERROR_OUT_OF_MEMORY);
447
0
448
0
     // uri
449
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_URI)) {
450
0
      nsAutoCString unescapedUri(kvp.value);
451
0
      NS_UnescapeURL(unescapedUri); // modifies input
452
0
      nsCOMPtr<nsIURI> uri;
453
0
      nsresult rv = NS_NewURI(getter_AddRefs(uri), unescapedUri);
454
0
      if (NS_FAILED(rv)) {
455
0
        NS_WARNING("Unable to parse URI");
456
0
      }
457
0
      rv = aQuery->SetUri(uri);
458
0
      NS_ENSURE_SUCCESS(rv, rv);
459
0
460
0
    // not annotation
461
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_NOTANNOTATION)) {
462
0
      nsAutoCString unescaped(kvp.value);
463
0
      NS_UnescapeURL(unescaped); // modifies input
464
0
      aQuery->SetAnnotationIsNot(true);
465
0
      aQuery->SetAnnotation(unescaped);
466
0
467
0
    // annotation
468
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_ANNOTATION)) {
469
0
      nsAutoCString unescaped(kvp.value);
470
0
      NS_UnescapeURL(unescaped); // modifies input
471
0
      aQuery->SetAnnotationIsNot(false);
472
0
      aQuery->SetAnnotation(unescaped);
473
0
474
0
    // tag
475
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_TAG)) {
476
0
      nsAutoCString unescaped(kvp.value);
477
0
      NS_UnescapeURL(unescaped); // modifies input
478
0
      NS_ConvertUTF8toUTF16 tag(unescaped);
479
0
      if (!tags.Contains(tag)) {
480
0
        NS_ENSURE_TRUE(tags.AppendElement(tag), NS_ERROR_OUT_OF_MEMORY);
481
0
      }
482
0
483
0
    // not tags
484
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_NOTTAGS)) {
485
0
      SetQueryKeyBool(kvp.value, aQuery, &nsINavHistoryQuery::SetTagsAreNot);
486
0
487
0
    // transition
488
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_TRANSITION)) {
489
0
      uint32_t transition = kvp.value.ToInteger(&rv);
490
0
      if (NS_SUCCEEDED(rv)) {
491
0
        if (!transitions.Contains(transition))
492
0
          NS_ENSURE_TRUE(transitions.AppendElement(transition),
493
0
                         NS_ERROR_OUT_OF_MEMORY);
494
0
      }
495
0
      else {
496
0
        NS_WARNING("Invalid Int32 transition value.");
497
0
      }
498
0
499
0
    // sorting mode
500
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_SORT)) {
501
0
      SetOptionsKeyUint16(kvp.value, aOptions,
502
0
                          &nsINavHistoryQueryOptions::SetSortingMode);
503
0
    // result type
504
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_RESULT_TYPE)) {
505
0
      SetOptionsKeyUint16(kvp.value, aOptions,
506
0
                          &nsINavHistoryQueryOptions::SetResultType);
507
0
508
0
    // exclude items
509
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_ITEMS)) {
510
0
      SetOptionsKeyBool(kvp.value, aOptions,
511
0
                        &nsINavHistoryQueryOptions::SetExcludeItems);
512
0
513
0
    // exclude queries
514
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_QUERIES)) {
515
0
      SetOptionsKeyBool(kvp.value, aOptions,
516
0
                        &nsINavHistoryQueryOptions::SetExcludeQueries);
517
0
518
0
    // exclude read only folders
519
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS)) {
520
0
      SetOptionsKeyBool(kvp.value, aOptions,
521
0
                        &nsINavHistoryQueryOptions::SetExcludeReadOnlyFolders);
522
0
523
0
    // expand queries
524
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXPAND_QUERIES)) {
525
0
      SetOptionsKeyBool(kvp.value, aOptions,
526
0
                        &nsINavHistoryQueryOptions::SetExpandQueries);
527
0
    // include hidden
528
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_INCLUDE_HIDDEN)) {
529
0
      SetOptionsKeyBool(kvp.value, aOptions,
530
0
                        &nsINavHistoryQueryOptions::SetIncludeHidden);
531
0
    // max results
532
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_RESULTS)) {
533
0
      SetOptionsKeyUint32(kvp.value, aOptions,
534
0
                          &nsINavHistoryQueryOptions::SetMaxResults);
535
0
    // query type
536
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_QUERY_TYPE)) {
537
0
      SetOptionsKeyUint16(kvp.value, aOptions,
538
0
                          &nsINavHistoryQueryOptions::SetQueryType);
539
0
    // async enabled
540
0
    } else if (kvp.key.EqualsLiteral(QUERYKEY_ASYNC_ENABLED)) {
541
0
      SetOptionsKeyBool(kvp.value, aOptions,
542
0
                        &nsINavHistoryQueryOptions::SetAsyncEnabled);
543
0
    // unknown key
544
0
    } else {
545
0
      NS_WARNING("TokensToQueries(), ignoring unknown key: ");
546
0
      NS_WARNING(kvp.key.get());
547
0
    }
548
0
  }
549
0
550
0
  if (parents.Length() != 0) {
551
0
    rv = aQuery->SetParents(parents);
552
0
    NS_ENSURE_SUCCESS(rv, rv);
553
0
  }
554
0
555
0
  if (tags.Length() > 0) {
556
0
    rv = aQuery->SetTags(tags);
557
0
    NS_ENSURE_SUCCESS(rv, rv);
558
0
  }
559
0
560
0
  if (transitions.Length() > 0) {
561
0
    rv = aQuery->SetTransitions(transitions);
562
0
    NS_ENSURE_SUCCESS(rv, rv);
563
0
  }
564
0
565
0
  return NS_OK;
566
0
}
567
568
569
// ParseQueryBooleanString
570
//
571
//    Converts a 0/1 or true/false string into a bool
572
573
nsresult
574
ParseQueryBooleanString(const nsCString& aString, bool* aValue)
575
0
{
576
0
  if (aString.EqualsLiteral("1") || aString.EqualsLiteral("true")) {
577
0
    *aValue = true;
578
0
    return NS_OK;
579
0
  } else if (aString.EqualsLiteral("0") || aString.EqualsLiteral("false")) {
580
0
    *aValue = false;
581
0
    return NS_OK;
582
0
  }
583
0
  return NS_ERROR_INVALID_ARG;
584
0
}
585
586
587
// nsINavHistoryQuery **********************************************************
588
589
NS_IMPL_ISUPPORTS(nsNavHistoryQuery, nsNavHistoryQuery, nsINavHistoryQuery)
590
591
// nsINavHistoryQuery::nsNavHistoryQuery
592
//
593
//    This must initialize the object such that the default values will cause
594
//    all history to be returned if this query is used. Then the caller can
595
//    just set the things it's interested in.
596
597
nsNavHistoryQuery::nsNavHistoryQuery()
598
  : mMinVisits(-1), mMaxVisits(-1), mBeginTime(0),
599
    mBeginTimeReference(TIME_RELATIVE_EPOCH),
600
    mEndTime(0), mEndTimeReference(TIME_RELATIVE_EPOCH),
601
    mOnlyBookmarked(false),
602
    mDomainIsHost(false),
603
    mAnnotationIsNot(false),
604
    mTagsAreNot(false)
605
0
{
606
0
  // differentiate not set (IsVoid) from empty string (local files)
607
0
  mDomain.SetIsVoid(true);
608
0
}
609
610
nsNavHistoryQuery::nsNavHistoryQuery(const nsNavHistoryQuery& aOther)
611
  : mMinVisits(aOther.mMinVisits), mMaxVisits(aOther.mMaxVisits),
612
    mBeginTime(aOther.mBeginTime), mBeginTimeReference(aOther.mBeginTimeReference),
613
    mEndTime(aOther.mEndTime), mEndTimeReference(aOther.mEndTimeReference),
614
    mSearchTerms(aOther.mSearchTerms), mOnlyBookmarked(aOther.mOnlyBookmarked),
615
    mDomainIsHost(aOther.mDomainIsHost), mDomain(aOther.mDomain),
616
    mUri(aOther.mUri), mAnnotationIsNot(aOther.mAnnotationIsNot),
617
    mAnnotation(aOther.mAnnotation),
618
    mParents(aOther.mParents),
619
    mTags(aOther.mTags), mTagsAreNot(aOther.mTagsAreNot),
620
    mTransitions(aOther.mTransitions)
621
0
{
622
0
}
623
624
NS_IMETHODIMP nsNavHistoryQuery::GetBeginTime(PRTime *aBeginTime)
625
0
{
626
0
  *aBeginTime = mBeginTime;
627
0
  return NS_OK;
628
0
}
629
NS_IMETHODIMP nsNavHistoryQuery::SetBeginTime(PRTime aBeginTime)
630
0
{
631
0
  mBeginTime = aBeginTime;
632
0
  return NS_OK;
633
0
}
634
635
NS_IMETHODIMP nsNavHistoryQuery::GetBeginTimeReference(uint32_t* _retval)
636
0
{
637
0
  *_retval = mBeginTimeReference;
638
0
  return NS_OK;
639
0
}
640
NS_IMETHODIMP nsNavHistoryQuery::SetBeginTimeReference(uint32_t aReference)
641
0
{
642
0
  if (aReference > TIME_RELATIVE_NOW)
643
0
    return NS_ERROR_INVALID_ARG;
644
0
  mBeginTimeReference = aReference;
645
0
  return NS_OK;
646
0
}
647
648
NS_IMETHODIMP nsNavHistoryQuery::GetHasBeginTime(bool* _retval)
649
0
{
650
0
  *_retval = ! (mBeginTimeReference == TIME_RELATIVE_EPOCH && mBeginTime == 0);
651
0
  return NS_OK;
652
0
}
653
654
NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteBeginTime(PRTime* _retval)
655
0
{
656
0
  *_retval = nsNavHistory::NormalizeTime(mBeginTimeReference, mBeginTime);
657
0
  return NS_OK;
658
0
}
659
660
NS_IMETHODIMP nsNavHistoryQuery::GetEndTime(PRTime *aEndTime)
661
0
{
662
0
  *aEndTime = mEndTime;
663
0
  return NS_OK;
664
0
}
665
NS_IMETHODIMP nsNavHistoryQuery::SetEndTime(PRTime aEndTime)
666
0
{
667
0
  mEndTime = aEndTime;
668
0
  return NS_OK;
669
0
}
670
671
NS_IMETHODIMP nsNavHistoryQuery::GetEndTimeReference(uint32_t* _retval)
672
0
{
673
0
  *_retval = mEndTimeReference;
674
0
  return NS_OK;
675
0
}
676
NS_IMETHODIMP nsNavHistoryQuery::SetEndTimeReference(uint32_t aReference)
677
0
{
678
0
  if (aReference > TIME_RELATIVE_NOW)
679
0
    return NS_ERROR_INVALID_ARG;
680
0
  mEndTimeReference = aReference;
681
0
  return NS_OK;
682
0
}
683
684
NS_IMETHODIMP nsNavHistoryQuery::GetHasEndTime(bool* _retval)
685
0
{
686
0
  *_retval = ! (mEndTimeReference == TIME_RELATIVE_EPOCH && mEndTime == 0);
687
0
  return NS_OK;
688
0
}
689
690
NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteEndTime(PRTime* _retval)
691
0
{
692
0
  *_retval = nsNavHistory::NormalizeTime(mEndTimeReference, mEndTime);
693
0
  return NS_OK;
694
0
}
695
696
NS_IMETHODIMP nsNavHistoryQuery::GetSearchTerms(nsAString& aSearchTerms)
697
0
{
698
0
  aSearchTerms = mSearchTerms;
699
0
  return NS_OK;
700
0
}
701
NS_IMETHODIMP nsNavHistoryQuery::SetSearchTerms(const nsAString& aSearchTerms)
702
0
{
703
0
  mSearchTerms = aSearchTerms;
704
0
  return NS_OK;
705
0
}
706
NS_IMETHODIMP nsNavHistoryQuery::GetHasSearchTerms(bool* _retval)
707
0
{
708
0
  *_retval = (! mSearchTerms.IsEmpty());
709
0
  return NS_OK;
710
0
}
711
712
NS_IMETHODIMP nsNavHistoryQuery::GetMinVisits(int32_t* _retval)
713
0
{
714
0
  NS_ENSURE_ARG_POINTER(_retval);
715
0
  *_retval = mMinVisits;
716
0
  return NS_OK;
717
0
}
718
NS_IMETHODIMP nsNavHistoryQuery::SetMinVisits(int32_t aVisits)
719
0
{
720
0
  mMinVisits = aVisits;
721
0
  return NS_OK;
722
0
}
723
724
NS_IMETHODIMP nsNavHistoryQuery::GetMaxVisits(int32_t* _retval)
725
0
{
726
0
  NS_ENSURE_ARG_POINTER(_retval);
727
0
  *_retval = mMaxVisits;
728
0
  return NS_OK;
729
0
}
730
NS_IMETHODIMP nsNavHistoryQuery::SetMaxVisits(int32_t aVisits)
731
0
{
732
0
  mMaxVisits = aVisits;
733
0
  return NS_OK;
734
0
}
735
736
NS_IMETHODIMP nsNavHistoryQuery::GetOnlyBookmarked(bool *aOnlyBookmarked)
737
0
{
738
0
  *aOnlyBookmarked = mOnlyBookmarked;
739
0
  return NS_OK;
740
0
}
741
NS_IMETHODIMP nsNavHistoryQuery::SetOnlyBookmarked(bool aOnlyBookmarked)
742
0
{
743
0
  mOnlyBookmarked = aOnlyBookmarked;
744
0
  return NS_OK;
745
0
}
746
747
NS_IMETHODIMP nsNavHistoryQuery::GetDomainIsHost(bool *aDomainIsHost)
748
0
{
749
0
  *aDomainIsHost = mDomainIsHost;
750
0
  return NS_OK;
751
0
}
752
NS_IMETHODIMP nsNavHistoryQuery::SetDomainIsHost(bool aDomainIsHost)
753
0
{
754
0
  mDomainIsHost = aDomainIsHost;
755
0
  return NS_OK;
756
0
}
757
758
NS_IMETHODIMP nsNavHistoryQuery::GetDomain(nsACString& aDomain)
759
0
{
760
0
  aDomain = mDomain;
761
0
  return NS_OK;
762
0
}
763
NS_IMETHODIMP nsNavHistoryQuery::SetDomain(const nsACString& aDomain)
764
0
{
765
0
  mDomain = aDomain;
766
0
  return NS_OK;
767
0
}
768
NS_IMETHODIMP nsNavHistoryQuery::GetHasDomain(bool* _retval)
769
0
{
770
0
  // note that empty but not void is still a valid query (local files)
771
0
  *_retval = (! mDomain.IsVoid());
772
0
  return NS_OK;
773
0
}
774
775
NS_IMETHODIMP nsNavHistoryQuery::GetUri(nsIURI** aUri)
776
0
{
777
0
  NS_IF_ADDREF(*aUri = mUri);
778
0
  return NS_OK;
779
0
}
780
NS_IMETHODIMP nsNavHistoryQuery::SetUri(nsIURI* aUri)
781
0
{
782
0
  mUri = aUri;
783
0
  return NS_OK;
784
0
}
785
NS_IMETHODIMP nsNavHistoryQuery::GetHasUri(bool* aHasUri)
786
0
{
787
0
  *aHasUri = (mUri != nullptr);
788
0
  return NS_OK;
789
0
}
790
791
NS_IMETHODIMP nsNavHistoryQuery::GetAnnotationIsNot(bool* aIsNot)
792
0
{
793
0
  *aIsNot = mAnnotationIsNot;
794
0
  return NS_OK;
795
0
}
796
NS_IMETHODIMP nsNavHistoryQuery::SetAnnotationIsNot(bool aIsNot)
797
0
{
798
0
  mAnnotationIsNot = aIsNot;
799
0
  return NS_OK;
800
0
}
801
802
NS_IMETHODIMP nsNavHistoryQuery::GetAnnotation(nsACString& aAnnotation)
803
0
{
804
0
  aAnnotation = mAnnotation;
805
0
  return NS_OK;
806
0
}
807
NS_IMETHODIMP nsNavHistoryQuery::SetAnnotation(const nsACString& aAnnotation)
808
0
{
809
0
  mAnnotation = aAnnotation;
810
0
  return NS_OK;
811
0
}
812
NS_IMETHODIMP nsNavHistoryQuery::GetHasAnnotation(bool* aHasIt)
813
0
{
814
0
  *aHasIt = ! mAnnotation.IsEmpty();
815
0
  return NS_OK;
816
0
}
817
818
NS_IMETHODIMP nsNavHistoryQuery::GetTags(nsIVariant **aTags)
819
0
{
820
0
  NS_ENSURE_ARG_POINTER(aTags);
821
0
822
0
  RefPtr<nsVariant> out = new nsVariant();
823
0
824
0
  uint32_t arrayLen = mTags.Length();
825
0
826
0
  nsresult rv;
827
0
  if (arrayLen == 0)
828
0
    rv = out->SetAsEmptyArray();
829
0
  else {
830
0
    // Note: The resulting nsIVariant dupes both the array and its elements.
831
0
    const char16_t **array = reinterpret_cast<const char16_t **>
832
0
                              (moz_xmalloc(arrayLen * sizeof(char16_t *)));
833
0
    for (uint32_t i = 0; i < arrayLen; ++i) {
834
0
      array[i] = mTags[i].get();
835
0
    }
836
0
837
0
    rv = out->SetAsArray(nsIDataType::VTYPE_WCHAR_STR,
838
0
                         nullptr,
839
0
                         arrayLen,
840
0
                         reinterpret_cast<void *>(array));
841
0
    free(array);
842
0
  }
843
0
  NS_ENSURE_SUCCESS(rv, rv);
844
0
845
0
  out.forget(aTags);
846
0
  return NS_OK;
847
0
}
848
849
NS_IMETHODIMP nsNavHistoryQuery::SetTags(nsIVariant *aTags)
850
0
{
851
0
  NS_ENSURE_ARG(aTags);
852
0
853
0
  uint16_t dataType;
854
0
  aTags->GetDataType(&dataType);
855
0
856
0
  // Caller passed in empty array.  Easy -- clear our mTags array and return.
857
0
  if (dataType == nsIDataType::VTYPE_EMPTY_ARRAY) {
858
0
    mTags.Clear();
859
0
    return NS_OK;
860
0
  }
861
0
862
0
  // Before we go any further, make sure caller passed in an array.
863
0
  NS_ENSURE_TRUE(dataType == nsIDataType::VTYPE_ARRAY, NS_ERROR_ILLEGAL_VALUE);
864
0
865
0
  uint16_t eltType;
866
0
  nsIID eltIID;
867
0
  uint32_t arrayLen;
868
0
  void *array;
869
0
870
0
  // Convert the nsIVariant to an array.  We own the resulting buffer and its
871
0
  // elements.
872
0
  nsresult rv = aTags->GetAsArray(&eltType, &eltIID, &arrayLen, &array);
873
0
  NS_ENSURE_SUCCESS(rv, rv);
874
0
875
0
  // If element type is not wstring, thanks a lot.  Your memory die now.
876
0
  if (eltType != nsIDataType::VTYPE_WCHAR_STR) {
877
0
    switch (eltType) {
878
0
    case nsIDataType::VTYPE_ID:
879
0
    case nsIDataType::VTYPE_CHAR_STR:
880
0
      {
881
0
        char **charArray = reinterpret_cast<char **>(array);
882
0
        for (uint32_t i = 0; i < arrayLen; ++i) {
883
0
          if (charArray[i])
884
0
            free(charArray[i]);
885
0
        }
886
0
      }
887
0
      break;
888
0
    case nsIDataType::VTYPE_INTERFACE:
889
0
    case nsIDataType::VTYPE_INTERFACE_IS:
890
0
      {
891
0
        nsISupports **supportsArray = reinterpret_cast<nsISupports **>(array);
892
0
        for (uint32_t i = 0; i < arrayLen; ++i) {
893
0
          NS_IF_RELEASE(supportsArray[i]);
894
0
        }
895
0
      }
896
0
      break;
897
0
    // The other types are primitives that do not need to be freed.
898
0
    }
899
0
    free(array);
900
0
    return NS_ERROR_ILLEGAL_VALUE;
901
0
  }
902
0
903
0
  char16_t **tags = reinterpret_cast<char16_t **>(array);
904
0
  mTags.Clear();
905
0
906
0
  // Finally, add each passed-in tag to our mTags array and then sort it.
907
0
  for (uint32_t i = 0; i < arrayLen; ++i) {
908
0
909
0
    // Don't allow nulls.
910
0
    if (!tags[i]) {
911
0
      free(tags);
912
0
      return NS_ERROR_ILLEGAL_VALUE;
913
0
    }
914
0
915
0
    nsDependentString tag(tags[i]);
916
0
917
0
    // Don't store duplicate tags.  This isn't just to save memory or to be
918
0
    // fancy; the SQL that's built from the tags relies on no dupes.
919
0
    if (!mTags.Contains(tag)) {
920
0
      if (!mTags.AppendElement(tag)) {
921
0
        free(tags[i]);
922
0
        free(tags);
923
0
        return NS_ERROR_OUT_OF_MEMORY;
924
0
      }
925
0
    }
926
0
    free(tags[i]);
927
0
  }
928
0
  free(tags);
929
0
930
0
  mTags.Sort();
931
0
932
0
  return NS_OK;
933
0
}
934
935
NS_IMETHODIMP nsNavHistoryQuery::GetTagsAreNot(bool *aTagsAreNot)
936
0
{
937
0
  NS_ENSURE_ARG_POINTER(aTagsAreNot);
938
0
  *aTagsAreNot = mTagsAreNot;
939
0
  return NS_OK;
940
0
}
941
942
NS_IMETHODIMP nsNavHistoryQuery::SetTagsAreNot(bool aTagsAreNot)
943
0
{
944
0
  mTagsAreNot = aTagsAreNot;
945
0
  return NS_OK;
946
0
}
947
948
NS_IMETHODIMP nsNavHistoryQuery::GetParents(uint32_t *aGuidCount,
949
                                            char ***aGuids)
950
0
{
951
0
  uint32_t count = mParents.Length();
952
0
  char **guids = nullptr;
953
0
  if (count > 0) {
954
0
    guids = static_cast<char**>(moz_xmalloc(count * sizeof(char*)));
955
0
956
0
    for (uint32_t i = 0; i < count; ++i) {
957
0
      guids[i] = ToNewCString(mParents[i]);
958
0
    }
959
0
  }
960
0
  *aGuidCount = count;
961
0
  *aGuids = guids;
962
0
  return NS_OK;
963
0
}
964
965
NS_IMETHODIMP nsNavHistoryQuery::GetParentCount(uint32_t *aGuidCount)
966
0
{
967
0
  *aGuidCount = mParents.Length();
968
0
  return NS_OK;
969
0
}
970
971
NS_IMETHODIMP nsNavHistoryQuery::SetParents(const char** aGuids,
972
                                            uint32_t aGuidCount)
973
0
{
974
0
  mParents.Clear();
975
0
  for (size_t i = 0; i < aGuidCount; i++) {
976
0
    if (!mParents.AppendElement(aGuids[i])) {
977
0
      return NS_ERROR_OUT_OF_MEMORY;
978
0
    }
979
0
  }
980
0
981
0
  return NS_OK;
982
0
}
983
984
NS_IMETHODIMP nsNavHistoryQuery::GetTransitions(uint32_t* aCount,
985
                                                uint32_t** aTransitions)
986
0
{
987
0
  uint32_t count = mTransitions.Length();
988
0
  uint32_t* transitions = nullptr;
989
0
  if (count > 0) {
990
0
    transitions = reinterpret_cast<uint32_t*>
991
0
                  (moz_xmalloc(count * sizeof(uint32_t)));
992
0
    for (uint32_t i = 0; i < count; ++i) {
993
0
      transitions[i] = mTransitions[i];
994
0
    }
995
0
  }
996
0
  *aCount = count;
997
0
  *aTransitions = transitions;
998
0
  return NS_OK;
999
0
}
1000
1001
NS_IMETHODIMP nsNavHistoryQuery::GetTransitionCount(uint32_t* aCount)
1002
0
{
1003
0
  *aCount = mTransitions.Length();
1004
0
  return NS_OK;
1005
0
}
1006
1007
NS_IMETHODIMP nsNavHistoryQuery::SetTransitions(const uint32_t* aTransitions,
1008
                                                uint32_t aCount)
1009
0
{
1010
0
  if (!mTransitions.ReplaceElementsAt(0, mTransitions.Length(), aTransitions,
1011
0
                                      aCount))
1012
0
    return NS_ERROR_OUT_OF_MEMORY;
1013
0
1014
0
  return NS_OK;
1015
0
}
1016
1017
NS_IMETHODIMP
1018
nsNavHistoryQuery::Clone(nsINavHistoryQuery** _clone)
1019
0
{
1020
0
  nsNavHistoryQuery *clone = nullptr;
1021
0
  Unused << Clone(&clone);
1022
0
  *_clone = clone;
1023
0
  return NS_OK;
1024
0
}
1025
1026
nsresult
1027
nsNavHistoryQuery::Clone(nsNavHistoryQuery** _clone)
1028
0
{
1029
0
  *_clone = nullptr;
1030
0
  RefPtr<nsNavHistoryQuery> clone = new nsNavHistoryQuery(*this);
1031
0
  clone.forget(_clone);
1032
0
  return NS_OK;
1033
0
}
1034
1035
// nsNavHistoryQueryOptions
1036
NS_IMPL_ISUPPORTS(nsNavHistoryQueryOptions, nsNavHistoryQueryOptions, nsINavHistoryQueryOptions)
1037
1038
nsNavHistoryQueryOptions::nsNavHistoryQueryOptions()
1039
: mSort(0)
1040
, mResultType(0)
1041
, mExcludeItems(false)
1042
, mExcludeQueries(false)
1043
, mExcludeReadOnlyFolders(false)
1044
, mExpandQueries(true)
1045
, mIncludeHidden(false)
1046
, mMaxResults(0)
1047
, mQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY)
1048
, mAsyncEnabled(false)
1049
0
{
1050
0
}
1051
1052
nsNavHistoryQueryOptions::nsNavHistoryQueryOptions(const nsNavHistoryQueryOptions& other)
1053
: mSort(other.mSort)
1054
, mResultType(other.mResultType)
1055
, mExcludeItems(other.mExcludeItems)
1056
, mExcludeQueries(other.mExcludeQueries)
1057
, mExcludeReadOnlyFolders(other.mExcludeReadOnlyFolders)
1058
, mExpandQueries(other.mExpandQueries)
1059
, mIncludeHidden(other.mIncludeHidden)
1060
, mMaxResults(other.mMaxResults)
1061
, mQueryType(other.mQueryType)
1062
, mAsyncEnabled(other.mAsyncEnabled)
1063
0
{
1064
0
}
1065
1066
// sortingMode
1067
NS_IMETHODIMP
1068
nsNavHistoryQueryOptions::GetSortingMode(uint16_t* aMode)
1069
0
{
1070
0
  *aMode = mSort;
1071
0
  return NS_OK;
1072
0
}
1073
NS_IMETHODIMP
1074
nsNavHistoryQueryOptions::SetSortingMode(uint16_t aMode)
1075
0
{
1076
0
  if (aMode > SORT_BY_FRECENCY_DESCENDING)
1077
0
    return NS_ERROR_INVALID_ARG;
1078
0
  mSort = aMode;
1079
0
  return NS_OK;
1080
0
}
1081
1082
// resultType
1083
NS_IMETHODIMP
1084
nsNavHistoryQueryOptions::GetResultType(uint16_t* aType)
1085
0
{
1086
0
  *aType = mResultType;
1087
0
  return NS_OK;
1088
0
}
1089
NS_IMETHODIMP
1090
nsNavHistoryQueryOptions::SetResultType(uint16_t aType)
1091
0
{
1092
0
  if (aType > RESULTS_AS_LEFT_PANE_QUERY)
1093
0
    return NS_ERROR_INVALID_ARG;
1094
0
  // Tag queries, containers and the roots query are bookmarks related, so we
1095
0
  // set the QueryType accordingly.
1096
0
  if (aType == RESULTS_AS_TAGS_ROOT || aType == RESULTS_AS_ROOTS_QUERY ||
1097
0
      aType == RESULTS_AS_LEFT_PANE_QUERY) {
1098
0
    mQueryType = QUERY_TYPE_BOOKMARKS;
1099
0
  }
1100
0
  mResultType = aType;
1101
0
  return NS_OK;
1102
0
}
1103
1104
// excludeItems
1105
NS_IMETHODIMP
1106
nsNavHistoryQueryOptions::GetExcludeItems(bool* aExclude)
1107
0
{
1108
0
  *aExclude = mExcludeItems;
1109
0
  return NS_OK;
1110
0
}
1111
NS_IMETHODIMP
1112
nsNavHistoryQueryOptions::SetExcludeItems(bool aExclude)
1113
0
{
1114
0
  mExcludeItems = aExclude;
1115
0
  return NS_OK;
1116
0
}
1117
1118
// excludeQueries
1119
NS_IMETHODIMP
1120
nsNavHistoryQueryOptions::GetExcludeQueries(bool* aExclude)
1121
0
{
1122
0
  *aExclude = mExcludeQueries;
1123
0
  return NS_OK;
1124
0
}
1125
NS_IMETHODIMP
1126
nsNavHistoryQueryOptions::SetExcludeQueries(bool aExclude)
1127
0
{
1128
0
  mExcludeQueries = aExclude;
1129
0
  return NS_OK;
1130
0
}
1131
1132
// excludeReadOnlyFolders
1133
NS_IMETHODIMP
1134
nsNavHistoryQueryOptions::GetExcludeReadOnlyFolders(bool* aExclude)
1135
0
{
1136
0
  *aExclude = mExcludeReadOnlyFolders;
1137
0
  return NS_OK;
1138
0
}
1139
NS_IMETHODIMP
1140
nsNavHistoryQueryOptions::SetExcludeReadOnlyFolders(bool aExclude)
1141
0
{
1142
0
  mExcludeReadOnlyFolders = aExclude;
1143
0
  return NS_OK;
1144
0
}
1145
1146
// expandQueries
1147
NS_IMETHODIMP
1148
nsNavHistoryQueryOptions::GetExpandQueries(bool* aExpand)
1149
0
{
1150
0
  *aExpand = mExpandQueries;
1151
0
  return NS_OK;
1152
0
}
1153
NS_IMETHODIMP
1154
nsNavHistoryQueryOptions::SetExpandQueries(bool aExpand)
1155
0
{
1156
0
  mExpandQueries = aExpand;
1157
0
  return NS_OK;
1158
0
}
1159
1160
// includeHidden
1161
NS_IMETHODIMP
1162
nsNavHistoryQueryOptions::GetIncludeHidden(bool* aIncludeHidden)
1163
0
{
1164
0
  *aIncludeHidden = mIncludeHidden;
1165
0
  return NS_OK;
1166
0
}
1167
NS_IMETHODIMP
1168
nsNavHistoryQueryOptions::SetIncludeHidden(bool aIncludeHidden)
1169
0
{
1170
0
  mIncludeHidden = aIncludeHidden;
1171
0
  return NS_OK;
1172
0
}
1173
1174
// maxResults
1175
NS_IMETHODIMP
1176
nsNavHistoryQueryOptions::GetMaxResults(uint32_t* aMaxResults)
1177
0
{
1178
0
  *aMaxResults = mMaxResults;
1179
0
  return NS_OK;
1180
0
}
1181
NS_IMETHODIMP
1182
nsNavHistoryQueryOptions::SetMaxResults(uint32_t aMaxResults)
1183
0
{
1184
0
  mMaxResults = aMaxResults;
1185
0
  return NS_OK;
1186
0
}
1187
1188
// queryType
1189
NS_IMETHODIMP
1190
nsNavHistoryQueryOptions::GetQueryType(uint16_t* _retval)
1191
0
{
1192
0
  *_retval = mQueryType;
1193
0
  return NS_OK;
1194
0
}
1195
NS_IMETHODIMP
1196
nsNavHistoryQueryOptions::SetQueryType(uint16_t aQueryType)
1197
0
{
1198
0
  // Tag query and containers are forced to QUERY_TYPE_BOOKMARKS when the
1199
0
  // resultType is set.
1200
0
  if (mResultType == RESULTS_AS_TAGS_ROOT ||
1201
0
      mResultType == RESULTS_AS_LEFT_PANE_QUERY ||
1202
0
      mResultType == RESULTS_AS_ROOTS_QUERY)
1203
0
   return NS_OK;
1204
0
  mQueryType = aQueryType;
1205
0
  return NS_OK;
1206
0
}
1207
1208
// asyncEnabled
1209
NS_IMETHODIMP
1210
nsNavHistoryQueryOptions::GetAsyncEnabled(bool* _asyncEnabled)
1211
0
{
1212
0
  *_asyncEnabled = mAsyncEnabled;
1213
0
  return NS_OK;
1214
0
}
1215
NS_IMETHODIMP
1216
nsNavHistoryQueryOptions::SetAsyncEnabled(bool aAsyncEnabled)
1217
0
{
1218
0
  mAsyncEnabled = aAsyncEnabled;
1219
0
  return NS_OK;
1220
0
}
1221
1222
NS_IMETHODIMP
1223
nsNavHistoryQueryOptions::Clone(nsINavHistoryQueryOptions** _clone)
1224
0
{
1225
0
  nsNavHistoryQueryOptions *clone = nullptr;
1226
0
  Unused << Clone(&clone);
1227
0
  *_clone = clone;
1228
0
  return NS_OK;
1229
0
}
1230
1231
nsresult
1232
nsNavHistoryQueryOptions::Clone(nsNavHistoryQueryOptions** _clone)
1233
0
{
1234
0
  *_clone = nullptr;
1235
0
  RefPtr<nsNavHistoryQueryOptions> clone = new nsNavHistoryQueryOptions(*this);
1236
0
  clone.forget(_clone);
1237
0
  return NS_OK;
1238
0
}
1239
1240
// AppendBoolKeyValueIfTrue
1241
1242
void // static
1243
AppendBoolKeyValueIfTrue(nsACString& aString, const nsCString& aName,
1244
                         nsINavHistoryQuery* aQuery,
1245
                         BoolQueryGetter getter)
1246
0
{
1247
0
  bool value;
1248
0
  DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
1249
0
  NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting boolean value");
1250
0
  if (value) {
1251
0
    AppendAmpersandIfNonempty(aString);
1252
0
    aString += aName;
1253
0
    aString.AppendLiteral("=1");
1254
0
  }
1255
0
}
1256
1257
1258
// AppendUint32KeyValueIfNonzero
1259
1260
void // static
1261
AppendUint32KeyValueIfNonzero(nsACString& aString,
1262
                              const nsCString& aName,
1263
                              nsINavHistoryQuery* aQuery,
1264
                              Uint32QueryGetter getter)
1265
0
{
1266
0
  uint32_t value;
1267
0
  DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
1268
0
  NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting value");
1269
0
  if (value) {
1270
0
    AppendAmpersandIfNonempty(aString);
1271
0
    aString += aName;
1272
0
1273
0
    // AppendInt requires a concrete string
1274
0
    nsAutoCString appendMe("=");
1275
0
    appendMe.AppendInt(value);
1276
0
    aString.Append(appendMe);
1277
0
  }
1278
0
}
1279
1280
1281
// AppendInt64KeyValueIfNonzero
1282
1283
void // static
1284
AppendInt64KeyValueIfNonzero(nsACString& aString,
1285
                             const nsCString& aName,
1286
                             nsINavHistoryQuery* aQuery,
1287
                             Int64QueryGetter getter)
1288
0
{
1289
0
  PRTime value;
1290
0
  DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
1291
0
  NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting value");
1292
0
  if (value) {
1293
0
    AppendAmpersandIfNonempty(aString);
1294
0
    aString += aName;
1295
0
    nsAutoCString appendMe("=");
1296
0
    appendMe.AppendInt(static_cast<int64_t>(value));
1297
0
    aString.Append(appendMe);
1298
0
  }
1299
0
}
1300
1301
1302
// SetQuery/OptionsKeyBool
1303
1304
void // static
1305
SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
1306
                BoolQuerySetter setter)
1307
0
{
1308
0
  bool value;
1309
0
  nsresult rv = ParseQueryBooleanString(aValue, &value);
1310
0
  if (NS_SUCCEEDED(rv)) {
1311
0
    rv = (aQuery->*setter)(value);
1312
0
    if (NS_FAILED(rv)) {
1313
0
      NS_WARNING("Error setting boolean key value");
1314
0
    }
1315
0
  } else {
1316
0
    NS_WARNING("Invalid boolean key value in query string.");
1317
0
  }
1318
0
}
1319
void // static
1320
SetOptionsKeyBool(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
1321
                 BoolOptionsSetter setter)
1322
0
{
1323
0
  bool value = false;
1324
0
  nsresult rv = ParseQueryBooleanString(aValue, &value);
1325
0
  if (NS_SUCCEEDED(rv)) {
1326
0
    rv = (aOptions->*setter)(value);
1327
0
    if (NS_FAILED(rv)) {
1328
0
      NS_WARNING("Error setting boolean key value");
1329
0
    }
1330
0
  } else {
1331
0
    NS_WARNING("Invalid boolean key value in query string.");
1332
0
  }
1333
0
}
1334
1335
1336
// SetQuery/OptionsKeyUint32
1337
1338
void // static
1339
SetQueryKeyUint32(const nsCString& aValue, nsINavHistoryQuery* aQuery,
1340
                  Uint32QuerySetter setter)
1341
0
{
1342
0
  nsresult rv;
1343
0
  uint32_t value = aValue.ToInteger(&rv);
1344
0
  if (NS_SUCCEEDED(rv)) {
1345
0
    rv = (aQuery->*setter)(value);
1346
0
    if (NS_FAILED(rv)) {
1347
0
      NS_WARNING("Error setting Int32 key value");
1348
0
    }
1349
0
  } else {
1350
0
    NS_WARNING("Invalid Int32 key value in query string.");
1351
0
  }
1352
0
}
1353
void // static
1354
SetOptionsKeyUint32(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
1355
                  Uint32OptionsSetter setter)
1356
0
{
1357
0
  nsresult rv;
1358
0
  uint32_t value = aValue.ToInteger(&rv);
1359
0
  if (NS_SUCCEEDED(rv)) {
1360
0
    rv = (aOptions->*setter)(value);
1361
0
    if (NS_FAILED(rv)) {
1362
0
      NS_WARNING("Error setting Int32 key value");
1363
0
    }
1364
0
  } else {
1365
0
    NS_WARNING("Invalid Int32 key value in query string.");
1366
0
  }
1367
0
}
1368
1369
void // static
1370
SetOptionsKeyUint16(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
1371
                    Uint16OptionsSetter setter)
1372
0
{
1373
0
  nsresult rv;
1374
0
  uint16_t value = static_cast<uint16_t>(aValue.ToInteger(&rv));
1375
0
  if (NS_SUCCEEDED(rv)) {
1376
0
    rv = (aOptions->*setter)(value);
1377
0
    if (NS_FAILED(rv)) {
1378
0
      NS_WARNING("Error setting Int16 key value");
1379
0
    }
1380
0
  } else {
1381
0
    NS_WARNING("Invalid Int16 key value in query string.");
1382
0
  }
1383
0
}
1384
1385
1386
// SetQueryKeyInt64
1387
1388
void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery,
1389
                      Int64QuerySetter setter)
1390
0
{
1391
0
  nsresult rv;
1392
0
  int64_t value;
1393
0
  if (PR_sscanf(aValue.get(), "%lld", &value) == 1) {
1394
0
    rv = (aQuery->*setter)(value);
1395
0
    if (NS_FAILED(rv)) {
1396
0
      NS_WARNING("Error setting Int64 key value");
1397
0
    }
1398
0
  } else {
1399
0
    NS_WARNING("Invalid Int64 value in query string.");
1400
0
  }
1401
0
}