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