Line data Source code
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 QueryStringToQueries and QueriesToQueryString).
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 :
25 0 : class QueryKeyValuePair
26 : {
27 : public:
28 :
29 : // QueryKeyValuePair
30 : //
31 : // 01234567890
32 : // input : qwerty&key=value&qwerty
33 : // ^ ^ ^
34 : // aKeyBegin | aPastEnd (may point to null terminator)
35 : // aEquals
36 : //
37 : // Special case: if aKeyBegin == aEquals, then there is only one string
38 : // and no equal sign, so we treat the entire thing as a key with no value
39 :
40 0 : QueryKeyValuePair(const nsACString& aSource, int32_t aKeyBegin,
41 : int32_t aEquals, int32_t aPastEnd)
42 0 : {
43 0 : if (aEquals == aKeyBegin)
44 0 : aEquals = aPastEnd;
45 0 : key = Substring(aSource, aKeyBegin, aEquals - aKeyBegin);
46 0 : if (aPastEnd - aEquals > 0)
47 0 : value = Substring(aSource, aEquals + 1, aPastEnd - aEquals - 1);
48 0 : }
49 : nsCString key;
50 : nsCString value;
51 : };
52 :
53 : static nsresult TokenizeQueryString(const nsACString& aQuery,
54 : nsTArray<QueryKeyValuePair>* aTokens);
55 : static nsresult ParseQueryBooleanString(const nsCString& aString,
56 : bool* aValue);
57 :
58 : // query getters
59 : typedef decltype(&nsINavHistoryQuery::GetOnlyBookmarked) BoolQueryGetter;
60 : typedef decltype(&nsINavHistoryQuery::GetBeginTimeReference) Uint32QueryGetter;
61 : typedef decltype(&nsINavHistoryQuery::GetBeginTime) Int64QueryGetter;
62 : static void AppendBoolKeyValueIfTrue(nsACString& aString,
63 : const nsCString& aName,
64 : nsINavHistoryQuery* aQuery,
65 : BoolQueryGetter getter);
66 : static void AppendUint32KeyValueIfNonzero(nsACString& aString,
67 : const nsCString& aName,
68 : nsINavHistoryQuery* aQuery,
69 : Uint32QueryGetter getter);
70 : static void AppendInt64KeyValueIfNonzero(nsACString& aString,
71 : const nsCString& aName,
72 : nsINavHistoryQuery* aQuery,
73 : Int64QueryGetter getter);
74 :
75 : // query setters
76 : typedef decltype(&nsINavHistoryQuery::SetOnlyBookmarked) BoolQuerySetter;
77 : typedef decltype(&nsINavHistoryQuery::SetBeginTimeReference) Uint32QuerySetter;
78 : typedef decltype(&nsINavHistoryQuery::SetBeginTime) Int64QuerySetter;
79 : static void SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
80 : BoolQuerySetter setter);
81 : static void SetQueryKeyUint32(const nsCString& aValue, nsINavHistoryQuery* aQuery,
82 : Uint32QuerySetter setter);
83 : static void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery,
84 : Int64QuerySetter setter);
85 :
86 : // options setters
87 : typedef decltype(&nsINavHistoryQueryOptions::SetExpandQueries) BoolOptionsSetter;
88 : typedef decltype(&nsINavHistoryQueryOptions::SetMaxResults) Uint32OptionsSetter;
89 : typedef decltype(&nsINavHistoryQueryOptions::SetResultType) Uint16OptionsSetter;
90 : static void SetOptionsKeyBool(const nsCString& aValue,
91 : nsINavHistoryQueryOptions* aOptions,
92 : BoolOptionsSetter setter);
93 : static void SetOptionsKeyUint16(const nsCString& aValue,
94 : nsINavHistoryQueryOptions* aOptions,
95 : Uint16OptionsSetter setter);
96 : static void SetOptionsKeyUint32(const nsCString& aValue,
97 : nsINavHistoryQueryOptions* aOptions,
98 : Uint32OptionsSetter setter);
99 :
100 : // Components of a query string.
101 : // Note that query strings are also generated in nsNavBookmarks::GetFolderURI
102 : // for performance reasons, so if you change these values, change that, too.
103 : #define QUERYKEY_BEGIN_TIME "beginTime"
104 : #define QUERYKEY_BEGIN_TIME_REFERENCE "beginTimeRef"
105 : #define QUERYKEY_END_TIME "endTime"
106 : #define QUERYKEY_END_TIME_REFERENCE "endTimeRef"
107 : #define QUERYKEY_SEARCH_TERMS "terms"
108 : #define QUERYKEY_MIN_VISITS "minVisits"
109 : #define QUERYKEY_MAX_VISITS "maxVisits"
110 : #define QUERYKEY_ONLY_BOOKMARKED "onlyBookmarked"
111 : #define QUERYKEY_DOMAIN_IS_HOST "domainIsHost"
112 : #define QUERYKEY_DOMAIN "domain"
113 : #define QUERYKEY_FOLDER "folder"
114 : #define QUERYKEY_NOTANNOTATION "!annotation"
115 : #define QUERYKEY_ANNOTATION "annotation"
116 : #define QUERYKEY_URI "uri"
117 : #define QUERYKEY_SEPARATOR "OR"
118 : #define QUERYKEY_GROUP "group"
119 : #define QUERYKEY_SORT "sort"
120 : #define QUERYKEY_SORTING_ANNOTATION "sortingAnnotation"
121 : #define QUERYKEY_RESULT_TYPE "type"
122 : #define QUERYKEY_EXCLUDE_ITEMS "excludeItems"
123 : #define QUERYKEY_EXCLUDE_QUERIES "excludeQueries"
124 : #define QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS "excludeReadOnlyFolders"
125 : #define QUERYKEY_EXPAND_QUERIES "expandQueries"
126 : #define QUERYKEY_FORCE_ORIGINAL_TITLE "originalTitle"
127 : #define QUERYKEY_INCLUDE_HIDDEN "includeHidden"
128 : #define QUERYKEY_MAX_RESULTS "maxResults"
129 : #define QUERYKEY_QUERY_TYPE "queryType"
130 : #define QUERYKEY_TAG "tag"
131 : #define QUERYKEY_NOTTAGS "!tags"
132 : #define QUERYKEY_ASYNC_ENABLED "asyncEnabled"
133 : #define QUERYKEY_TRANSITION "transition"
134 :
135 0 : inline void AppendAmpersandIfNonempty(nsACString& aString)
136 : {
137 0 : if (! aString.IsEmpty())
138 0 : aString.Append('&');
139 0 : }
140 0 : inline void AppendInt16(nsACString& str, int16_t i)
141 : {
142 0 : nsAutoCString tmp;
143 0 : tmp.AppendInt(i);
144 0 : str.Append(tmp);
145 0 : }
146 0 : inline void AppendInt32(nsACString& str, int32_t i)
147 : {
148 0 : nsAutoCString tmp;
149 0 : tmp.AppendInt(i);
150 0 : str.Append(tmp);
151 0 : }
152 0 : inline void AppendInt64(nsACString& str, int64_t i)
153 : {
154 0 : nsCString tmp;
155 0 : tmp.AppendInt(i);
156 0 : str.Append(tmp);
157 0 : }
158 :
159 : namespace PlacesFolderConversion {
160 : #define PLACES_ROOT_FOLDER "PLACES_ROOT"
161 : #define BOOKMARKS_MENU_FOLDER "BOOKMARKS_MENU"
162 : #define TAGS_FOLDER "TAGS"
163 : #define UNFILED_BOOKMARKS_FOLDER "UNFILED_BOOKMARKS"
164 : #define TOOLBAR_FOLDER "TOOLBAR"
165 : #define MOBILE_BOOKMARKS_FOLDER "MOBILE_BOOKMARKS"
166 :
167 : /**
168 : * Converts a folder name to a folder id.
169 : *
170 : * @param aName
171 : * The name of the folder to convert to a folder id.
172 : * @returns the folder id if aName is a recognizable name, -1 otherwise.
173 : */
174 0 : inline int64_t DecodeFolder(const nsCString &aName)
175 : {
176 0 : nsNavBookmarks *bs = nsNavBookmarks::GetBookmarksService();
177 0 : NS_ENSURE_TRUE(bs, false);
178 0 : int64_t folderID = -1;
179 :
180 0 : if (aName.EqualsLiteral(PLACES_ROOT_FOLDER))
181 0 : (void)bs->GetPlacesRoot(&folderID);
182 0 : else if (aName.EqualsLiteral(BOOKMARKS_MENU_FOLDER))
183 0 : (void)bs->GetBookmarksMenuFolder(&folderID);
184 0 : else if (aName.EqualsLiteral(TAGS_FOLDER))
185 0 : (void)bs->GetTagsFolder(&folderID);
186 0 : else if (aName.EqualsLiteral(UNFILED_BOOKMARKS_FOLDER))
187 0 : (void)bs->GetUnfiledBookmarksFolder(&folderID);
188 0 : else if (aName.EqualsLiteral(TOOLBAR_FOLDER))
189 0 : (void)bs->GetToolbarFolder(&folderID);
190 0 : else if (aName.EqualsLiteral(MOBILE_BOOKMARKS_FOLDER))
191 0 : (void)bs->GetMobileFolder(&folderID);
192 :
193 0 : return folderID;
194 : }
195 :
196 : /**
197 : * Converts a folder id to a named constant, or a string representation of the
198 : * folder id if there is no named constant for the folder, and appends it to
199 : * aQuery.
200 : *
201 : * @param aQuery
202 : * The string to append the folder string to. This is generally a
203 : * query string, but could really be anything.
204 : * @param aFolderID
205 : * The folder ID to convert to the proper named constant.
206 : */
207 0 : inline nsresult AppendFolder(nsCString &aQuery, int64_t aFolderID)
208 : {
209 0 : nsNavBookmarks *bs = nsNavBookmarks::GetBookmarksService();
210 0 : NS_ENSURE_STATE(bs);
211 0 : int64_t folderID = -1;
212 :
213 0 : if (NS_SUCCEEDED(bs->GetPlacesRoot(&folderID)) &&
214 0 : aFolderID == folderID) {
215 0 : aQuery.AppendLiteral(PLACES_ROOT_FOLDER);
216 : }
217 0 : else if (NS_SUCCEEDED(bs->GetBookmarksMenuFolder(&folderID)) &&
218 0 : aFolderID == folderID) {
219 0 : aQuery.AppendLiteral(BOOKMARKS_MENU_FOLDER);
220 : }
221 0 : else if (NS_SUCCEEDED(bs->GetTagsFolder(&folderID)) &&
222 0 : aFolderID == folderID) {
223 0 : aQuery.AppendLiteral(TAGS_FOLDER);
224 : }
225 0 : else if (NS_SUCCEEDED(bs->GetUnfiledBookmarksFolder(&folderID)) &&
226 0 : aFolderID == folderID) {
227 0 : aQuery.AppendLiteral(UNFILED_BOOKMARKS_FOLDER);
228 : }
229 0 : else if (NS_SUCCEEDED(bs->GetToolbarFolder(&folderID)) &&
230 0 : aFolderID == folderID) {
231 0 : aQuery.AppendLiteral(TOOLBAR_FOLDER);
232 : }
233 0 : else if (NS_SUCCEEDED(bs->GetMobileFolder(&folderID)) &&
234 0 : aFolderID == folderID) {
235 0 : aQuery.AppendLiteral(MOBILE_BOOKMARKS_FOLDER);
236 : }
237 : else {
238 : // It wasn't one of our named constants, so just convert it to a string.
239 0 : aQuery.AppendInt(aFolderID);
240 : }
241 :
242 0 : return NS_OK;
243 : }
244 : } // namespace PlacesFolderConversion
245 :
246 : // nsNavHistory::QueryStringToQueries
247 : //
248 : // From C++ places code, you should use QueryStringToQueryArray, this is
249 : // the harder-to-use XPCOM version.
250 :
251 : NS_IMETHODIMP
252 0 : nsNavHistory::QueryStringToQueries(const nsACString& aQueryString,
253 : nsINavHistoryQuery*** aQueries,
254 : uint32_t* aResultCount,
255 : nsINavHistoryQueryOptions** aOptions)
256 : {
257 0 : NS_ENSURE_ARG_POINTER(aQueries);
258 0 : NS_ENSURE_ARG_POINTER(aResultCount);
259 0 : NS_ENSURE_ARG_POINTER(aOptions);
260 :
261 0 : *aQueries = nullptr;
262 0 : *aResultCount = 0;
263 0 : nsCOMPtr<nsNavHistoryQueryOptions> options;
264 0 : nsCOMArray<nsNavHistoryQuery> queries;
265 0 : nsresult rv = QueryStringToQueryArray(aQueryString, &queries,
266 0 : getter_AddRefs(options));
267 0 : NS_ENSURE_SUCCESS(rv, rv);
268 :
269 0 : *aResultCount = queries.Count();
270 0 : if (queries.Count() > 0) {
271 : // convert COM array to raw
272 0 : *aQueries = static_cast<nsINavHistoryQuery**>
273 0 : (moz_xmalloc(sizeof(nsINavHistoryQuery*) * queries.Count()));
274 0 : NS_ENSURE_TRUE(*aQueries, NS_ERROR_OUT_OF_MEMORY);
275 0 : for (int32_t i = 0; i < queries.Count(); i ++) {
276 0 : (*aQueries)[i] = queries[i];
277 0 : NS_ADDREF((*aQueries)[i]);
278 : }
279 : }
280 0 : options.forget(aOptions);
281 0 : return NS_OK;
282 : }
283 :
284 :
285 : // nsNavHistory::QueryStringToQueryArray
286 : //
287 : // An internal version of QueryStringToQueries that fills a COM array for
288 : // ease-of-use.
289 :
290 : nsresult
291 0 : nsNavHistory::QueryStringToQueryArray(const nsACString& aQueryString,
292 : nsCOMArray<nsNavHistoryQuery>* aQueries,
293 : nsNavHistoryQueryOptions** aOptions)
294 : {
295 : nsresult rv;
296 0 : aQueries->Clear();
297 0 : *aOptions = nullptr;
298 :
299 0 : RefPtr<nsNavHistoryQueryOptions> options(new nsNavHistoryQueryOptions());
300 0 : if (! options)
301 0 : return NS_ERROR_OUT_OF_MEMORY;
302 :
303 0 : nsTArray<QueryKeyValuePair> tokens;
304 0 : rv = TokenizeQueryString(aQueryString, &tokens);
305 0 : NS_ENSURE_SUCCESS(rv, rv);
306 :
307 0 : rv = TokensToQueries(tokens, aQueries, options);
308 0 : if (NS_FAILED(rv)) {
309 0 : NS_WARNING("Unable to parse the query string: ");
310 0 : NS_WARNING(PromiseFlatCString(aQueryString).get());
311 0 : return rv;
312 : }
313 :
314 0 : options.forget(aOptions);
315 0 : return NS_OK;
316 : }
317 :
318 :
319 : // nsNavHistory::QueriesToQueryString
320 :
321 : NS_IMETHODIMP
322 0 : nsNavHistory::QueriesToQueryString(nsINavHistoryQuery **aQueries,
323 : uint32_t aQueryCount,
324 : nsINavHistoryQueryOptions* aOptions,
325 : nsACString& aQueryString)
326 : {
327 0 : NS_ENSURE_ARG(aQueries);
328 0 : NS_ENSURE_ARG(aOptions);
329 :
330 0 : nsCOMPtr<nsNavHistoryQueryOptions> options = do_QueryInterface(aOptions);
331 0 : NS_ENSURE_TRUE(options, NS_ERROR_INVALID_ARG);
332 :
333 0 : nsAutoCString queryString;
334 0 : for (uint32_t queryIndex = 0; queryIndex < aQueryCount; queryIndex ++) {
335 0 : nsCOMPtr<nsNavHistoryQuery> query = do_QueryInterface(aQueries[queryIndex]);
336 0 : if (queryIndex > 0) {
337 0 : AppendAmpersandIfNonempty(queryString);
338 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_SEPARATOR);
339 : }
340 :
341 : bool hasIt;
342 :
343 : // begin time
344 0 : query->GetHasBeginTime(&hasIt);
345 0 : if (hasIt) {
346 0 : AppendInt64KeyValueIfNonzero(queryString,
347 0 : NS_LITERAL_CSTRING(QUERYKEY_BEGIN_TIME),
348 0 : query, &nsINavHistoryQuery::GetBeginTime);
349 0 : AppendUint32KeyValueIfNonzero(queryString,
350 0 : NS_LITERAL_CSTRING(QUERYKEY_BEGIN_TIME_REFERENCE),
351 0 : query, &nsINavHistoryQuery::GetBeginTimeReference);
352 : }
353 :
354 : // end time
355 0 : query->GetHasEndTime(&hasIt);
356 0 : if (hasIt) {
357 0 : AppendInt64KeyValueIfNonzero(queryString,
358 0 : NS_LITERAL_CSTRING(QUERYKEY_END_TIME),
359 0 : query, &nsINavHistoryQuery::GetEndTime);
360 0 : AppendUint32KeyValueIfNonzero(queryString,
361 0 : NS_LITERAL_CSTRING(QUERYKEY_END_TIME_REFERENCE),
362 0 : query, &nsINavHistoryQuery::GetEndTimeReference);
363 : }
364 :
365 : // search terms
366 0 : query->GetHasSearchTerms(&hasIt);
367 0 : if (hasIt) {
368 0 : nsAutoString searchTerms;
369 0 : query->GetSearchTerms(searchTerms);
370 0 : nsCString escapedTerms;
371 0 : if (! NS_Escape(NS_ConvertUTF16toUTF8(searchTerms), escapedTerms,
372 : url_XAlphas))
373 0 : return NS_ERROR_OUT_OF_MEMORY;
374 :
375 0 : AppendAmpersandIfNonempty(queryString);
376 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_SEARCH_TERMS "=");
377 0 : queryString += escapedTerms;
378 : }
379 :
380 : // min and max visits
381 : int32_t minVisits;
382 0 : if (NS_SUCCEEDED(query->GetMinVisits(&minVisits)) && minVisits >= 0) {
383 0 : AppendAmpersandIfNonempty(queryString);
384 0 : queryString.AppendLiteral(QUERYKEY_MIN_VISITS "=");
385 0 : AppendInt32(queryString, minVisits);
386 : }
387 :
388 : int32_t maxVisits;
389 0 : if (NS_SUCCEEDED(query->GetMaxVisits(&maxVisits)) && maxVisits >= 0) {
390 0 : AppendAmpersandIfNonempty(queryString);
391 0 : queryString.AppendLiteral(QUERYKEY_MAX_VISITS "=");
392 0 : AppendInt32(queryString, maxVisits);
393 : }
394 :
395 : // only bookmarked
396 0 : AppendBoolKeyValueIfTrue(queryString,
397 0 : NS_LITERAL_CSTRING(QUERYKEY_ONLY_BOOKMARKED),
398 0 : query, &nsINavHistoryQuery::GetOnlyBookmarked);
399 :
400 : // domain (+ is host), only call if hasDomain, which means non-IsVoid
401 : // this means we may get an empty string for the domain in the result,
402 : // which is valid
403 0 : query->GetHasDomain(&hasIt);
404 0 : if (hasIt) {
405 0 : AppendBoolKeyValueIfTrue(queryString,
406 0 : NS_LITERAL_CSTRING(QUERYKEY_DOMAIN_IS_HOST),
407 0 : query, &nsINavHistoryQuery::GetDomainIsHost);
408 0 : nsAutoCString domain;
409 0 : nsresult rv = query->GetDomain(domain);
410 0 : NS_ENSURE_SUCCESS(rv, rv);
411 0 : nsCString escapedDomain;
412 0 : bool success = NS_Escape(domain, escapedDomain, url_XAlphas);
413 0 : NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
414 :
415 0 : AppendAmpersandIfNonempty(queryString);
416 0 : queryString.AppendLiteral(QUERYKEY_DOMAIN "=");
417 0 : queryString.Append(escapedDomain);
418 : }
419 :
420 : // uri
421 0 : query->GetHasUri(&hasIt);
422 0 : if (hasIt) {
423 0 : nsCOMPtr<nsIURI> uri;
424 0 : query->GetUri(getter_AddRefs(uri));
425 0 : NS_ENSURE_TRUE(uri, NS_ERROR_FAILURE); // hasURI should tell is if invalid
426 0 : nsAutoCString uriSpec;
427 0 : nsresult rv = uri->GetSpec(uriSpec);
428 0 : NS_ENSURE_SUCCESS(rv, rv);
429 0 : nsAutoCString escaped;
430 0 : bool success = NS_Escape(uriSpec, escaped, url_XAlphas);
431 0 : NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
432 :
433 0 : AppendAmpersandIfNonempty(queryString);
434 0 : queryString.AppendLiteral(QUERYKEY_URI "=");
435 0 : queryString.Append(escaped);
436 : }
437 :
438 : // annotation
439 0 : query->GetHasAnnotation(&hasIt);
440 0 : if (hasIt) {
441 0 : AppendAmpersandIfNonempty(queryString);
442 : bool annotationIsNot;
443 0 : query->GetAnnotationIsNot(&annotationIsNot);
444 0 : if (annotationIsNot)
445 0 : queryString.AppendLiteral(QUERYKEY_NOTANNOTATION "=");
446 : else
447 0 : queryString.AppendLiteral(QUERYKEY_ANNOTATION "=");
448 0 : nsAutoCString annot;
449 0 : query->GetAnnotation(annot);
450 0 : nsAutoCString escaped;
451 0 : bool success = NS_Escape(annot, escaped, url_XAlphas);
452 0 : NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
453 0 : queryString.Append(escaped);
454 : }
455 :
456 : // folders
457 0 : int64_t *folders = nullptr;
458 0 : uint32_t folderCount = 0;
459 0 : query->GetFolders(&folderCount, &folders);
460 0 : for (uint32_t i = 0; i < folderCount; ++i) {
461 0 : AppendAmpersandIfNonempty(queryString);
462 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_FOLDER "=");
463 0 : nsresult rv = PlacesFolderConversion::AppendFolder(queryString, folders[i]);
464 0 : NS_ENSURE_SUCCESS(rv, rv);
465 : }
466 0 : free(folders);
467 :
468 : // tags
469 0 : const nsTArray<nsString> &tags = query->Tags();
470 0 : for (uint32_t i = 0; i < tags.Length(); ++i) {
471 0 : nsAutoCString escapedTag;
472 0 : if (!NS_Escape(NS_ConvertUTF16toUTF8(tags[i]), escapedTag, url_XAlphas))
473 0 : return NS_ERROR_OUT_OF_MEMORY;
474 :
475 0 : AppendAmpersandIfNonempty(queryString);
476 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_TAG "=");
477 0 : queryString += escapedTag;
478 : }
479 0 : AppendBoolKeyValueIfTrue(queryString,
480 0 : NS_LITERAL_CSTRING(QUERYKEY_NOTTAGS),
481 : query,
482 0 : &nsINavHistoryQuery::GetTagsAreNot);
483 :
484 : // transitions
485 0 : const nsTArray<uint32_t>& transitions = query->Transitions();
486 0 : for (uint32_t i = 0; i < transitions.Length(); ++i) {
487 0 : AppendAmpersandIfNonempty(queryString);
488 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_TRANSITION "=");
489 0 : AppendInt64(queryString, transitions[i]);
490 : }
491 : }
492 :
493 : // sorting
494 0 : if (options->SortingMode() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
495 0 : AppendAmpersandIfNonempty(queryString);
496 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_SORT "=");
497 0 : AppendInt16(queryString, options->SortingMode());
498 0 : if (options->SortingMode() == nsINavHistoryQueryOptions::SORT_BY_ANNOTATION_DESCENDING ||
499 0 : options->SortingMode() == nsINavHistoryQueryOptions::SORT_BY_ANNOTATION_ASCENDING) {
500 : // sortingAnnotation
501 0 : nsAutoCString sortingAnnotation;
502 0 : if (NS_SUCCEEDED(options->GetSortingAnnotation(sortingAnnotation))) {
503 0 : nsCString escaped;
504 0 : if (!NS_Escape(sortingAnnotation, escaped, url_XAlphas))
505 0 : return NS_ERROR_OUT_OF_MEMORY;
506 0 : AppendAmpersandIfNonempty(queryString);
507 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_SORTING_ANNOTATION "=");
508 0 : queryString.Append(escaped);
509 : }
510 : }
511 : }
512 :
513 : // result type
514 0 : if (options->ResultType() != nsINavHistoryQueryOptions::RESULTS_AS_URI) {
515 0 : AppendAmpersandIfNonempty(queryString);
516 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_RESULT_TYPE "=");
517 0 : AppendInt16(queryString, options->ResultType());
518 : }
519 :
520 : // exclude items
521 0 : if (options->ExcludeItems()) {
522 0 : AppendAmpersandIfNonempty(queryString);
523 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_ITEMS "=1");
524 : }
525 :
526 : // exclude queries
527 0 : if (options->ExcludeQueries()) {
528 0 : AppendAmpersandIfNonempty(queryString);
529 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_QUERIES "=1");
530 : }
531 :
532 : // exclude read only folders
533 0 : if (options->ExcludeReadOnlyFolders()) {
534 0 : AppendAmpersandIfNonempty(queryString);
535 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS "=1");
536 : }
537 :
538 : // expand queries
539 0 : if (!options->ExpandQueries()) {
540 0 : AppendAmpersandIfNonempty(queryString);
541 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_EXPAND_QUERIES "=0");
542 : }
543 :
544 : // include hidden
545 0 : if (options->IncludeHidden()) {
546 0 : AppendAmpersandIfNonempty(queryString);
547 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_INCLUDE_HIDDEN "=1");
548 : }
549 :
550 : // max results
551 0 : if (options->MaxResults()) {
552 0 : AppendAmpersandIfNonempty(queryString);
553 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_MAX_RESULTS "=");
554 0 : AppendInt32(queryString, options->MaxResults());
555 : }
556 :
557 : // queryType
558 0 : if (options->QueryType() != nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY) {
559 0 : AppendAmpersandIfNonempty(queryString);
560 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_QUERY_TYPE "=");
561 0 : AppendInt16(queryString, options->QueryType());
562 : }
563 :
564 : // async enabled
565 0 : if (options->AsyncEnabled()) {
566 0 : AppendAmpersandIfNonempty(queryString);
567 0 : queryString += NS_LITERAL_CSTRING(QUERYKEY_ASYNC_ENABLED "=1");
568 : }
569 :
570 0 : aQueryString.AssignLiteral("place:");
571 0 : aQueryString.Append(queryString);
572 0 : return NS_OK;
573 : }
574 :
575 :
576 : // TokenizeQueryString
577 :
578 : nsresult
579 0 : TokenizeQueryString(const nsACString& aQuery,
580 : nsTArray<QueryKeyValuePair>* aTokens)
581 : {
582 : // Strip off the "place:" prefix
583 0 : const uint32_t prefixlen = 6; // = strlen("place:");
584 0 : nsCString query;
585 0 : if (aQuery.Length() >= prefixlen &&
586 0 : Substring(aQuery, 0, prefixlen).EqualsLiteral("place:"))
587 0 : query = Substring(aQuery, prefixlen);
588 : else
589 0 : query = aQuery;
590 :
591 0 : int32_t keyFirstIndex = 0;
592 0 : int32_t equalsIndex = 0;
593 0 : for (uint32_t i = 0; i < query.Length(); i ++) {
594 0 : if (query[i] == '&') {
595 : // new clause, save last one
596 0 : if (i - keyFirstIndex > 1) {
597 0 : if (! aTokens->AppendElement(QueryKeyValuePair(query, keyFirstIndex,
598 : equalsIndex, i)))
599 0 : return NS_ERROR_OUT_OF_MEMORY;
600 : }
601 0 : keyFirstIndex = equalsIndex = i + 1;
602 0 : } else if (query[i] == '=') {
603 0 : equalsIndex = i;
604 : }
605 : }
606 :
607 : // handle last pair, if any
608 0 : if (query.Length() - keyFirstIndex > 1) {
609 0 : if (! aTokens->AppendElement(QueryKeyValuePair(query, keyFirstIndex,
610 0 : equalsIndex, query.Length())))
611 0 : return NS_ERROR_OUT_OF_MEMORY;
612 : }
613 0 : return NS_OK;
614 : }
615 :
616 : // nsNavHistory::TokensToQueries
617 :
618 : nsresult
619 0 : nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
620 : nsCOMArray<nsNavHistoryQuery>* aQueries,
621 : nsNavHistoryQueryOptions* aOptions)
622 : {
623 : nsresult rv;
624 :
625 0 : nsCOMPtr<nsNavHistoryQuery> query(new nsNavHistoryQuery());
626 0 : if (! query)
627 0 : return NS_ERROR_OUT_OF_MEMORY;
628 0 : if (! aQueries->AppendObject(query))
629 0 : return NS_ERROR_OUT_OF_MEMORY;
630 :
631 0 : if (aTokens.Length() == 0)
632 0 : return NS_OK; // nothing to do
633 :
634 0 : nsTArray<int64_t> folders;
635 0 : nsTArray<nsString> tags;
636 0 : nsTArray<uint32_t> transitions;
637 0 : for (uint32_t i = 0; i < aTokens.Length(); i ++) {
638 0 : const QueryKeyValuePair& kvp = aTokens[i];
639 :
640 : // begin time
641 0 : if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME)) {
642 0 : SetQueryKeyInt64(kvp.value, query, &nsINavHistoryQuery::SetBeginTime);
643 :
644 : // begin time reference
645 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME_REFERENCE)) {
646 0 : SetQueryKeyUint32(kvp.value, query, &nsINavHistoryQuery::SetBeginTimeReference);
647 :
648 : // end time
649 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME)) {
650 0 : SetQueryKeyInt64(kvp.value, query, &nsINavHistoryQuery::SetEndTime);
651 :
652 : // end time reference
653 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME_REFERENCE)) {
654 0 : SetQueryKeyUint32(kvp.value, query, &nsINavHistoryQuery::SetEndTimeReference);
655 :
656 : // search terms
657 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_SEARCH_TERMS)) {
658 0 : nsCString unescapedTerms = kvp.value;
659 0 : NS_UnescapeURL(unescapedTerms); // modifies input
660 0 : rv = query->SetSearchTerms(NS_ConvertUTF8toUTF16(unescapedTerms));
661 0 : NS_ENSURE_SUCCESS(rv, rv);
662 :
663 : // min visits
664 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_MIN_VISITS)) {
665 0 : int32_t visits = kvp.value.ToInteger(&rv);
666 0 : if (NS_SUCCEEDED(rv))
667 0 : query->SetMinVisits(visits);
668 : else
669 0 : NS_WARNING("Bad number for minVisits in query");
670 :
671 : // max visits
672 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_VISITS)) {
673 0 : int32_t visits = kvp.value.ToInteger(&rv);
674 0 : if (NS_SUCCEEDED(rv))
675 0 : query->SetMaxVisits(visits);
676 : else
677 0 : NS_WARNING("Bad number for maxVisits in query");
678 :
679 : // onlyBookmarked flag
680 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_ONLY_BOOKMARKED)) {
681 0 : SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetOnlyBookmarked);
682 :
683 : // domainIsHost flag
684 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN_IS_HOST)) {
685 0 : SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetDomainIsHost);
686 :
687 : // domain string
688 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN)) {
689 0 : nsAutoCString unescapedDomain(kvp.value);
690 0 : NS_UnescapeURL(unescapedDomain); // modifies input
691 0 : rv = query->SetDomain(unescapedDomain);
692 0 : NS_ENSURE_SUCCESS(rv, rv);
693 :
694 : // folders
695 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_FOLDER)) {
696 : int64_t folder;
697 0 : if (PR_sscanf(kvp.value.get(), "%lld", &folder) == 1) {
698 0 : NS_ENSURE_TRUE(folders.AppendElement(folder), NS_ERROR_OUT_OF_MEMORY);
699 : } else {
700 0 : folder = PlacesFolderConversion::DecodeFolder(kvp.value);
701 0 : if (folder != -1)
702 0 : NS_ENSURE_TRUE(folders.AppendElement(folder), NS_ERROR_OUT_OF_MEMORY);
703 : else
704 0 : NS_WARNING("folders value in query is invalid, ignoring");
705 : }
706 :
707 : // uri
708 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_URI)) {
709 0 : nsAutoCString unescapedUri(kvp.value);
710 0 : NS_UnescapeURL(unescapedUri); // modifies input
711 0 : nsCOMPtr<nsIURI> uri;
712 0 : nsresult rv = NS_NewURI(getter_AddRefs(uri), unescapedUri);
713 0 : if (NS_FAILED(rv)) {
714 0 : NS_WARNING("Unable to parse URI");
715 : }
716 0 : rv = query->SetUri(uri);
717 0 : NS_ENSURE_SUCCESS(rv, rv);
718 :
719 : // not annotation
720 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_NOTANNOTATION)) {
721 0 : nsAutoCString unescaped(kvp.value);
722 0 : NS_UnescapeURL(unescaped); // modifies input
723 0 : query->SetAnnotationIsNot(true);
724 0 : query->SetAnnotation(unescaped);
725 :
726 : // annotation
727 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_ANNOTATION)) {
728 0 : nsAutoCString unescaped(kvp.value);
729 0 : NS_UnescapeURL(unescaped); // modifies input
730 0 : query->SetAnnotationIsNot(false);
731 0 : query->SetAnnotation(unescaped);
732 :
733 : // tag
734 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_TAG)) {
735 0 : nsAutoCString unescaped(kvp.value);
736 0 : NS_UnescapeURL(unescaped); // modifies input
737 0 : NS_ConvertUTF8toUTF16 tag(unescaped);
738 0 : if (!tags.Contains(tag)) {
739 0 : NS_ENSURE_TRUE(tags.AppendElement(tag), NS_ERROR_OUT_OF_MEMORY);
740 : }
741 :
742 : // not tags
743 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_NOTTAGS)) {
744 0 : SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetTagsAreNot);
745 :
746 : // transition
747 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_TRANSITION)) {
748 0 : uint32_t transition = kvp.value.ToInteger(&rv);
749 0 : if (NS_SUCCEEDED(rv)) {
750 0 : if (!transitions.Contains(transition))
751 0 : NS_ENSURE_TRUE(transitions.AppendElement(transition),
752 : NS_ERROR_OUT_OF_MEMORY);
753 : }
754 : else {
755 0 : NS_WARNING("Invalid Int32 transition value.");
756 : }
757 :
758 : // new query component
759 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_SEPARATOR)) {
760 :
761 0 : if (folders.Length() != 0) {
762 0 : query->SetFolders(folders.Elements(), folders.Length());
763 0 : folders.Clear();
764 : }
765 :
766 0 : if (tags.Length() > 0) {
767 0 : rv = query->SetTags(tags);
768 0 : NS_ENSURE_SUCCESS(rv, rv);
769 0 : tags.Clear();
770 : }
771 :
772 0 : if (transitions.Length() > 0) {
773 0 : rv = query->SetTransitions(transitions);
774 0 : NS_ENSURE_SUCCESS(rv, rv);
775 0 : transitions.Clear();
776 : }
777 :
778 0 : query = new nsNavHistoryQuery();
779 0 : if (! query)
780 0 : return NS_ERROR_OUT_OF_MEMORY;
781 0 : if (! aQueries->AppendObject(query))
782 0 : return NS_ERROR_OUT_OF_MEMORY;
783 :
784 : // sorting mode
785 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_SORT)) {
786 0 : SetOptionsKeyUint16(kvp.value, aOptions,
787 0 : &nsINavHistoryQueryOptions::SetSortingMode);
788 : // sorting annotation
789 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_SORTING_ANNOTATION)) {
790 0 : nsCString sortingAnnotation = kvp.value;
791 0 : NS_UnescapeURL(sortingAnnotation);
792 0 : rv = aOptions->SetSortingAnnotation(sortingAnnotation);
793 0 : NS_ENSURE_SUCCESS(rv, rv);
794 : // result type
795 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_RESULT_TYPE)) {
796 0 : SetOptionsKeyUint16(kvp.value, aOptions,
797 0 : &nsINavHistoryQueryOptions::SetResultType);
798 :
799 : // exclude items
800 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_ITEMS)) {
801 0 : SetOptionsKeyBool(kvp.value, aOptions,
802 0 : &nsINavHistoryQueryOptions::SetExcludeItems);
803 :
804 : // exclude queries
805 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_QUERIES)) {
806 0 : SetOptionsKeyBool(kvp.value, aOptions,
807 0 : &nsINavHistoryQueryOptions::SetExcludeQueries);
808 :
809 : // exclude read only folders
810 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS)) {
811 0 : SetOptionsKeyBool(kvp.value, aOptions,
812 0 : &nsINavHistoryQueryOptions::SetExcludeReadOnlyFolders);
813 :
814 : // expand queries
815 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_EXPAND_QUERIES)) {
816 0 : SetOptionsKeyBool(kvp.value, aOptions,
817 0 : &nsINavHistoryQueryOptions::SetExpandQueries);
818 : // include hidden
819 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_INCLUDE_HIDDEN)) {
820 0 : SetOptionsKeyBool(kvp.value, aOptions,
821 0 : &nsINavHistoryQueryOptions::SetIncludeHidden);
822 : // max results
823 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_RESULTS)) {
824 0 : SetOptionsKeyUint32(kvp.value, aOptions,
825 0 : &nsINavHistoryQueryOptions::SetMaxResults);
826 : // query type
827 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_QUERY_TYPE)) {
828 0 : SetOptionsKeyUint16(kvp.value, aOptions,
829 0 : &nsINavHistoryQueryOptions::SetQueryType);
830 : // async enabled
831 0 : } else if (kvp.key.EqualsLiteral(QUERYKEY_ASYNC_ENABLED)) {
832 0 : SetOptionsKeyBool(kvp.value, aOptions,
833 0 : &nsINavHistoryQueryOptions::SetAsyncEnabled);
834 : // unknown key
835 : } else {
836 0 : NS_WARNING("TokensToQueries(), ignoring unknown key: ");
837 0 : NS_WARNING(kvp.key.get());
838 : }
839 : }
840 :
841 0 : if (folders.Length() != 0)
842 0 : query->SetFolders(folders.Elements(), folders.Length());
843 :
844 0 : if (tags.Length() > 0) {
845 0 : rv = query->SetTags(tags);
846 0 : NS_ENSURE_SUCCESS(rv, rv);
847 : }
848 :
849 0 : if (transitions.Length() > 0) {
850 0 : rv = query->SetTransitions(transitions);
851 0 : NS_ENSURE_SUCCESS(rv, rv);
852 : }
853 :
854 0 : return NS_OK;
855 : }
856 :
857 :
858 : // ParseQueryBooleanString
859 : //
860 : // Converts a 0/1 or true/false string into a bool
861 :
862 : nsresult
863 0 : ParseQueryBooleanString(const nsCString& aString, bool* aValue)
864 : {
865 0 : if (aString.EqualsLiteral("1") || aString.EqualsLiteral("true")) {
866 0 : *aValue = true;
867 0 : return NS_OK;
868 0 : } else if (aString.EqualsLiteral("0") || aString.EqualsLiteral("false")) {
869 0 : *aValue = false;
870 0 : return NS_OK;
871 : }
872 0 : return NS_ERROR_INVALID_ARG;
873 : }
874 :
875 :
876 : // nsINavHistoryQuery **********************************************************
877 :
878 0 : NS_IMPL_ISUPPORTS(nsNavHistoryQuery, nsNavHistoryQuery, nsINavHistoryQuery)
879 :
880 : // nsINavHistoryQuery::nsNavHistoryQuery
881 : //
882 : // This must initialize the object such that the default values will cause
883 : // all history to be returned if this query is used. Then the caller can
884 : // just set the things it's interested in.
885 :
886 0 : nsNavHistoryQuery::nsNavHistoryQuery()
887 : : mMinVisits(-1), mMaxVisits(-1), mBeginTime(0),
888 : mBeginTimeReference(TIME_RELATIVE_EPOCH),
889 : mEndTime(0), mEndTimeReference(TIME_RELATIVE_EPOCH),
890 : mOnlyBookmarked(false),
891 : mDomainIsHost(false),
892 : mAnnotationIsNot(false),
893 0 : mTagsAreNot(false)
894 : {
895 : // differentiate not set (IsVoid) from empty string (local files)
896 0 : mDomain.SetIsVoid(true);
897 0 : }
898 :
899 0 : nsNavHistoryQuery::nsNavHistoryQuery(const nsNavHistoryQuery& aOther)
900 0 : : mMinVisits(aOther.mMinVisits), mMaxVisits(aOther.mMaxVisits),
901 0 : mBeginTime(aOther.mBeginTime),
902 0 : mBeginTimeReference(aOther.mBeginTimeReference),
903 0 : mEndTime(aOther.mEndTime), mEndTimeReference(aOther.mEndTimeReference),
904 0 : mSearchTerms(aOther.mSearchTerms), mOnlyBookmarked(aOther.mOnlyBookmarked),
905 0 : mDomainIsHost(aOther.mDomainIsHost), mDomain(aOther.mDomain),
906 : mUri(aOther.mUri),
907 0 : mAnnotationIsNot(aOther.mAnnotationIsNot),
908 : mAnnotation(aOther.mAnnotation), mTags(aOther.mTags),
909 0 : mTagsAreNot(aOther.mTagsAreNot), mTransitions(aOther.mTransitions)
910 0 : {}
911 :
912 0 : NS_IMETHODIMP nsNavHistoryQuery::GetBeginTime(PRTime *aBeginTime)
913 : {
914 0 : *aBeginTime = mBeginTime;
915 0 : return NS_OK;
916 : }
917 0 : NS_IMETHODIMP nsNavHistoryQuery::SetBeginTime(PRTime aBeginTime)
918 : {
919 0 : mBeginTime = aBeginTime;
920 0 : return NS_OK;
921 : }
922 :
923 0 : NS_IMETHODIMP nsNavHistoryQuery::GetBeginTimeReference(uint32_t* _retval)
924 : {
925 0 : *_retval = mBeginTimeReference;
926 0 : return NS_OK;
927 : }
928 0 : NS_IMETHODIMP nsNavHistoryQuery::SetBeginTimeReference(uint32_t aReference)
929 : {
930 0 : if (aReference > TIME_RELATIVE_NOW)
931 0 : return NS_ERROR_INVALID_ARG;
932 0 : mBeginTimeReference = aReference;
933 0 : return NS_OK;
934 : }
935 :
936 0 : NS_IMETHODIMP nsNavHistoryQuery::GetHasBeginTime(bool* _retval)
937 : {
938 0 : *_retval = ! (mBeginTimeReference == TIME_RELATIVE_EPOCH && mBeginTime == 0);
939 0 : return NS_OK;
940 : }
941 :
942 0 : NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteBeginTime(PRTime* _retval)
943 : {
944 0 : *_retval = nsNavHistory::NormalizeTime(mBeginTimeReference, mBeginTime);
945 0 : return NS_OK;
946 : }
947 :
948 0 : NS_IMETHODIMP nsNavHistoryQuery::GetEndTime(PRTime *aEndTime)
949 : {
950 0 : *aEndTime = mEndTime;
951 0 : return NS_OK;
952 : }
953 0 : NS_IMETHODIMP nsNavHistoryQuery::SetEndTime(PRTime aEndTime)
954 : {
955 0 : mEndTime = aEndTime;
956 0 : return NS_OK;
957 : }
958 :
959 0 : NS_IMETHODIMP nsNavHistoryQuery::GetEndTimeReference(uint32_t* _retval)
960 : {
961 0 : *_retval = mEndTimeReference;
962 0 : return NS_OK;
963 : }
964 0 : NS_IMETHODIMP nsNavHistoryQuery::SetEndTimeReference(uint32_t aReference)
965 : {
966 0 : if (aReference > TIME_RELATIVE_NOW)
967 0 : return NS_ERROR_INVALID_ARG;
968 0 : mEndTimeReference = aReference;
969 0 : return NS_OK;
970 : }
971 :
972 0 : NS_IMETHODIMP nsNavHistoryQuery::GetHasEndTime(bool* _retval)
973 : {
974 0 : *_retval = ! (mEndTimeReference == TIME_RELATIVE_EPOCH && mEndTime == 0);
975 0 : return NS_OK;
976 : }
977 :
978 0 : NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteEndTime(PRTime* _retval)
979 : {
980 0 : *_retval = nsNavHistory::NormalizeTime(mEndTimeReference, mEndTime);
981 0 : return NS_OK;
982 : }
983 :
984 0 : NS_IMETHODIMP nsNavHistoryQuery::GetSearchTerms(nsAString& aSearchTerms)
985 : {
986 0 : aSearchTerms = mSearchTerms;
987 0 : return NS_OK;
988 : }
989 0 : NS_IMETHODIMP nsNavHistoryQuery::SetSearchTerms(const nsAString& aSearchTerms)
990 : {
991 0 : mSearchTerms = aSearchTerms;
992 0 : return NS_OK;
993 : }
994 0 : NS_IMETHODIMP nsNavHistoryQuery::GetHasSearchTerms(bool* _retval)
995 : {
996 0 : *_retval = (! mSearchTerms.IsEmpty());
997 0 : return NS_OK;
998 : }
999 :
1000 0 : NS_IMETHODIMP nsNavHistoryQuery::GetMinVisits(int32_t* _retval)
1001 : {
1002 0 : NS_ENSURE_ARG_POINTER(_retval);
1003 0 : *_retval = mMinVisits;
1004 0 : return NS_OK;
1005 : }
1006 0 : NS_IMETHODIMP nsNavHistoryQuery::SetMinVisits(int32_t aVisits)
1007 : {
1008 0 : mMinVisits = aVisits;
1009 0 : return NS_OK;
1010 : }
1011 :
1012 0 : NS_IMETHODIMP nsNavHistoryQuery::GetMaxVisits(int32_t* _retval)
1013 : {
1014 0 : NS_ENSURE_ARG_POINTER(_retval);
1015 0 : *_retval = mMaxVisits;
1016 0 : return NS_OK;
1017 : }
1018 0 : NS_IMETHODIMP nsNavHistoryQuery::SetMaxVisits(int32_t aVisits)
1019 : {
1020 0 : mMaxVisits = aVisits;
1021 0 : return NS_OK;
1022 : }
1023 :
1024 0 : NS_IMETHODIMP nsNavHistoryQuery::GetOnlyBookmarked(bool *aOnlyBookmarked)
1025 : {
1026 0 : *aOnlyBookmarked = mOnlyBookmarked;
1027 0 : return NS_OK;
1028 : }
1029 0 : NS_IMETHODIMP nsNavHistoryQuery::SetOnlyBookmarked(bool aOnlyBookmarked)
1030 : {
1031 0 : mOnlyBookmarked = aOnlyBookmarked;
1032 0 : return NS_OK;
1033 : }
1034 :
1035 0 : NS_IMETHODIMP nsNavHistoryQuery::GetDomainIsHost(bool *aDomainIsHost)
1036 : {
1037 0 : *aDomainIsHost = mDomainIsHost;
1038 0 : return NS_OK;
1039 : }
1040 0 : NS_IMETHODIMP nsNavHistoryQuery::SetDomainIsHost(bool aDomainIsHost)
1041 : {
1042 0 : mDomainIsHost = aDomainIsHost;
1043 0 : return NS_OK;
1044 : }
1045 :
1046 0 : NS_IMETHODIMP nsNavHistoryQuery::GetDomain(nsACString& aDomain)
1047 : {
1048 0 : aDomain = mDomain;
1049 0 : return NS_OK;
1050 : }
1051 0 : NS_IMETHODIMP nsNavHistoryQuery::SetDomain(const nsACString& aDomain)
1052 : {
1053 0 : mDomain = aDomain;
1054 0 : return NS_OK;
1055 : }
1056 0 : NS_IMETHODIMP nsNavHistoryQuery::GetHasDomain(bool* _retval)
1057 : {
1058 : // note that empty but not void is still a valid query (local files)
1059 0 : *_retval = (! mDomain.IsVoid());
1060 0 : return NS_OK;
1061 : }
1062 :
1063 0 : NS_IMETHODIMP nsNavHistoryQuery::GetUri(nsIURI** aUri)
1064 : {
1065 0 : NS_IF_ADDREF(*aUri = mUri);
1066 0 : return NS_OK;
1067 : }
1068 0 : NS_IMETHODIMP nsNavHistoryQuery::SetUri(nsIURI* aUri)
1069 : {
1070 0 : mUri = aUri;
1071 0 : return NS_OK;
1072 : }
1073 0 : NS_IMETHODIMP nsNavHistoryQuery::GetHasUri(bool* aHasUri)
1074 : {
1075 0 : *aHasUri = (mUri != nullptr);
1076 0 : return NS_OK;
1077 : }
1078 :
1079 0 : NS_IMETHODIMP nsNavHistoryQuery::GetAnnotationIsNot(bool* aIsNot)
1080 : {
1081 0 : *aIsNot = mAnnotationIsNot;
1082 0 : return NS_OK;
1083 : }
1084 0 : NS_IMETHODIMP nsNavHistoryQuery::SetAnnotationIsNot(bool aIsNot)
1085 : {
1086 0 : mAnnotationIsNot = aIsNot;
1087 0 : return NS_OK;
1088 : }
1089 :
1090 0 : NS_IMETHODIMP nsNavHistoryQuery::GetAnnotation(nsACString& aAnnotation)
1091 : {
1092 0 : aAnnotation = mAnnotation;
1093 0 : return NS_OK;
1094 : }
1095 0 : NS_IMETHODIMP nsNavHistoryQuery::SetAnnotation(const nsACString& aAnnotation)
1096 : {
1097 0 : mAnnotation = aAnnotation;
1098 0 : return NS_OK;
1099 : }
1100 0 : NS_IMETHODIMP nsNavHistoryQuery::GetHasAnnotation(bool* aHasIt)
1101 : {
1102 0 : *aHasIt = ! mAnnotation.IsEmpty();
1103 0 : return NS_OK;
1104 : }
1105 :
1106 0 : NS_IMETHODIMP nsNavHistoryQuery::GetTags(nsIVariant **aTags)
1107 : {
1108 0 : NS_ENSURE_ARG_POINTER(aTags);
1109 :
1110 0 : RefPtr<nsVariant> out = new nsVariant();
1111 :
1112 0 : uint32_t arrayLen = mTags.Length();
1113 :
1114 : nsresult rv;
1115 0 : if (arrayLen == 0)
1116 0 : rv = out->SetAsEmptyArray();
1117 : else {
1118 : // Note: The resulting nsIVariant dupes both the array and its elements.
1119 : const char16_t **array = reinterpret_cast<const char16_t **>
1120 0 : (moz_xmalloc(arrayLen * sizeof(char16_t *)));
1121 0 : NS_ENSURE_TRUE(array, NS_ERROR_OUT_OF_MEMORY);
1122 :
1123 0 : for (uint32_t i = 0; i < arrayLen; ++i) {
1124 0 : array[i] = mTags[i].get();
1125 : }
1126 :
1127 0 : rv = out->SetAsArray(nsIDataType::VTYPE_WCHAR_STR,
1128 : nullptr,
1129 : arrayLen,
1130 0 : reinterpret_cast<void *>(array));
1131 0 : free(array);
1132 : }
1133 0 : NS_ENSURE_SUCCESS(rv, rv);
1134 :
1135 0 : out.forget(aTags);
1136 0 : return NS_OK;
1137 : }
1138 :
1139 0 : NS_IMETHODIMP nsNavHistoryQuery::SetTags(nsIVariant *aTags)
1140 : {
1141 0 : NS_ENSURE_ARG(aTags);
1142 :
1143 : uint16_t dataType;
1144 0 : aTags->GetDataType(&dataType);
1145 :
1146 : // Caller passed in empty array. Easy -- clear our mTags array and return.
1147 0 : if (dataType == nsIDataType::VTYPE_EMPTY_ARRAY) {
1148 0 : mTags.Clear();
1149 0 : return NS_OK;
1150 : }
1151 :
1152 : // Before we go any further, make sure caller passed in an array.
1153 0 : NS_ENSURE_TRUE(dataType == nsIDataType::VTYPE_ARRAY, NS_ERROR_ILLEGAL_VALUE);
1154 :
1155 : uint16_t eltType;
1156 : nsIID eltIID;
1157 : uint32_t arrayLen;
1158 : void *array;
1159 :
1160 : // Convert the nsIVariant to an array. We own the resulting buffer and its
1161 : // elements.
1162 0 : nsresult rv = aTags->GetAsArray(&eltType, &eltIID, &arrayLen, &array);
1163 0 : NS_ENSURE_SUCCESS(rv, rv);
1164 :
1165 : // If element type is not wstring, thanks a lot. Your memory die now.
1166 0 : if (eltType != nsIDataType::VTYPE_WCHAR_STR) {
1167 0 : switch (eltType) {
1168 : case nsIDataType::VTYPE_ID:
1169 : case nsIDataType::VTYPE_CHAR_STR:
1170 : {
1171 0 : char **charArray = reinterpret_cast<char **>(array);
1172 0 : for (uint32_t i = 0; i < arrayLen; ++i) {
1173 0 : if (charArray[i])
1174 0 : free(charArray[i]);
1175 : }
1176 : }
1177 0 : break;
1178 : case nsIDataType::VTYPE_INTERFACE:
1179 : case nsIDataType::VTYPE_INTERFACE_IS:
1180 : {
1181 0 : nsISupports **supportsArray = reinterpret_cast<nsISupports **>(array);
1182 0 : for (uint32_t i = 0; i < arrayLen; ++i) {
1183 0 : NS_IF_RELEASE(supportsArray[i]);
1184 : }
1185 : }
1186 0 : break;
1187 : // The other types are primitives that do not need to be freed.
1188 : }
1189 0 : free(array);
1190 0 : return NS_ERROR_ILLEGAL_VALUE;
1191 : }
1192 :
1193 0 : char16_t **tags = reinterpret_cast<char16_t **>(array);
1194 0 : mTags.Clear();
1195 :
1196 : // Finally, add each passed-in tag to our mTags array and then sort it.
1197 0 : for (uint32_t i = 0; i < arrayLen; ++i) {
1198 :
1199 : // Don't allow nulls.
1200 0 : if (!tags[i]) {
1201 0 : free(tags);
1202 0 : return NS_ERROR_ILLEGAL_VALUE;
1203 : }
1204 :
1205 0 : nsDependentString tag(tags[i]);
1206 :
1207 : // Don't store duplicate tags. This isn't just to save memory or to be
1208 : // fancy; the SQL that's built from the tags relies on no dupes.
1209 0 : if (!mTags.Contains(tag)) {
1210 0 : if (!mTags.AppendElement(tag)) {
1211 0 : free(tags[i]);
1212 0 : free(tags);
1213 0 : return NS_ERROR_OUT_OF_MEMORY;
1214 : }
1215 : }
1216 0 : free(tags[i]);
1217 : }
1218 0 : free(tags);
1219 :
1220 0 : mTags.Sort();
1221 :
1222 0 : return NS_OK;
1223 : }
1224 :
1225 0 : NS_IMETHODIMP nsNavHistoryQuery::GetTagsAreNot(bool *aTagsAreNot)
1226 : {
1227 0 : NS_ENSURE_ARG_POINTER(aTagsAreNot);
1228 0 : *aTagsAreNot = mTagsAreNot;
1229 0 : return NS_OK;
1230 : }
1231 :
1232 0 : NS_IMETHODIMP nsNavHistoryQuery::SetTagsAreNot(bool aTagsAreNot)
1233 : {
1234 0 : mTagsAreNot = aTagsAreNot;
1235 0 : return NS_OK;
1236 : }
1237 :
1238 0 : NS_IMETHODIMP nsNavHistoryQuery::GetFolders(uint32_t *aCount,
1239 : int64_t **aFolders)
1240 : {
1241 0 : uint32_t count = mFolders.Length();
1242 0 : int64_t *folders = nullptr;
1243 0 : if (count > 0) {
1244 : folders = static_cast<int64_t*>
1245 0 : (moz_xmalloc(count * sizeof(int64_t)));
1246 0 : NS_ENSURE_TRUE(folders, NS_ERROR_OUT_OF_MEMORY);
1247 :
1248 0 : for (uint32_t i = 0; i < count; ++i) {
1249 0 : folders[i] = mFolders[i];
1250 : }
1251 : }
1252 0 : *aCount = count;
1253 0 : *aFolders = folders;
1254 0 : return NS_OK;
1255 : }
1256 :
1257 0 : NS_IMETHODIMP nsNavHistoryQuery::GetFolderCount(uint32_t *aCount)
1258 : {
1259 0 : *aCount = mFolders.Length();
1260 0 : return NS_OK;
1261 : }
1262 :
1263 0 : NS_IMETHODIMP nsNavHistoryQuery::SetFolders(const int64_t *aFolders,
1264 : uint32_t aFolderCount)
1265 : {
1266 0 : if (!mFolders.ReplaceElementsAt(0, mFolders.Length(),
1267 : aFolders, aFolderCount)) {
1268 0 : return NS_ERROR_OUT_OF_MEMORY;
1269 : }
1270 :
1271 0 : return NS_OK;
1272 : }
1273 :
1274 0 : NS_IMETHODIMP nsNavHistoryQuery::GetTransitions(uint32_t* aCount,
1275 : uint32_t** aTransitions)
1276 : {
1277 0 : uint32_t count = mTransitions.Length();
1278 0 : uint32_t* transitions = nullptr;
1279 0 : if (count > 0) {
1280 : transitions = reinterpret_cast<uint32_t*>
1281 0 : (moz_xmalloc(count * sizeof(uint32_t)));
1282 0 : NS_ENSURE_TRUE(transitions, NS_ERROR_OUT_OF_MEMORY);
1283 0 : for (uint32_t i = 0; i < count; ++i) {
1284 0 : transitions[i] = mTransitions[i];
1285 : }
1286 : }
1287 0 : *aCount = count;
1288 0 : *aTransitions = transitions;
1289 0 : return NS_OK;
1290 : }
1291 :
1292 0 : NS_IMETHODIMP nsNavHistoryQuery::GetTransitionCount(uint32_t* aCount)
1293 : {
1294 0 : *aCount = mTransitions.Length();
1295 0 : return NS_OK;
1296 : }
1297 :
1298 0 : NS_IMETHODIMP nsNavHistoryQuery::SetTransitions(const uint32_t* aTransitions,
1299 : uint32_t aCount)
1300 : {
1301 0 : if (!mTransitions.ReplaceElementsAt(0, mTransitions.Length(), aTransitions,
1302 : aCount))
1303 0 : return NS_ERROR_OUT_OF_MEMORY;
1304 :
1305 0 : return NS_OK;
1306 : }
1307 :
1308 0 : NS_IMETHODIMP nsNavHistoryQuery::Clone(nsINavHistoryQuery** _retval)
1309 : {
1310 0 : *_retval = nullptr;
1311 :
1312 0 : RefPtr<nsNavHistoryQuery> clone = new nsNavHistoryQuery(*this);
1313 0 : NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
1314 :
1315 0 : clone.forget(_retval);
1316 0 : return NS_OK;
1317 : }
1318 :
1319 :
1320 : // nsNavHistoryQueryOptions
1321 0 : NS_IMPL_ISUPPORTS(nsNavHistoryQueryOptions, nsNavHistoryQueryOptions, nsINavHistoryQueryOptions)
1322 :
1323 : // sortingMode
1324 : NS_IMETHODIMP
1325 0 : nsNavHistoryQueryOptions::GetSortingMode(uint16_t* aMode)
1326 : {
1327 0 : *aMode = mSort;
1328 0 : return NS_OK;
1329 : }
1330 : NS_IMETHODIMP
1331 0 : nsNavHistoryQueryOptions::SetSortingMode(uint16_t aMode)
1332 : {
1333 0 : if (aMode > SORT_BY_FRECENCY_DESCENDING)
1334 0 : return NS_ERROR_INVALID_ARG;
1335 0 : mSort = aMode;
1336 0 : return NS_OK;
1337 : }
1338 :
1339 : // sortingAnnotation
1340 : NS_IMETHODIMP
1341 0 : nsNavHistoryQueryOptions::GetSortingAnnotation(nsACString& _result) {
1342 0 : _result.Assign(mSortingAnnotation);
1343 0 : return NS_OK;
1344 : }
1345 :
1346 : NS_IMETHODIMP
1347 0 : nsNavHistoryQueryOptions::SetSortingAnnotation(const nsACString& aSortingAnnotation) {
1348 0 : mSortingAnnotation.Assign(aSortingAnnotation);
1349 0 : return NS_OK;
1350 : }
1351 :
1352 : // resultType
1353 : NS_IMETHODIMP
1354 0 : nsNavHistoryQueryOptions::GetResultType(uint16_t* aType)
1355 : {
1356 0 : *aType = mResultType;
1357 0 : return NS_OK;
1358 : }
1359 : NS_IMETHODIMP
1360 0 : nsNavHistoryQueryOptions::SetResultType(uint16_t aType)
1361 : {
1362 0 : if (aType > RESULTS_AS_TAG_CONTENTS)
1363 0 : return NS_ERROR_INVALID_ARG;
1364 : // Tag queries and containers are bookmarks related, so we set the QueryType
1365 : // accordingly.
1366 0 : if (aType == RESULTS_AS_TAG_QUERY || aType == RESULTS_AS_TAG_CONTENTS)
1367 0 : mQueryType = QUERY_TYPE_BOOKMARKS;
1368 0 : mResultType = aType;
1369 0 : return NS_OK;
1370 : }
1371 :
1372 : // excludeItems
1373 : NS_IMETHODIMP
1374 0 : nsNavHistoryQueryOptions::GetExcludeItems(bool* aExclude)
1375 : {
1376 0 : *aExclude = mExcludeItems;
1377 0 : return NS_OK;
1378 : }
1379 : NS_IMETHODIMP
1380 0 : nsNavHistoryQueryOptions::SetExcludeItems(bool aExclude)
1381 : {
1382 0 : mExcludeItems = aExclude;
1383 0 : return NS_OK;
1384 : }
1385 :
1386 : // excludeQueries
1387 : NS_IMETHODIMP
1388 0 : nsNavHistoryQueryOptions::GetExcludeQueries(bool* aExclude)
1389 : {
1390 0 : *aExclude = mExcludeQueries;
1391 0 : return NS_OK;
1392 : }
1393 : NS_IMETHODIMP
1394 0 : nsNavHistoryQueryOptions::SetExcludeQueries(bool aExclude)
1395 : {
1396 0 : mExcludeQueries = aExclude;
1397 0 : return NS_OK;
1398 : }
1399 :
1400 : // excludeReadOnlyFolders
1401 : NS_IMETHODIMP
1402 0 : nsNavHistoryQueryOptions::GetExcludeReadOnlyFolders(bool* aExclude)
1403 : {
1404 0 : *aExclude = mExcludeReadOnlyFolders;
1405 0 : return NS_OK;
1406 : }
1407 : NS_IMETHODIMP
1408 0 : nsNavHistoryQueryOptions::SetExcludeReadOnlyFolders(bool aExclude)
1409 : {
1410 0 : mExcludeReadOnlyFolders = aExclude;
1411 0 : return NS_OK;
1412 : }
1413 :
1414 : // expandQueries
1415 : NS_IMETHODIMP
1416 0 : nsNavHistoryQueryOptions::GetExpandQueries(bool* aExpand)
1417 : {
1418 0 : *aExpand = mExpandQueries;
1419 0 : return NS_OK;
1420 : }
1421 : NS_IMETHODIMP
1422 0 : nsNavHistoryQueryOptions::SetExpandQueries(bool aExpand)
1423 : {
1424 0 : mExpandQueries = aExpand;
1425 0 : return NS_OK;
1426 : }
1427 :
1428 : // includeHidden
1429 : NS_IMETHODIMP
1430 0 : nsNavHistoryQueryOptions::GetIncludeHidden(bool* aIncludeHidden)
1431 : {
1432 0 : *aIncludeHidden = mIncludeHidden;
1433 0 : return NS_OK;
1434 : }
1435 : NS_IMETHODIMP
1436 0 : nsNavHistoryQueryOptions::SetIncludeHidden(bool aIncludeHidden)
1437 : {
1438 0 : mIncludeHidden = aIncludeHidden;
1439 0 : return NS_OK;
1440 : }
1441 :
1442 : // maxResults
1443 : NS_IMETHODIMP
1444 0 : nsNavHistoryQueryOptions::GetMaxResults(uint32_t* aMaxResults)
1445 : {
1446 0 : *aMaxResults = mMaxResults;
1447 0 : return NS_OK;
1448 : }
1449 : NS_IMETHODIMP
1450 0 : nsNavHistoryQueryOptions::SetMaxResults(uint32_t aMaxResults)
1451 : {
1452 0 : mMaxResults = aMaxResults;
1453 0 : return NS_OK;
1454 : }
1455 :
1456 : // queryType
1457 : NS_IMETHODIMP
1458 0 : nsNavHistoryQueryOptions::GetQueryType(uint16_t* _retval)
1459 : {
1460 0 : *_retval = mQueryType;
1461 0 : return NS_OK;
1462 : }
1463 : NS_IMETHODIMP
1464 0 : nsNavHistoryQueryOptions::SetQueryType(uint16_t aQueryType)
1465 : {
1466 : // Tag query and containers are forced to QUERY_TYPE_BOOKMARKS when the
1467 : // resultType is set.
1468 0 : if (mResultType == RESULTS_AS_TAG_CONTENTS ||
1469 0 : mResultType == RESULTS_AS_TAG_QUERY)
1470 0 : return NS_OK;
1471 0 : mQueryType = aQueryType;
1472 0 : return NS_OK;
1473 : }
1474 :
1475 : // asyncEnabled
1476 : NS_IMETHODIMP
1477 0 : nsNavHistoryQueryOptions::GetAsyncEnabled(bool* _asyncEnabled)
1478 : {
1479 0 : *_asyncEnabled = mAsyncEnabled;
1480 0 : return NS_OK;
1481 : }
1482 : NS_IMETHODIMP
1483 0 : nsNavHistoryQueryOptions::SetAsyncEnabled(bool aAsyncEnabled)
1484 : {
1485 0 : mAsyncEnabled = aAsyncEnabled;
1486 0 : return NS_OK;
1487 : }
1488 :
1489 :
1490 : NS_IMETHODIMP
1491 0 : nsNavHistoryQueryOptions::Clone(nsINavHistoryQueryOptions** aResult)
1492 : {
1493 0 : nsNavHistoryQueryOptions *clone = nullptr;
1494 0 : nsresult rv = Clone(&clone);
1495 0 : *aResult = clone;
1496 0 : return rv;
1497 : }
1498 :
1499 : nsresult
1500 0 : nsNavHistoryQueryOptions::Clone(nsNavHistoryQueryOptions **aResult)
1501 : {
1502 0 : *aResult = nullptr;
1503 0 : nsNavHistoryQueryOptions *result = new nsNavHistoryQueryOptions();
1504 :
1505 0 : RefPtr<nsNavHistoryQueryOptions> resultHolder(result);
1506 0 : result->mSort = mSort;
1507 0 : result->mResultType = mResultType;
1508 0 : result->mExcludeItems = mExcludeItems;
1509 0 : result->mExcludeQueries = mExcludeQueries;
1510 0 : result->mExpandQueries = mExpandQueries;
1511 0 : result->mMaxResults = mMaxResults;
1512 0 : result->mQueryType = mQueryType;
1513 0 : result->mParentAnnotationToExclude = mParentAnnotationToExclude;
1514 0 : result->mAsyncEnabled = mAsyncEnabled;
1515 :
1516 0 : resultHolder.forget(aResult);
1517 0 : return NS_OK;
1518 : }
1519 :
1520 :
1521 : // AppendBoolKeyValueIfTrue
1522 :
1523 : void // static
1524 0 : AppendBoolKeyValueIfTrue(nsACString& aString, const nsCString& aName,
1525 : nsINavHistoryQuery* aQuery,
1526 : BoolQueryGetter getter)
1527 : {
1528 : bool value;
1529 0 : DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
1530 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting boolean value");
1531 0 : if (value) {
1532 0 : AppendAmpersandIfNonempty(aString);
1533 0 : aString += aName;
1534 0 : aString.AppendLiteral("=1");
1535 : }
1536 0 : }
1537 :
1538 :
1539 : // AppendUint32KeyValueIfNonzero
1540 :
1541 : void // static
1542 0 : AppendUint32KeyValueIfNonzero(nsACString& aString,
1543 : const nsCString& aName,
1544 : nsINavHistoryQuery* aQuery,
1545 : Uint32QueryGetter getter)
1546 : {
1547 : uint32_t value;
1548 0 : DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
1549 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting value");
1550 0 : if (value) {
1551 0 : AppendAmpersandIfNonempty(aString);
1552 0 : aString += aName;
1553 :
1554 : // AppendInt requires a concrete string
1555 0 : nsAutoCString appendMe("=");
1556 0 : appendMe.AppendInt(value);
1557 0 : aString.Append(appendMe);
1558 : }
1559 0 : }
1560 :
1561 :
1562 : // AppendInt64KeyValueIfNonzero
1563 :
1564 : void // static
1565 0 : AppendInt64KeyValueIfNonzero(nsACString& aString,
1566 : const nsCString& aName,
1567 : nsINavHistoryQuery* aQuery,
1568 : Int64QueryGetter getter)
1569 : {
1570 : PRTime value;
1571 0 : DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
1572 0 : NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting value");
1573 0 : if (value) {
1574 0 : AppendAmpersandIfNonempty(aString);
1575 0 : aString += aName;
1576 0 : nsAutoCString appendMe("=");
1577 0 : appendMe.AppendInt(static_cast<int64_t>(value));
1578 0 : aString.Append(appendMe);
1579 : }
1580 0 : }
1581 :
1582 :
1583 : // SetQuery/OptionsKeyBool
1584 :
1585 : void // static
1586 0 : SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
1587 : BoolQuerySetter setter)
1588 : {
1589 : bool value;
1590 0 : nsresult rv = ParseQueryBooleanString(aValue, &value);
1591 0 : if (NS_SUCCEEDED(rv)) {
1592 0 : rv = (aQuery->*setter)(value);
1593 0 : if (NS_FAILED(rv)) {
1594 0 : NS_WARNING("Error setting boolean key value");
1595 : }
1596 : } else {
1597 0 : NS_WARNING("Invalid boolean key value in query string.");
1598 : }
1599 0 : }
1600 : void // static
1601 0 : SetOptionsKeyBool(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
1602 : BoolOptionsSetter setter)
1603 : {
1604 0 : bool value = false;
1605 0 : nsresult rv = ParseQueryBooleanString(aValue, &value);
1606 0 : if (NS_SUCCEEDED(rv)) {
1607 0 : rv = (aOptions->*setter)(value);
1608 0 : if (NS_FAILED(rv)) {
1609 0 : NS_WARNING("Error setting boolean key value");
1610 : }
1611 : } else {
1612 0 : NS_WARNING("Invalid boolean key value in query string.");
1613 : }
1614 0 : }
1615 :
1616 :
1617 : // SetQuery/OptionsKeyUint32
1618 :
1619 : void // static
1620 0 : SetQueryKeyUint32(const nsCString& aValue, nsINavHistoryQuery* aQuery,
1621 : Uint32QuerySetter setter)
1622 : {
1623 : nsresult rv;
1624 0 : uint32_t value = aValue.ToInteger(&rv);
1625 0 : if (NS_SUCCEEDED(rv)) {
1626 0 : rv = (aQuery->*setter)(value);
1627 0 : if (NS_FAILED(rv)) {
1628 0 : NS_WARNING("Error setting Int32 key value");
1629 : }
1630 : } else {
1631 0 : NS_WARNING("Invalid Int32 key value in query string.");
1632 : }
1633 0 : }
1634 : void // static
1635 0 : SetOptionsKeyUint32(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
1636 : Uint32OptionsSetter setter)
1637 : {
1638 : nsresult rv;
1639 0 : uint32_t value = aValue.ToInteger(&rv);
1640 0 : if (NS_SUCCEEDED(rv)) {
1641 0 : rv = (aOptions->*setter)(value);
1642 0 : if (NS_FAILED(rv)) {
1643 0 : NS_WARNING("Error setting Int32 key value");
1644 : }
1645 : } else {
1646 0 : NS_WARNING("Invalid Int32 key value in query string.");
1647 : }
1648 0 : }
1649 :
1650 : void // static
1651 0 : SetOptionsKeyUint16(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
1652 : Uint16OptionsSetter setter)
1653 : {
1654 : nsresult rv;
1655 0 : uint16_t value = static_cast<uint16_t>(aValue.ToInteger(&rv));
1656 0 : if (NS_SUCCEEDED(rv)) {
1657 0 : rv = (aOptions->*setter)(value);
1658 0 : if (NS_FAILED(rv)) {
1659 0 : NS_WARNING("Error setting Int16 key value");
1660 : }
1661 : } else {
1662 0 : NS_WARNING("Invalid Int16 key value in query string.");
1663 : }
1664 0 : }
1665 :
1666 :
1667 : // SetQueryKeyInt64
1668 :
1669 0 : void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery,
1670 : Int64QuerySetter setter)
1671 : {
1672 : nsresult rv;
1673 : int64_t value;
1674 0 : if (PR_sscanf(aValue.get(), "%lld", &value) == 1) {
1675 0 : rv = (aQuery->*setter)(value);
1676 0 : if (NS_FAILED(rv)) {
1677 0 : NS_WARNING("Error setting Int64 key value");
1678 : }
1679 : } else {
1680 0 : NS_WARNING("Invalid Int64 value in query string.");
1681 : }
1682 0 : }
|