LCOV - code coverage report
Current view: directory - toolkit/components/places - nsNavHistoryQuery.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 837 764 91.3 %
Date: 2012-06-02 Functions: 104 98 94.2 %

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

Generated by: LCOV version 1.7