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