toolkit/components/places/nsNavHistoryQuery.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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/. */
     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  */
    12 #include "mozilla/DebugOnly.h"
    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"
    22 using namespace mozilla;
    24 class QueryKeyValuePair
    25 {
    26 public:
    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
    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 };
    52 static nsresult TokenizeQueryString(const nsACString& aQuery,
    53                                     nsTArray<QueryKeyValuePair>* aTokens);
    54 static nsresult ParseQueryBooleanString(const nsCString& aString,
    55                                         bool* aValue);
    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);
    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);
    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);
   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"
   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 }
   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"
   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;
   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);
   202     return folderID;
   203   }
   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;
   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     }
   247     return NS_OK;
   248   }
   249 }
   251 // nsNavHistory::QueryStringToQueries
   252 //
   253 //    From C++ places code, you should use QueryStringToQueryArray, this is
   254 //    the harder-to-use XPCOM version.
   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);
   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);
   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 }
   290 // nsNavHistory::QueryStringToQueryArray
   291 //
   292 //    An internal version of QueryStringToQueries that fills a COM array for
   293 //    ease-of-use.
   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;
   304   nsRefPtr<nsNavHistoryQueryOptions> options(new nsNavHistoryQueryOptions());
   305   if (! options)
   306     return NS_ERROR_OUT_OF_MEMORY;
   308   nsTArray<QueryKeyValuePair> tokens;
   309   rv = TokenizeQueryString(aQueryString, &tokens);
   310   NS_ENSURE_SUCCESS(rv, rv);
   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   }
   319   NS_ADDREF(*aOptions = options);
   320   return NS_OK;
   321 }
   324 // nsNavHistory::QueriesToQueryString
   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);
   335   nsCOMPtr<nsNavHistoryQueryOptions> options = do_QueryInterface(aOptions);
   336   NS_ENSURE_TRUE(options, NS_ERROR_INVALID_ARG);
   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     }
   346     bool hasIt;
   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     }
   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     }
   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;
   380       AppendAmpersandIfNonempty(queryString);
   381       queryString += NS_LITERAL_CSTRING(QUERYKEY_SEARCH_TERMS "=");
   382       queryString += escapedTerms;
   383     }
   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     }
   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     }
   400     // only bookmarked
   401     AppendBoolKeyValueIfTrue(queryString,
   402                              NS_LITERAL_CSTRING(QUERYKEY_ONLY_BOOKMARKED),
   403                              query, &nsINavHistoryQuery::GetOnlyBookmarked);
   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);
   420       AppendAmpersandIfNonempty(queryString);
   421       queryString.Append(NS_LITERAL_CSTRING(QUERYKEY_DOMAIN "="));
   422       queryString.Append(escapedDomain);
   423     }
   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);
   441       AppendAmpersandIfNonempty(queryString);
   442       queryString.Append(NS_LITERAL_CSTRING(QUERYKEY_URI "="));
   443       queryString.Append(escaped);
   444     }
   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     }
   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);
   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;
   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);
   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   }
   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   }
   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   }
   528   // exclude items
   529   if (options->ExcludeItems()) {
   530     AppendAmpersandIfNonempty(queryString);
   531     queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_ITEMS "=1");
   532   }
   534   // exclude queries
   535   if (options->ExcludeQueries()) {
   536     AppendAmpersandIfNonempty(queryString);
   537     queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_QUERIES "=1");
   538   }
   540   // exclude read only folders
   541   if (options->ExcludeReadOnlyFolders()) {
   542     AppendAmpersandIfNonempty(queryString);
   543     queryString += NS_LITERAL_CSTRING(QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS "=1");
   544   }
   546   // expand queries
   547   if (!options->ExpandQueries()) {
   548     AppendAmpersandIfNonempty(queryString);
   549     queryString += NS_LITERAL_CSTRING(QUERYKEY_EXPAND_QUERIES "=0");
   550   }
   552   // include hidden
   553   if (options->IncludeHidden()) {
   554     AppendAmpersandIfNonempty(queryString);
   555     queryString += NS_LITERAL_CSTRING(QUERYKEY_INCLUDE_HIDDEN "=1");
   556   }
   558   // max results
   559   if (options->MaxResults()) {
   560     AppendAmpersandIfNonempty(queryString);
   561     queryString += NS_LITERAL_CSTRING(QUERYKEY_MAX_RESULTS "=");
   562     AppendInt32(queryString, options->MaxResults());
   563   }
   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   }
   572   // async enabled
   573   if (options->AsyncEnabled()) {
   574     AppendAmpersandIfNonempty(queryString);
   575     queryString += NS_LITERAL_CSTRING(QUERYKEY_ASYNC_ENABLED "=1");
   576   }
   578   aQueryString.Assign(NS_LITERAL_CSTRING("place:") + queryString);
   579   return NS_OK;
   580 }
   583 // TokenizeQueryString
   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;
   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   }
   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 }
   623 // nsNavHistory::TokensToQueries
   625 nsresult
   626 nsNavHistory::TokensToQueries(const nsTArray<QueryKeyValuePair>& aTokens,
   627                               nsCOMArray<nsNavHistoryQuery>* aQueries,
   628                               nsNavHistoryQueryOptions* aOptions)
   629 {
   630   nsresult rv;
   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;
   638   if (aTokens.Length() == 0)
   639     return NS_OK; // nothing to do
   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];
   647     // begin time
   648     if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME)) {
   649       SetQueryKeyInt64(kvp.value, query, &nsINavHistoryQuery::SetBeginTime);
   651     // begin time reference
   652     } else if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME_REFERENCE)) {
   653       SetQueryKeyUint32(kvp.value, query, &nsINavHistoryQuery::SetBeginTimeReference);
   655     // end time
   656     } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME)) {
   657       SetQueryKeyInt64(kvp.value, query, &nsINavHistoryQuery::SetEndTime);
   659     // end time reference
   660     } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME_REFERENCE)) {
   661       SetQueryKeyUint32(kvp.value, query, &nsINavHistoryQuery::SetEndTimeReference);
   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);
   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");
   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");
   686     // onlyBookmarked flag
   687     } else if (kvp.key.EqualsLiteral(QUERYKEY_ONLY_BOOKMARKED)) {
   688       SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetOnlyBookmarked);
   690     // domainIsHost flag
   691     } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN_IS_HOST)) {
   692       SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetDomainIsHost);
   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);
   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       }
   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);
   726     // URI is prefix
   727     } else if (kvp.key.EqualsLiteral(QUERYKEY_URIISPREFIX)) {
   728       SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetUriIsPrefix);
   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);
   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);
   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       }
   753     // not tags
   754     } else if (kvp.key.EqualsLiteral(QUERYKEY_NOTTAGS)) {
   755       SetQueryKeyBool(kvp.value, query, &nsINavHistoryQuery::SetTagsAreNot);
   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       }
   769     // new query component
   770     } else if (kvp.key.EqualsLiteral(QUERYKEY_SEPARATOR)) {
   772       if (folders.Length() != 0) {
   773         query->SetFolders(folders.Elements(), folders.Length());
   774         folders.Clear();
   775       }
   777       if (tags.Length() > 0) {
   778         rv = query->SetTags(tags);
   779         NS_ENSURE_SUCCESS(rv, rv);
   780         tags.Clear();
   781       }
   783       if (transitions.Length() > 0) {
   784         rv = query->SetTransitions(transitions);
   785         NS_ENSURE_SUCCESS(rv, rv);
   786         transitions.Clear();
   787       }
   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;
   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);
   810     // exclude items
   811     } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_ITEMS)) {
   812       SetOptionsKeyBool(kvp.value, aOptions,
   813                         &nsINavHistoryQueryOptions::SetExcludeItems);
   815     // exclude queries
   816     } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_QUERIES)) {
   817       SetOptionsKeyBool(kvp.value, aOptions,
   818                         &nsINavHistoryQueryOptions::SetExcludeQueries);
   820     // exclude read only folders
   821     } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_READ_ONLY_FOLDERS)) {
   822       SetOptionsKeyBool(kvp.value, aOptions,
   823                         &nsINavHistoryQueryOptions::SetExcludeReadOnlyFolders);
   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   }
   852   if (folders.Length() != 0)
   853     query->SetFolders(folders.Elements(), folders.Length());
   855   if (tags.Length() > 0) {
   856     rv = query->SetTags(tags);
   857     NS_ENSURE_SUCCESS(rv, rv);
   858   }
   860   if (transitions.Length() > 0) {
   861     rv = query->SetTransitions(transitions);
   862     NS_ENSURE_SUCCESS(rv, rv);
   863   }
   865   return NS_OK;
   866 }
   869 // ParseQueryBooleanString
   870 //
   871 //    Converts a 0/1 or true/false string into a bool
   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 }
   887 // nsINavHistoryQuery **********************************************************
   889 NS_IMPL_ISUPPORTS(nsNavHistoryQuery, nsNavHistoryQuery, nsINavHistoryQuery)
   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.
   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 }
   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 }
   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 }
   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 }
   943 /* readonly attribute PRTime absoluteBeginTime; */
   944 NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteBeginTime(PRTime* _retval)
   945 {
   946   *_retval = nsNavHistory::NormalizeTime(mBeginTimeReference, mBeginTime);
   947   return NS_OK;
   948 }
   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 }
   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 }
   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 }
   983 /* readonly attribute PRTime absoluteEndTime; */
   984 NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteEndTime(PRTime* _retval)
   985 {
   986   *_retval = nsNavHistory::NormalizeTime(mEndTimeReference, mEndTime);
   987   return NS_OK;
   988 }
   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;
  1001 NS_IMETHODIMP nsNavHistoryQuery::GetHasSearchTerms(bool* _retval)
  1003   *_retval = (! mSearchTerms.IsEmpty());
  1004   return NS_OK;
  1007 /* attribute int32_t minVisits; */
  1008 NS_IMETHODIMP nsNavHistoryQuery::GetMinVisits(int32_t* _retval)
  1010   NS_ENSURE_ARG_POINTER(_retval);
  1011   *_retval = mMinVisits;
  1012   return NS_OK;
  1014 NS_IMETHODIMP nsNavHistoryQuery::SetMinVisits(int32_t aVisits)
  1016   mMinVisits = aVisits;
  1017   return NS_OK;
  1020 /* attribute PRint32 maxVisits; */
  1021 NS_IMETHODIMP nsNavHistoryQuery::GetMaxVisits(int32_t* _retval)
  1023   NS_ENSURE_ARG_POINTER(_retval);
  1024   *_retval = mMaxVisits;
  1025   return NS_OK;
  1027 NS_IMETHODIMP nsNavHistoryQuery::SetMaxVisits(int32_t aVisits)
  1029   mMaxVisits = aVisits;
  1030   return NS_OK;
  1033 /* attribute boolean onlyBookmarked; */
  1034 NS_IMETHODIMP nsNavHistoryQuery::GetOnlyBookmarked(bool *aOnlyBookmarked)
  1036   *aOnlyBookmarked = mOnlyBookmarked;
  1037   return NS_OK;
  1039 NS_IMETHODIMP nsNavHistoryQuery::SetOnlyBookmarked(bool aOnlyBookmarked)
  1041   mOnlyBookmarked = aOnlyBookmarked;
  1042   return NS_OK;
  1045 /* attribute boolean domainIsHost; */
  1046 NS_IMETHODIMP nsNavHistoryQuery::GetDomainIsHost(bool *aDomainIsHost)
  1048   *aDomainIsHost = mDomainIsHost;
  1049   return NS_OK;
  1051 NS_IMETHODIMP nsNavHistoryQuery::SetDomainIsHost(bool aDomainIsHost)
  1053   mDomainIsHost = aDomainIsHost;
  1054   return NS_OK;
  1057 /* attribute AUTF8String domain; */
  1058 NS_IMETHODIMP nsNavHistoryQuery::GetDomain(nsACString& aDomain)
  1060   aDomain = mDomain;
  1061   return NS_OK;
  1063 NS_IMETHODIMP nsNavHistoryQuery::SetDomain(const nsACString& aDomain)
  1065   mDomain = aDomain;
  1066   return NS_OK;
  1068 NS_IMETHODIMP nsNavHistoryQuery::GetHasDomain(bool* _retval)
  1070   // note that empty but not void is still a valid query (local files)
  1071   *_retval = (! mDomain.IsVoid());
  1072   return NS_OK;
  1075 /* attribute boolean uriIsPrefix; */
  1076 NS_IMETHODIMP nsNavHistoryQuery::GetUriIsPrefix(bool* aIsPrefix)
  1078   *aIsPrefix = mUriIsPrefix;
  1079   return NS_OK;
  1081 NS_IMETHODIMP nsNavHistoryQuery::SetUriIsPrefix(bool aIsPrefix)
  1083   mUriIsPrefix = aIsPrefix;
  1084   return NS_OK;
  1087 /* attribute nsIURI uri; */
  1088 NS_IMETHODIMP nsNavHistoryQuery::GetUri(nsIURI** aUri)
  1090   NS_IF_ADDREF(*aUri = mUri);
  1091   return NS_OK;
  1093 NS_IMETHODIMP nsNavHistoryQuery::SetUri(nsIURI* aUri)
  1095   mUri = aUri;
  1096   return NS_OK;
  1098 NS_IMETHODIMP nsNavHistoryQuery::GetHasUri(bool* aHasUri)
  1100   *aHasUri = (mUri != nullptr);
  1101   return NS_OK;
  1104 /* attribute boolean annotationIsNot; */
  1105 NS_IMETHODIMP nsNavHistoryQuery::GetAnnotationIsNot(bool* aIsNot)
  1107   *aIsNot = mAnnotationIsNot;
  1108   return NS_OK;
  1110 NS_IMETHODIMP nsNavHistoryQuery::SetAnnotationIsNot(bool aIsNot)
  1112   mAnnotationIsNot = aIsNot;
  1113   return NS_OK;
  1116 /* attribute AUTF8String annotation; */
  1117 NS_IMETHODIMP nsNavHistoryQuery::GetAnnotation(nsACString& aAnnotation)
  1119   aAnnotation = mAnnotation;
  1120   return NS_OK;
  1122 NS_IMETHODIMP nsNavHistoryQuery::SetAnnotation(const nsACString& aAnnotation)
  1124   mAnnotation = aAnnotation;
  1125   return NS_OK;
  1127 NS_IMETHODIMP nsNavHistoryQuery::GetHasAnnotation(bool* aHasIt)
  1129   *aHasIt = ! mAnnotation.IsEmpty();
  1130   return NS_OK;
  1133 /* attribute nsIVariant tags; */
  1134 NS_IMETHODIMP nsNavHistoryQuery::GetTags(nsIVariant **aTags)
  1136   NS_ENSURE_ARG_POINTER(aTags);
  1138   nsresult rv;
  1139   nsCOMPtr<nsIWritableVariant> out = do_CreateInstance(NS_VARIANT_CONTRACTID,
  1140                                                        &rv);
  1141   NS_ENSURE_SUCCESS(rv, rv);
  1143   uint32_t arrayLen = mTags.Length();
  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);
  1153     for (uint32_t i = 0; i < arrayLen; ++i) {
  1154       array[i] = mTags[i].get();
  1157     rv = out->SetAsArray(nsIDataType::VTYPE_WCHAR_STR,
  1158                          nullptr,
  1159                          arrayLen,
  1160                          reinterpret_cast<void *>(array));
  1161     NS_Free(array);
  1163   NS_ENSURE_SUCCESS(rv, rv);
  1165   NS_ADDREF(*aTags = out);
  1166   return NS_OK;
  1169 NS_IMETHODIMP nsNavHistoryQuery::SetTags(nsIVariant *aTags)
  1171   NS_ENSURE_ARG(aTags);
  1173   uint16_t dataType;
  1174   aTags->GetDataType(&dataType);
  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;
  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);
  1185   uint16_t eltType;
  1186   nsIID eltIID;
  1187   uint32_t arrayLen;
  1188   void *array;
  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);
  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:
  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]);
  1207       break;
  1208     case nsIDataType::VTYPE_INTERFACE:
  1209     case nsIDataType::VTYPE_INTERFACE_IS:
  1211         nsISupports **supportsArray = reinterpret_cast<nsISupports **>(array);
  1212         for (uint32_t i = 0; i < arrayLen; ++i) {
  1213           NS_IF_RELEASE(supportsArray[i]);
  1216       break;
  1217     // The other types are primitives that do not need to be freed.
  1219     NS_Free(array);
  1220     return NS_ERROR_ILLEGAL_VALUE;
  1223   char16_t **tags = reinterpret_cast<char16_t **>(array);
  1224   mTags.Clear();
  1226   // Finally, add each passed-in tag to our mTags array and then sort it.
  1227   for (uint32_t i = 0; i < arrayLen; ++i) {
  1229     // Don't allow nulls.
  1230     if (!tags[i]) {
  1231       NS_Free(tags);
  1232       return NS_ERROR_ILLEGAL_VALUE;
  1235     nsDependentString tag(tags[i]);
  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;
  1246     NS_Free(tags[i]);
  1248   NS_Free(tags);
  1250   mTags.Sort();
  1252   return NS_OK;
  1255 /* attribute boolean tagsAreNot; */
  1256 NS_IMETHODIMP nsNavHistoryQuery::GetTagsAreNot(bool *aTagsAreNot)
  1258   NS_ENSURE_ARG_POINTER(aTagsAreNot);
  1259   *aTagsAreNot = mTagsAreNot;
  1260   return NS_OK;
  1263 NS_IMETHODIMP nsNavHistoryQuery::SetTagsAreNot(bool aTagsAreNot)
  1265   mTagsAreNot = aTagsAreNot;
  1266   return NS_OK;
  1269 NS_IMETHODIMP nsNavHistoryQuery::GetFolders(uint32_t *aCount,
  1270                                             int64_t **aFolders)
  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);
  1279     for (uint32_t i = 0; i < count; ++i) {
  1280       folders[i] = mFolders[i];
  1283   *aCount = count;
  1284   *aFolders = folders;
  1285   return NS_OK;
  1288 NS_IMETHODIMP nsNavHistoryQuery::GetFolderCount(uint32_t *aCount)
  1290   *aCount = mFolders.Length();
  1291   return NS_OK;
  1294 NS_IMETHODIMP nsNavHistoryQuery::SetFolders(const int64_t *aFolders,
  1295                                             uint32_t aFolderCount)
  1297   if (!mFolders.ReplaceElementsAt(0, mFolders.Length(),
  1298                                   aFolders, aFolderCount)) {
  1299     return NS_ERROR_OUT_OF_MEMORY;
  1302   return NS_OK;
  1305 NS_IMETHODIMP nsNavHistoryQuery::GetTransitions(uint32_t* aCount,
  1306                                                 uint32_t** aTransitions)
  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];
  1318   *aCount = count;
  1319   *aTransitions = transitions;
  1320   return NS_OK;
  1323 NS_IMETHODIMP nsNavHistoryQuery::GetTransitionCount(uint32_t* aCount)
  1325   *aCount = mTransitions.Length();
  1326   return NS_OK;
  1329 NS_IMETHODIMP nsNavHistoryQuery::SetTransitions(const uint32_t* aTransitions,
  1330                                                 uint32_t aCount)
  1332   if (!mTransitions.ReplaceElementsAt(0, mTransitions.Length(), aTransitions,
  1333                                       aCount))
  1334     return NS_ERROR_OUT_OF_MEMORY;
  1336   return NS_OK;
  1339 NS_IMETHODIMP nsNavHistoryQuery::Clone(nsINavHistoryQuery** _retval)
  1341   *_retval = nullptr;
  1343   nsNavHistoryQuery *clone = new nsNavHistoryQuery(*this);
  1344   NS_ENSURE_TRUE(clone, NS_ERROR_OUT_OF_MEMORY);
  1346   clone->mRefCnt = 0; // the clone doesn't inherit our refcount
  1347   NS_ADDREF(*_retval = clone);
  1348   return NS_OK;
  1352 // nsNavHistoryQueryOptions
  1353 NS_IMPL_ISUPPORTS(nsNavHistoryQueryOptions, nsNavHistoryQueryOptions, nsINavHistoryQueryOptions)
  1355 // sortingMode
  1356 NS_IMETHODIMP
  1357 nsNavHistoryQueryOptions::GetSortingMode(uint16_t* aMode)
  1359   *aMode = mSort;
  1360   return NS_OK;
  1362 NS_IMETHODIMP
  1363 nsNavHistoryQueryOptions::SetSortingMode(uint16_t aMode)
  1365   if (aMode > SORT_BY_FRECENCY_DESCENDING)
  1366     return NS_ERROR_INVALID_ARG;
  1367   mSort = aMode;
  1368   return NS_OK;
  1371 // sortingAnnotation
  1372 NS_IMETHODIMP
  1373 nsNavHistoryQueryOptions::GetSortingAnnotation(nsACString& _result) {
  1374   _result.Assign(mSortingAnnotation);
  1375   return NS_OK;
  1378 NS_IMETHODIMP
  1379 nsNavHistoryQueryOptions::SetSortingAnnotation(const nsACString& aSortingAnnotation) {
  1380   mSortingAnnotation.Assign(aSortingAnnotation);
  1381   return NS_OK;
  1384 // resultType
  1385 NS_IMETHODIMP
  1386 nsNavHistoryQueryOptions::GetResultType(uint16_t* aType)
  1388   *aType = mResultType;
  1389   return NS_OK;
  1391 NS_IMETHODIMP
  1392 nsNavHistoryQueryOptions::SetResultType(uint16_t aType)
  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;
  1404 // excludeItems
  1405 NS_IMETHODIMP
  1406 nsNavHistoryQueryOptions::GetExcludeItems(bool* aExclude)
  1408   *aExclude = mExcludeItems;
  1409   return NS_OK;
  1411 NS_IMETHODIMP
  1412 nsNavHistoryQueryOptions::SetExcludeItems(bool aExclude)
  1414   mExcludeItems = aExclude;
  1415   return NS_OK;
  1418 // excludeQueries
  1419 NS_IMETHODIMP
  1420 nsNavHistoryQueryOptions::GetExcludeQueries(bool* aExclude)
  1422   *aExclude = mExcludeQueries;
  1423   return NS_OK;
  1425 NS_IMETHODIMP
  1426 nsNavHistoryQueryOptions::SetExcludeQueries(bool aExclude)
  1428   mExcludeQueries = aExclude;
  1429   return NS_OK;
  1432 // excludeReadOnlyFolders
  1433 NS_IMETHODIMP
  1434 nsNavHistoryQueryOptions::GetExcludeReadOnlyFolders(bool* aExclude)
  1436   *aExclude = mExcludeReadOnlyFolders;
  1437   return NS_OK;
  1439 NS_IMETHODIMP
  1440 nsNavHistoryQueryOptions::SetExcludeReadOnlyFolders(bool aExclude)
  1442   mExcludeReadOnlyFolders = aExclude;
  1443   return NS_OK;
  1446 // expandQueries
  1447 NS_IMETHODIMP
  1448 nsNavHistoryQueryOptions::GetExpandQueries(bool* aExpand)
  1450   *aExpand = mExpandQueries;
  1451   return NS_OK;
  1453 NS_IMETHODIMP
  1454 nsNavHistoryQueryOptions::SetExpandQueries(bool aExpand)
  1456   mExpandQueries = aExpand;
  1457   return NS_OK;
  1460 // includeHidden
  1461 NS_IMETHODIMP
  1462 nsNavHistoryQueryOptions::GetIncludeHidden(bool* aIncludeHidden)
  1464   *aIncludeHidden = mIncludeHidden;
  1465   return NS_OK;
  1467 NS_IMETHODIMP
  1468 nsNavHistoryQueryOptions::SetIncludeHidden(bool aIncludeHidden)
  1470   mIncludeHidden = aIncludeHidden;
  1471   return NS_OK;
  1474 // maxResults
  1475 NS_IMETHODIMP
  1476 nsNavHistoryQueryOptions::GetMaxResults(uint32_t* aMaxResults)
  1478   *aMaxResults = mMaxResults;
  1479   return NS_OK;
  1481 NS_IMETHODIMP
  1482 nsNavHistoryQueryOptions::SetMaxResults(uint32_t aMaxResults)
  1484   mMaxResults = aMaxResults;
  1485   return NS_OK;
  1488 // queryType
  1489 NS_IMETHODIMP
  1490 nsNavHistoryQueryOptions::GetQueryType(uint16_t* _retval)
  1492   *_retval = mQueryType;
  1493   return NS_OK;
  1495 NS_IMETHODIMP
  1496 nsNavHistoryQueryOptions::SetQueryType(uint16_t aQueryType)
  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;
  1507 // asyncEnabled
  1508 NS_IMETHODIMP
  1509 nsNavHistoryQueryOptions::GetAsyncEnabled(bool* _asyncEnabled)
  1511   *_asyncEnabled = mAsyncEnabled;
  1512   return NS_OK;
  1514 NS_IMETHODIMP
  1515 nsNavHistoryQueryOptions::SetAsyncEnabled(bool aAsyncEnabled)
  1517   mAsyncEnabled = aAsyncEnabled;
  1518   return NS_OK;
  1522 NS_IMETHODIMP
  1523 nsNavHistoryQueryOptions::Clone(nsINavHistoryQueryOptions** aResult)
  1525   nsNavHistoryQueryOptions *clone = nullptr;
  1526   nsresult rv = Clone(&clone);
  1527   *aResult = clone;
  1528   return rv;
  1531 nsresult
  1532 nsNavHistoryQueryOptions::Clone(nsNavHistoryQueryOptions **aResult)
  1534   *aResult = nullptr;
  1535   nsNavHistoryQueryOptions *result = new nsNavHistoryQueryOptions();
  1536   if (! result)
  1537     return NS_ERROR_OUT_OF_MEMORY;
  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;
  1550   resultHolder.swap(*aResult);
  1551   return NS_OK;
  1555 // AppendBoolKeyValueIfTrue
  1557 void // static
  1558 AppendBoolKeyValueIfTrue(nsACString& aString, const nsCString& aName,
  1559                          nsINavHistoryQuery* aQuery,
  1560                          BoolQueryGetter getter)
  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");
  1573 // AppendUint32KeyValueIfNonzero
  1575 void // static
  1576 AppendUint32KeyValueIfNonzero(nsACString& aString,
  1577                               const nsCString& aName,
  1578                               nsINavHistoryQuery* aQuery,
  1579                               Uint32QueryGetter getter)
  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;
  1588     // AppendInt requires a concrete string
  1589     nsAutoCString appendMe("=");
  1590     appendMe.AppendInt(value);
  1591     aString.Append(appendMe);
  1596 // AppendInt64KeyValueIfNonzero
  1598 void // static
  1599 AppendInt64KeyValueIfNonzero(nsACString& aString,
  1600                              const nsCString& aName,
  1601                              nsINavHistoryQuery* aQuery,
  1602                              Int64QueryGetter getter)
  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);
  1617 // SetQuery/OptionsKeyBool
  1619 void // static
  1620 SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
  1621                 BoolQuerySetter setter)
  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");
  1630   } else {
  1631     NS_WARNING("Invalid boolean key value in query string.");
  1634 void // static
  1635 SetOptionsKeyBool(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
  1636                  BoolOptionsSetter setter)
  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");
  1645   } else {
  1646     NS_WARNING("Invalid boolean key value in query string.");
  1651 // SetQuery/OptionsKeyUint32
  1653 void // static
  1654 SetQueryKeyUint32(const nsCString& aValue, nsINavHistoryQuery* aQuery,
  1655                   Uint32QuerySetter setter)
  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");
  1664   } else {
  1665     NS_WARNING("Invalid Int32 key value in query string.");
  1668 void // static
  1669 SetOptionsKeyUint32(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
  1670                   Uint32OptionsSetter setter)
  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");
  1679   } else {
  1680     NS_WARNING("Invalid Int32 key value in query string.");
  1684 void // static
  1685 SetOptionsKeyUint16(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
  1686                     Uint16OptionsSetter setter)
  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");
  1695   } else {
  1696     NS_WARNING("Invalid Int16 key value in query string.");
  1701 // SetQueryKeyInt64
  1703 void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery,
  1704                       Int64QuerySetter setter)
  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");
  1713   } else {
  1714     NS_WARNING("Invalid Int64 value in query string.");

mercurial