toolkit/components/places/nsNavHistoryQuery.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial