Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  nsNavHistoryQuery.cpp   Sprache: C

 
//* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


/**
 * This file contains the definitions of nsNavHistoryQuery,
 * nsNavHistoryQueryOptions, and those functions in nsINavHistory that directly
 * support queries (specifically QueryStringToQuery and QueryToQueryString).
 */


#include "mozilla/DebugOnly.h"

#include "nsNavHistory.h"
#include "nsNavBookmarks.h"
#include "nsEscape.h"
#include "nsCOMArray.h"
#include "nsNetUtil.h"
#include "nsTArray.h"
#include "nsQueryObject.h"
#include "prprf.h"
#include "nsVariant.h"

using namespace mozilla;
using namespace mozilla::places;

static nsresult ParseQueryBooleanString(const nsCString& aString, bool* aValue);

// query getters
using BoolQueryGetter = nsresult (NS_STDCALL nsINavHistoryQuery::*)(bool*);
using Uint32QueryGetter =
    nsresult (NS_STDCALL nsINavHistoryQuery::*)(uint32_t*);
using Int64QueryGetter = nsresult (NS_STDCALL nsINavHistoryQuery::*)(int64_t*);
static void AppendBoolKeyValueIfTrue(nsACString& aString,
                                     const nsCString& aName,
                                     nsINavHistoryQuery* aQuery,
                                     BoolQueryGetter getter);
static void AppendUint32KeyValueIfNonzero(nsACString& aString,
                                          const nsCString& aName,
                                          nsINavHistoryQuery* aQuery,
                                          Uint32QueryGetter getter);
static void AppendInt64KeyValueIfNonzero(nsACString& aString,
                                         const nsCString& aName,
                                         nsINavHistoryQuery* aQuery,
                                         Int64QueryGetter getter);

// query setters
using BoolQuerySetter = nsresult (NS_STDCALL nsINavHistoryQuery::*)(bool);
using Uint32QuerySetter = nsresult (NS_STDCALL nsINavHistoryQuery::*)(uint32_t);
using Int64QuerySetter = nsresult (NS_STDCALL nsINavHistoryQuery::*)(int64_t);
static void SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
                            BoolQuerySetter setter);
static void SetQueryKeyUint32(const nsCString& aValue,
                              nsINavHistoryQuery* aQuery,
                              Uint32QuerySetter setter);
static void SetQueryKeyInt64(const nsCString& aValue,
                             nsINavHistoryQuery* aQuery,
                             Int64QuerySetter setter);

// options setters
using BoolOptionsSetter =
    nsresult (NS_STDCALL nsINavHistoryQueryOptions::*)(bool);
using Uint32OptionsSetter =
    nsresult (NS_STDCALL nsINavHistoryQueryOptions::*)(uint32_t);
using Uint16OptionsSetter =
    nsresult (NS_STDCALL nsINavHistoryQueryOptions::*)(uint16_t);
static void SetOptionsKeyBool(const nsCString& aValue,
                              nsINavHistoryQueryOptions* aOptions,
                              BoolOptionsSetter setter);
static void SetOptionsKeyUint16(const nsCString& aValue,
                                nsINavHistoryQueryOptions* aOptions,
                                Uint16OptionsSetter setter);
static void SetOptionsKeyUint32(const nsCString& aValue,
                                nsINavHistoryQueryOptions* aOptions,
                                Uint32OptionsSetter setter);

// Components of a query string.
// Note that query strings are also generated in nsNavBookmarks::GetFolderURI
// for performance reasons, so if you change these values, change that, too.
#define QUERYKEY_BEGIN_TIME "beginTime"
#define QUERYKEY_BEGIN_TIME_REFERENCE "beginTimeRef"
#define QUERYKEY_END_TIME "endTime"
#define QUERYKEY_END_TIME_REFERENCE "endTimeRef"
#define QUERYKEY_SEARCH_TERMS "terms"
#define QUERYKEY_MIN_VISITS "minVisits"
#define QUERYKEY_MAX_VISITS "maxVisits"
#define QUERYKEY_DOMAIN_IS_HOST "domainIsHost"
#define QUERYKEY_DOMAIN "domain"
#define QUERYKEY_PARENT "parent"
#define QUERYKEY_URI "uri"
#define QUERYKEY_GROUP "group"
#define QUERYKEY_SORT "sort"
#define QUERYKEY_RESULT_TYPE "type"
#define QUERYKEY_EXCLUDE_ITEMS "excludeItems"
#define QUERYKEY_EXCLUDE_QUERIES "excludeQueries"
#define QUERYKEY_EXPAND_QUERIES "expandQueries"
#define QUERYKEY_FORCE_ORIGINAL_TITLE "originalTitle"
#define QUERYKEY_INCLUDE_HIDDEN "includeHidden"
#define QUERYKEY_MAX_RESULTS "maxResults"
#define QUERYKEY_QUERY_TYPE "queryType"
#define QUERYKEY_TAG "tag"
#define QUERYKEY_NOTTAGS "!tags"
#define QUERYKEY_ASYNC_ENABLED "asyncEnabled"
#define QUERYKEY_TRANSITION "transition"

inline void AppendAmpersandIfNonempty(nsACString& aString) {
  if (!aString.IsEmpty()) aString.Append('&');
}
inline void AppendInt16(nsACString& str, int16_t i) {
  nsAutoCString tmp;
  tmp.AppendInt(i);
  str.Append(tmp);
}
inline void AppendInt32(nsACString& str, int32_t i) {
  nsAutoCString tmp;
  tmp.AppendInt(i);
  str.Append(tmp);
}
inline void AppendInt64(nsACString& str, int64_t i) {
  nsCString tmp;
  tmp.AppendInt(i);
  str.Append(tmp);
}

NS_IMETHODIMP
nsNavHistory::QueryStringToQuery(const nsACString& aQueryString,
                                 nsINavHistoryQuery** _query,
                                 nsINavHistoryQueryOptions** _options) {
  return nsNavHistoryQuery::QueryStringToQuery(aQueryString, _query, _options);
}

NS_IMETHODIMP
nsNavHistory::QueryToQueryString(nsINavHistoryQuery* aQuery,
                                 nsINavHistoryQueryOptions* aOptions,
                                 nsACString& aQueryString) {
  NS_ENSURE_ARG(aQuery);
  NS_ENSURE_ARG(aOptions);

  RefPtr<nsNavHistoryQuery> query = do_QueryObject(aQuery);
  NS_ENSURE_STATE(query);
  RefPtr<nsNavHistoryQueryOptions> options = do_QueryObject(aOptions);
  NS_ENSURE_STATE(options);

  nsAutoCString queryString;
  bool hasIt;

  // begin time
  query->GetHasBeginTime(&hasIt);
  if (hasIt) {
    AppendInt64KeyValueIfNonzero(queryString,
                                 nsLiteralCString(QUERYKEY_BEGIN_TIME), query,
                                 &nsINavHistoryQuery::GetBeginTime);
    AppendUint32KeyValueIfNonzero(
        queryString, nsLiteralCString(QUERYKEY_BEGIN_TIME_REFERENCE), query,
        &nsINavHistoryQuery::GetBeginTimeReference);
  }

  // end time
  query->GetHasEndTime(&hasIt);
  if (hasIt) {
    AppendInt64KeyValueIfNonzero(queryString,
                                 nsLiteralCString(QUERYKEY_END_TIME), query,
                                 &nsINavHistoryQuery::GetEndTime);
    AppendUint32KeyValueIfNonzero(
        queryString, nsLiteralCString(QUERYKEY_END_TIME_REFERENCE), query,
        &nsINavHistoryQuery::GetEndTimeReference);
  }

  // search terms
  if (!query->SearchTerms().IsEmpty()) {
    const nsString& searchTerms = query->SearchTerms();
    nsCString escapedTerms;
    if (!NS_Escape(NS_ConvertUTF16toUTF8(searchTerms), escapedTerms,
                   url_XAlphas)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_SEARCH_TERMS "=");
    queryString += escapedTerms;
  }

  // min and max visits
  int32_t minVisits;
  if (NS_SUCCEEDED(query->GetMinVisits(&minVisits)) && minVisits >= 0) {
    AppendAmpersandIfNonempty(queryString);
    queryString.AppendLiteral(QUERYKEY_MIN_VISITS "=");
    AppendInt32(queryString, minVisits);
  }

  int32_t maxVisits;
  if (NS_SUCCEEDED(query->GetMaxVisits(&maxVisits)) && maxVisits >= 0) {
    AppendAmpersandIfNonempty(queryString);
    queryString.AppendLiteral(QUERYKEY_MAX_VISITS "=");
    AppendInt32(queryString, maxVisits);
  }

  // domain (+ is host), only call if hasDomain, which means non-IsVoid
  // this means we may get an empty string for the domain in the result,
  // which is valid
  if (!query->Domain().IsVoid()) {
    AppendBoolKeyValueIfTrue(queryString,
                             nsLiteralCString(QUERYKEY_DOMAIN_IS_HOST), query,
                             &nsINavHistoryQuery::GetDomainIsHost);
    const nsCString& domain = query->Domain();
    nsCString escapedDomain;
    bool success = NS_Escape(domain, escapedDomain, url_XAlphas);
    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);

    AppendAmpersandIfNonempty(queryString);
    queryString.AppendLiteral(QUERYKEY_DOMAIN "=");
    queryString.Append(escapedDomain);
  }

  // uri
  if (query->Uri()) {
    nsCOMPtr<nsIURI> uri = query->Uri();
    nsAutoCString uriSpec;
    nsresult rv = uri->GetSpec(uriSpec);
    NS_ENSURE_SUCCESS(rv, rv);
    nsAutoCString escaped;
    bool success = NS_Escape(uriSpec, escaped, url_XAlphas);
    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);

    AppendAmpersandIfNonempty(queryString);
    queryString.AppendLiteral(QUERYKEY_URI "=");
    queryString.Append(escaped);
  }

  // parents
  const nsTArray<nsCString>& parents = query->Parents();
  for (uint32_t i = 0; i < parents.Length(); ++i) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_PARENT "=");
    queryString += parents[i];
  }

  // tags
  const nsTArray<nsString>& tags = query->Tags();
  for (uint32_t i = 0; i < tags.Length(); ++i) {
    nsAutoCString escapedTag;
    if (!NS_Escape(NS_ConvertUTF16toUTF8(tags[i]), escapedTag, url_XAlphas)) {
      return NS_ERROR_OUT_OF_MEMORY;
    }

    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_TAG "=");
    queryString += escapedTag;
  }
  AppendBoolKeyValueIfTrue(queryString, nsLiteralCString(QUERYKEY_NOTTAGS),
                           query, &nsINavHistoryQuery::GetTagsAreNot);

  // transitions
  const nsTArray<uint32_t>& transitions = query->Transitions();
  for (uint32_t i = 0; i < transitions.Length(); ++i) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_TRANSITION "=");
    AppendInt64(queryString, transitions[i]);
  }

  // sorting
  if (options->SortingMode() != nsINavHistoryQueryOptions::SORT_BY_NONE) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_SORT "=");
    AppendInt16(queryString, static_cast<int16_t>(options->SortingMode()));
  }

  // result type
  if (options->ResultType() != nsINavHistoryQueryOptions::RESULTS_AS_URI) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_RESULT_TYPE "=");
    AppendInt16(queryString, static_cast<int16_t>(options->ResultType()));
  }

  // exclude items
  if (options->ExcludeItems()) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_EXCLUDE_ITEMS "=1");
  }

  // exclude queries
  if (options->ExcludeQueries()) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_EXCLUDE_QUERIES "=1");
  }

  // expand queries
  if (!options->ExpandQueries()) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_EXPAND_QUERIES "=0");
  }

  // include hidden
  if (options->IncludeHidden()) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_INCLUDE_HIDDEN "=1");
  }

  // max results
  if (options->MaxResults()) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_MAX_RESULTS "=");
    AppendInt32(queryString, static_cast<int32_t>(options->MaxResults()));
  }

  // queryType
  if (options->QueryType() != nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_QUERY_TYPE "=");
    AppendInt16(queryString, static_cast<int16_t>(options->QueryType()));
  }

  // async enabled
  if (options->AsyncEnabled()) {
    AppendAmpersandIfNonempty(queryString);
    queryString += nsLiteralCString(QUERYKEY_ASYNC_ENABLED "=1");
  }

  aQueryString.AssignLiteral("place:");
  aQueryString.Append(queryString);
  return NS_OK;
}

/* static */
nsresult nsNavHistory::TokensToQuery(const nsTArray<QueryKeyValuePair>& aTokens,
                                     nsNavHistoryQuery* aQuery,
                                     nsNavHistoryQueryOptions* aOptions) {
  nsresult rv;

  if (aTokens.Length() == 0) return NS_OK;

  nsTArray<nsCString> parents;
  nsTArray<nsString> tags;
  nsTArray<uint32_t> transitions;
  for (uint32_t i = 0; i < aTokens.Length(); i++) {
    const QueryKeyValuePair& kvp = aTokens[i];

    // begin time
    if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME)) {
      SetQueryKeyInt64(kvp.value, aQuery, &nsINavHistoryQuery::SetBeginTime);

      // begin time reference
    } else if (kvp.key.EqualsLiteral(QUERYKEY_BEGIN_TIME_REFERENCE)) {
      SetQueryKeyUint32(kvp.value, aQuery,
                        &nsINavHistoryQuery::SetBeginTimeReference);

      // end time
    } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME)) {
      SetQueryKeyInt64(kvp.value, aQuery, &nsINavHistoryQuery::SetEndTime);

      // end time reference
    } else if (kvp.key.EqualsLiteral(QUERYKEY_END_TIME_REFERENCE)) {
      SetQueryKeyUint32(kvp.value, aQuery,
                        &nsINavHistoryQuery::SetEndTimeReference);

      // search terms
    } else if (kvp.key.EqualsLiteral(QUERYKEY_SEARCH_TERMS)) {
      nsCString unescapedTerms = kvp.value;
      NS_UnescapeURL(unescapedTerms);  // modifies input
      rv = aQuery->SetSearchTerms(NS_ConvertUTF8toUTF16(unescapedTerms));
      NS_ENSURE_SUCCESS(rv, rv);

      // min visits
    } else if (kvp.key.EqualsLiteral(QUERYKEY_MIN_VISITS)) {
      int32_t visits = kvp.value.ToInteger(&rv);
      if (NS_SUCCEEDED(rv)) {
        aQuery->SetMinVisits(visits);
      } else {
        NS_WARNING("Bad number for minVisits in query");
      }

      // max visits
    } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_VISITS)) {
      int32_t visits = kvp.value.ToInteger(&rv);
      if (NS_SUCCEEDED(rv)) {
        aQuery->SetMaxVisits(visits);
      } else {
        NS_WARNING("Bad number for maxVisits in query");
      }

      // domainIsHost flag
    } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN_IS_HOST)) {
      SetQueryKeyBool(kvp.value, aQuery, &nsINavHistoryQuery::SetDomainIsHost);

      // domain string
    } else if (kvp.key.EqualsLiteral(QUERYKEY_DOMAIN)) {
      nsAutoCString unescapedDomain(kvp.value);
      NS_UnescapeURL(unescapedDomain);  // modifies input
      rv = aQuery->SetDomain(unescapedDomain);
      NS_ENSURE_SUCCESS(rv, rv);

      // parent folders (guids)
    } else if (kvp.key.EqualsLiteral(QUERYKEY_PARENT)) {
      parents.AppendElement(kvp.value);

      // uri
    } else if (kvp.key.EqualsLiteral(QUERYKEY_URI)) {
      nsAutoCString unescapedUri(kvp.value);
      NS_UnescapeURL(unescapedUri);  // modifies input
      nsCOMPtr<nsIURI> uri;
      nsresult rv = NS_NewURI(getter_AddRefs(uri), unescapedUri);
      if (NS_FAILED(rv)) {
        NS_WARNING("Unable to parse URI");
      }
      rv = aQuery->SetUri(uri);
      NS_ENSURE_SUCCESS(rv, rv);

      // tag
    } else if (kvp.key.EqualsLiteral(QUERYKEY_TAG)) {
      nsAutoCString unescaped(kvp.value);
      NS_UnescapeURL(unescaped);  // modifies input
      NS_ConvertUTF8toUTF16 tag(unescaped);
      if (!tags.Contains(tag)) {
        tags.AppendElement(tag);
      }

      // not tags
    } else if (kvp.key.EqualsLiteral(QUERYKEY_NOTTAGS)) {
      SetQueryKeyBool(kvp.value, aQuery, &nsINavHistoryQuery::SetTagsAreNot);

      // transition
    } else if (kvp.key.EqualsLiteral(QUERYKEY_TRANSITION)) {
      uint32_t transition = kvp.value.ToInteger(&rv);
      if (NS_SUCCEEDED(rv)) {
        if (!transitions.Contains(transition)) {
          transitions.AppendElement(transition);
        }
      } else {
        NS_WARNING("Invalid Int32 transition value.");
      }

      // sorting mode
    } else if (kvp.key.EqualsLiteral(QUERYKEY_SORT)) {
      SetOptionsKeyUint16(kvp.value, aOptions,
                          &nsINavHistoryQueryOptions::SetSortingMode);
      // result type
    } else if (kvp.key.EqualsLiteral(QUERYKEY_RESULT_TYPE)) {
      SetOptionsKeyUint16(kvp.value, aOptions,
                          &nsINavHistoryQueryOptions::SetResultType);

      // exclude items
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_ITEMS)) {
      SetOptionsKeyBool(kvp.value, aOptions,
                        &nsINavHistoryQueryOptions::SetExcludeItems);

      // exclude queries
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXCLUDE_QUERIES)) {
      SetOptionsKeyBool(kvp.value, aOptions,
                        &nsINavHistoryQueryOptions::SetExcludeQueries);

      // expand queries
    } else if (kvp.key.EqualsLiteral(QUERYKEY_EXPAND_QUERIES)) {
      SetOptionsKeyBool(kvp.value, aOptions,
                        &nsINavHistoryQueryOptions::SetExpandQueries);
      // include hidden
    } else if (kvp.key.EqualsLiteral(QUERYKEY_INCLUDE_HIDDEN)) {
      SetOptionsKeyBool(kvp.value, aOptions,
                        &nsINavHistoryQueryOptions::SetIncludeHidden);
      // max results
    } else if (kvp.key.EqualsLiteral(QUERYKEY_MAX_RESULTS)) {
      SetOptionsKeyUint32(kvp.value, aOptions,
                          &nsINavHistoryQueryOptions::SetMaxResults);
      // query type
    } else if (kvp.key.EqualsLiteral(QUERYKEY_QUERY_TYPE)) {
      SetOptionsKeyUint16(kvp.value, aOptions,
                          &nsINavHistoryQueryOptions::SetQueryType);
      // async enabled
    } else if (kvp.key.EqualsLiteral(QUERYKEY_ASYNC_ENABLED)) {
      SetOptionsKeyBool(kvp.value, aOptions,
                        &nsINavHistoryQueryOptions::SetAsyncEnabled);
      // unknown key
    } else {
      NS_WARNING("TokensToQueries(), ignoring unknown key: ");
      NS_WARNING(kvp.key.get());
    }
  }

  if (parents.Length() != 0) {
    rv = aQuery->SetParents(parents);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  if (tags.Length() > 0) {
    aQuery->SetTags(std::move(tags));
  }

  if (transitions.Length() > 0) {
    rv = aQuery->SetTransitions(transitions);
    NS_ENSURE_SUCCESS(rv, rv);
  }

  return NS_OK;
}

// ParseQueryBooleanString
//
//    Converts a 0/1 or true/false string into a bool

nsresult ParseQueryBooleanString(const nsCString& aString, bool* aValue) {
  if (aString.EqualsLiteral("1") || aString.EqualsLiteral("true")) {
    *aValue = true;
    return NS_OK;
  }
  if (aString.EqualsLiteral("0") || aString.EqualsLiteral("false")) {
    *aValue = false;
    return NS_OK;
  }
  return NS_ERROR_INVALID_ARG;
}

// nsINavHistoryQuery **********************************************************

NS_IMPL_ISUPPORTS(nsNavHistoryQuery, nsNavHistoryQuery, nsINavHistoryQuery)

// nsINavHistoryQuery::nsNavHistoryQuery
//
//    This must initialize the object such that the default values will cause
//    all history to be returned if this query is used. Then the caller can
//    just set the things it's interested in.

nsNavHistoryQuery::nsNavHistoryQuery()
    : mMinVisits(-1),
      mMaxVisits(-1),
      mBeginTime(0),
      mBeginTimeReference(TIME_RELATIVE_EPOCH),
      mEndTime(0),
      mEndTimeReference(TIME_RELATIVE_EPOCH),
      mDomainIsHost(false),
      mTagsAreNot(false) {
  // differentiate not set (IsVoid) from empty string (local files)
  mDomain.SetIsVoid(true);
}

nsNavHistoryQuery::nsNavHistoryQuery(const nsNavHistoryQuery& aOther)
    : mMinVisits(aOther.mMinVisits),
      mMaxVisits(aOther.mMaxVisits),
      mBeginTime(aOther.mBeginTime),
      mBeginTimeReference(aOther.mBeginTimeReference),
      mEndTime(aOther.mEndTime),
      mEndTimeReference(aOther.mEndTimeReference),
      mSearchTerms(aOther.mSearchTerms),
      mDomainIsHost(aOther.mDomainIsHost),
      mDomain(aOther.mDomain),
      mUri(aOther.mUri),
      mParents(aOther.mParents.Clone()),
      mTags(aOther.mTags.Clone()),
      mTagsAreNot(aOther.mTagsAreNot),
      mTransitions(aOther.mTransitions.Clone()) {}

NS_IMETHODIMP nsNavHistoryQuery::GetBeginTime(PRTime* aBeginTime) {
  *aBeginTime = mBeginTime;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetBeginTime(PRTime aBeginTime) {
  mBeginTime = aBeginTime;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetBeginTimeReference(uint32_t* _retval) {
  *_retval = mBeginTimeReference;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetBeginTimeReference(uint32_t aReference) {
  if (aReference > TIME_RELATIVE_NOW) return NS_ERROR_INVALID_ARG;
  mBeginTimeReference = aReference;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetHasBeginTime(bool* _retval) {
  *_retval = !(mBeginTimeReference == TIME_RELATIVE_EPOCH && mBeginTime == 0);
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteBeginTime(PRTime* _retval) {
  *_retval = nsNavHistory::NormalizeTime(mBeginTimeReference, mBeginTime);
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetEndTime(PRTime* aEndTime) {
  *aEndTime = mEndTime;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetEndTime(PRTime aEndTime) {
  mEndTime = aEndTime;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetEndTimeReference(uint32_t* _retval) {
  *_retval = mEndTimeReference;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetEndTimeReference(uint32_t aReference) {
  if (aReference > TIME_RELATIVE_NOW) return NS_ERROR_INVALID_ARG;
  mEndTimeReference = aReference;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetHasEndTime(bool* _retval) {
  *_retval = !(mEndTimeReference == TIME_RELATIVE_EPOCH && mEndTime == 0);
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetAbsoluteEndTime(PRTime* _retval) {
  *_retval = nsNavHistory::NormalizeTime(mEndTimeReference, mEndTime);
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetSearchTerms(nsAString& aSearchTerms) {
  aSearchTerms = mSearchTerms;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetSearchTerms(const nsAString& aSearchTerms) {
  mSearchTerms = aSearchTerms;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::GetHasSearchTerms(bool* _retval) {
  *_retval = (!mSearchTerms.IsEmpty());
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetMinVisits(int32_t* _retval) {
  NS_ENSURE_ARG_POINTER(_retval);
  *_retval = mMinVisits;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetMinVisits(int32_t aVisits) {
  mMinVisits = aVisits;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetMaxVisits(int32_t* _retval) {
  NS_ENSURE_ARG_POINTER(_retval);
  *_retval = mMaxVisits;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetMaxVisits(int32_t aVisits) {
  mMaxVisits = aVisits;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetDomainIsHost(bool* aDomainIsHost) {
  *aDomainIsHost = mDomainIsHost;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetDomainIsHost(bool aDomainIsHost) {
  mDomainIsHost = aDomainIsHost;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetDomain(nsACString& aDomain) {
  aDomain = mDomain;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetDomain(const nsACString& aDomain) {
  mDomain = aDomain;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::GetHasDomain(bool* _retval) {
  // note that empty but not void is still a valid query (local files)
  *_retval = (!mDomain.IsVoid());
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetUri(nsIURI** aUri) {
  NS_IF_ADDREF(*aUri = mUri);
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::SetUri(nsIURI* aUri) {
  mUri = aUri;
  return NS_OK;
}
NS_IMETHODIMP nsNavHistoryQuery::GetHasUri(bool* aHasUri) {
  *aHasUri = (mUri != nullptr);
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetTags(nsIVariant** aTags) {
  NS_ENSURE_ARG_POINTER(aTags);

  RefPtr<nsVariant> out = new nsVariant();

  uint32_t arrayLen = mTags.Length();

  nsresult rv;
  if (arrayLen == 0) {
    rv = out->SetAsEmptyArray();
  } else {
    // Note: The resulting nsIVariant dupes both the array and its elements.
    const char16_t** array = reinterpret_cast<const char16_t**>(
        moz_xmalloc(arrayLen * sizeof(char16_t*)));
    for (uint32_t i = 0; i < arrayLen; ++i) {
      array[i] = mTags[i].get();
    }

    rv = out->SetAsArray(nsIDataType::VTYPE_WCHAR_STR, nullptr, arrayLen,
                         reinterpret_cast<void*>(array));
    free(array);
  }
  NS_ENSURE_SUCCESS(rv, rv);

  out.forget(aTags);
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::SetTags(nsIVariant* aTags) {
  NS_ENSURE_ARG(aTags);

  uint16_t dataType = aTags->GetDataType();

  // Caller passed in empty array.  Easy -- clear our mTags array and return.
  if (dataType == nsIDataType::VTYPE_EMPTY_ARRAY) {
    mTags.Clear();
    return NS_OK;
  }

  // Before we go any further, make sure caller passed in an array.
  NS_ENSURE_TRUE(dataType == nsIDataType::VTYPE_ARRAY, NS_ERROR_ILLEGAL_VALUE);

  uint16_t eltType;
  nsIID eltIID;
  uint32_t arrayLen;
  void* array;

  // Convert the nsIVariant to an array.  We own the resulting buffer and its
  // elements.
  nsresult rv = aTags->GetAsArray(&eltType, &eltIID, &arrayLen, &array);
  NS_ENSURE_SUCCESS(rv, rv);

  // If element type is not wstring, thanks a lot.  Your memory die now.
  if (eltType != nsIDataType::VTYPE_WCHAR_STR) {
    switch (eltType) {
      case nsIDataType::VTYPE_ID:
      case nsIDataType::VTYPE_CHAR_STR: {
        char** charArray = reinterpret_cast<char**>(array);
        for (uint32_t i = 0; i < arrayLen; ++i) {
          if (charArray[i]) free(charArray[i]);
        }
      } break;
      case nsIDataType::VTYPE_INTERFACE:
      case nsIDataType::VTYPE_INTERFACE_IS: {
        nsISupports** supportsArray = reinterpret_cast<nsISupports**>(array);
        for (uint32_t i = 0; i < arrayLen; ++i) {
          NS_IF_RELEASE(supportsArray[i]);
        }
      } break;
        // The other types are primitives that do not need to be freed.
    }
    free(array);
    return NS_ERROR_ILLEGAL_VALUE;
  }

  char16_t** tags = reinterpret_cast<char16_t**>(array);
  mTags.Clear();

  // Finally, add each passed-in tag to our mTags array and then sort it.
  for (uint32_t i = 0; i < arrayLen; ++i) {
    // Don't allow nulls.
    if (!tags[i]) {
      free(tags);
      return NS_ERROR_ILLEGAL_VALUE;
    }

    nsDependentString tag(tags[i]);

    // Don't store duplicate tags.  This isn't just to save memory or to be
    // fancy; the SQL that's built from the tags relies on no dupes.
    if (!mTags.Contains(tag)) {
      // XXX(Bug 1631371) Check if this should use a fallible operation as it
      // pretended earlier.
      mTags.AppendElement(tag);
    }
    free(tags[i]);
  }
  free(tags);

  mTags.Sort();

  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetTagsAreNot(bool* aTagsAreNot) {
  NS_ENSURE_ARG_POINTER(aTagsAreNot);
  *aTagsAreNot = mTagsAreNot;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::SetTagsAreNot(bool aTagsAreNot) {
  mTagsAreNot = aTagsAreNot;
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetParents(nsTArray<nsCString>& aGuids) {
  aGuids = mParents.Clone();
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetParentCount(uint32_t* aGuidCount) {
  *aGuidCount = mParents.Length();
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::SetParents(const nsTArray<nsCString>& aGuids) {
  mParents.Clear();
  if (!mParents.Assign(aGuids, fallible)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }

  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetTransitions(
    nsTArray<uint32_t>& aTransitions) {
  aTransitions = mTransitions.Clone();
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::GetTransitionCount(uint32_t* aCount) {
  *aCount = mTransitions.Length();
  return NS_OK;
}

NS_IMETHODIMP nsNavHistoryQuery::SetTransitions(
    const nsTArray<uint32_t>& aTransitions) {
  if (!mTransitions.Assign(aTransitions, fallible)) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  return NS_OK;
}

NS_IMETHODIMP
nsNavHistoryQuery::Clone(nsINavHistoryQuery** _clone) {
  nsNavHistoryQuery* clone = nullptr;
  Unused << Clone(&clone);
  *_clone = clone;
  return NS_OK;
}

nsresult nsNavHistoryQuery::Clone(nsNavHistoryQuery** _clone) {
  *_clone = nullptr;
  RefPtr<nsNavHistoryQuery> clone = new nsNavHistoryQuery(*this);
  clone.forget(_clone);
  return NS_OK;
}

/* static */
nsresult nsNavHistoryQuery::QueryStringToQuery(
    const nsACString& aQueryString, nsINavHistoryQuery** _query,
    nsINavHistoryQueryOptions** _options) {
  NS_ENSURE_ARG_POINTER(_query);
  NS_ENSURE_ARG_POINTER(_options);

  nsTArray<QueryKeyValuePair> tokens;
  nsresult rv = TokenizeQueryString(aQueryString, &tokens);
  NS_ENSURE_SUCCESS(rv, rv);

  RefPtr<nsNavHistoryQueryOptions> options = new nsNavHistoryQueryOptions();
  RefPtr<nsNavHistoryQuery> query = new nsNavHistoryQuery();
  rv = nsNavHistory::TokensToQuery(tokens, query, options);
  MOZ_ASSERT(NS_SUCCEEDED(rv), "The query string should be valid");
  if (NS_FAILED(rv)) {
    NS_WARNING("Unable to parse the query string: ");
    NS_WARNING(PromiseFlatCString(aQueryString).get());
  }

  options.forget(_options);
  query.forget(_query);
  return NS_OK;
}

// nsNavHistoryQueryOptions
NS_IMPL_ISUPPORTS(nsNavHistoryQueryOptions, nsNavHistoryQueryOptions,
                  nsINavHistoryQueryOptions)

nsNavHistoryQueryOptions::nsNavHistoryQueryOptions()
    : mSort(0),
      mResultType(0),
      mExcludeItems(false),
      mExcludeQueries(false),
      mExpandQueries(true),
      mIncludeHidden(false),
      mMaxResults(0),
      mQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY),
      mAsyncEnabled(false) {}

nsNavHistoryQueryOptions::nsNavHistoryQueryOptions(
    const nsNavHistoryQueryOptions& other)
    : mSort(other.mSort),
      mResultType(other.mResultType),
      mExcludeItems(other.mExcludeItems),
      mExcludeQueries(other.mExcludeQueries),
      mExpandQueries(other.mExpandQueries),
      mIncludeHidden(other.mIncludeHidden),
      mMaxResults(other.mMaxResults),
      mQueryType(other.mQueryType),
      mAsyncEnabled(other.mAsyncEnabled) {}

// sortingMode
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetSortingMode(uint16_t* aMode) {
  *aMode = mSort;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetSortingMode(uint16_t aMode) {
  if (aMode > SORT_BY_FRECENCY_DESCENDING) return NS_ERROR_INVALID_ARG;
  mSort = aMode;
  return NS_OK;
}

// resultType
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetResultType(uint16_t* aType) {
  *aType = mResultType;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetResultType(uint16_t aType) {
  if (aType > RESULTS_AS_LEFT_PANE_QUERY) return NS_ERROR_INVALID_ARG;
  // Tag queries, containers and the roots query are bookmarks related, so we
  // set the QueryType accordingly.
  if (aType == RESULTS_AS_TAGS_ROOT || aType == RESULTS_AS_ROOTS_QUERY ||
      aType == RESULTS_AS_LEFT_PANE_QUERY) {
    mQueryType = QUERY_TYPE_BOOKMARKS;
  }
  mResultType = aType;
  return NS_OK;
}

// excludeItems
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetExcludeItems(bool* aExclude) {
  *aExclude = mExcludeItems;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetExcludeItems(bool aExclude) {
  mExcludeItems = aExclude;
  return NS_OK;
}

// excludeQueries
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetExcludeQueries(bool* aExclude) {
  *aExclude = mExcludeQueries;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetExcludeQueries(bool aExclude) {
  mExcludeQueries = aExclude;
  return NS_OK;
}
// expandQueries
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetExpandQueries(bool* aExpand) {
  *aExpand = mExpandQueries;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetExpandQueries(bool aExpand) {
  mExpandQueries = aExpand;
  return NS_OK;
}

// includeHidden
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetIncludeHidden(bool* aIncludeHidden) {
  *aIncludeHidden = mIncludeHidden;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetIncludeHidden(bool aIncludeHidden) {
  mIncludeHidden = aIncludeHidden;
  return NS_OK;
}

// maxResults
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetMaxResults(uint32_t* aMaxResults) {
  *aMaxResults = mMaxResults;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetMaxResults(uint32_t aMaxResults) {
  mMaxResults = aMaxResults;
  return NS_OK;
}

// queryType
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetQueryType(uint16_t* _retval) {
  *_retval = mQueryType;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetQueryType(uint16_t aQueryType) {
  // Tag query and containers are forced to QUERY_TYPE_BOOKMARKS when the
  // resultType is set.
  if (mResultType == RESULTS_AS_TAGS_ROOT ||
      mResultType == RESULTS_AS_LEFT_PANE_QUERY ||
      mResultType == RESULTS_AS_ROOTS_QUERY) {
    return NS_OK;
  }
  mQueryType = aQueryType;
  return NS_OK;
}

// asyncEnabled
NS_IMETHODIMP
nsNavHistoryQueryOptions::GetAsyncEnabled(bool* _asyncEnabled) {
  *_asyncEnabled = mAsyncEnabled;
  return NS_OK;
}
NS_IMETHODIMP
nsNavHistoryQueryOptions::SetAsyncEnabled(bool aAsyncEnabled) {
  mAsyncEnabled = aAsyncEnabled;
  return NS_OK;
}

NS_IMETHODIMP
nsNavHistoryQueryOptions::Clone(nsINavHistoryQueryOptions** _clone) {
  nsNavHistoryQueryOptions* clone = nullptr;
  Unused << Clone(&clone);
  *_clone = clone;
  return NS_OK;
}

nsresult nsNavHistoryQueryOptions::Clone(nsNavHistoryQueryOptions** _clone) {
  *_clone = nullptr;
  RefPtr<nsNavHistoryQueryOptions> clone = new nsNavHistoryQueryOptions(*this);
  clone.forget(_clone);
  return NS_OK;
}

// AppendBoolKeyValueIfTrue

void  // static
AppendBoolKeyValueIfTrue(nsACString& aString, const nsCString& aName,
                         nsINavHistoryQuery* aQuery, BoolQueryGetter getter) {
  bool value;
  DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
  NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting boolean value");
  if (value) {
    AppendAmpersandIfNonempty(aString);
    aString += aName;
    aString.AppendLiteral("=1");
  }
}

// AppendUint32KeyValueIfNonzero

void  // static
AppendUint32KeyValueIfNonzero(nsACString& aString, const nsCString& aName,
                              nsINavHistoryQuery* aQuery,
                              Uint32QueryGetter getter) {
  uint32_t value;
  DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
  NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting value");
  if (value) {
    AppendAmpersandIfNonempty(aString);
    aString += aName;

    // AppendInt requires a concrete string
    nsAutoCString appendMe("=");
    appendMe.AppendInt(value);
    aString.Append(appendMe);
  }
}

// AppendInt64KeyValueIfNonzero

void  // static
AppendInt64KeyValueIfNonzero(nsACString& aString, const nsCString& aName,
                             nsINavHistoryQuery* aQuery,
                             Int64QueryGetter getter) {
  PRTime value;
  DebugOnly<nsresult> rv = (aQuery->*getter)(&value);
  NS_ASSERTION(NS_SUCCEEDED(rv), "Failure getting value");
  if (value) {
    AppendAmpersandIfNonempty(aString);
    aString += aName;
    nsAutoCString appendMe("=");
    appendMe.AppendInt(static_cast<int64_t>(value));
    aString.Append(appendMe);
  }
}

// SetQuery/OptionsKeyBool

void  // static
SetQueryKeyBool(const nsCString& aValue, nsINavHistoryQuery* aQuery,
                BoolQuerySetter setter) {
  bool value;
  nsresult rv = ParseQueryBooleanString(aValue, &value);
  if (NS_SUCCEEDED(rv)) {
    rv = (aQuery->*setter)(value);
    if (NS_FAILED(rv)) {
      NS_WARNING("Error setting boolean key value");
    }
  } else {
    NS_WARNING("Invalid boolean key value in query string.");
  }
}
void  // static
SetOptionsKeyBool(const nsCString& aValue, nsINavHistoryQueryOptions* aOptions,
                  BoolOptionsSetter setter) {
  bool value = false;
  nsresult rv = ParseQueryBooleanString(aValue, &value);
  if (NS_SUCCEEDED(rv)) {
    rv = (aOptions->*setter)(value);
    if (NS_FAILED(rv)) {
      NS_WARNING("Error setting boolean key value");
    }
  } else {
    NS_WARNING("Invalid boolean key value in query string.");
  }
}

// SetQuery/OptionsKeyUint32

void  // static
SetQueryKeyUint32(const nsCString& aValue, nsINavHistoryQuery* aQuery,
                  Uint32QuerySetter setter) {
  nsresult rv;
  uint32_t value = aValue.ToInteger(&rv);
  if (NS_SUCCEEDED(rv)) {
    rv = (aQuery->*setter)(value);
    if (NS_FAILED(rv)) {
      NS_WARNING("Error setting Int32 key value");
    }
  } else {
    NS_WARNING("Invalid Int32 key value in query string.");
  }
}
void  // static
SetOptionsKeyUint32(const nsCString& aValue,
                    nsINavHistoryQueryOptions* aOptions,
                    Uint32OptionsSetter setter) {
  nsresult rv;
  uint32_t value = aValue.ToInteger(&rv);
  if (NS_SUCCEEDED(rv)) {
    rv = (aOptions->*setter)(value);
    if (NS_FAILED(rv)) {
      NS_WARNING("Error setting Int32 key value");
    }
  } else {
    NS_WARNING("Invalid Int32 key value in query string.");
  }
}

void  // static
SetOptionsKeyUint16(const nsCString& aValue,
                    nsINavHistoryQueryOptions* aOptions,
                    Uint16OptionsSetter setter) {
  nsresult rv;
  uint16_t value = static_cast<uint16_t>(aValue.ToInteger(&rv));
  if (NS_SUCCEEDED(rv)) {
    rv = (aOptions->*setter)(value);
    if (NS_FAILED(rv)) {
      NS_WARNING("Error setting Int16 key value");
    }
  } else {
    NS_WARNING("Invalid Int16 key value in query string.");
  }
}

// SetQueryKeyInt64

void SetQueryKeyInt64(const nsCString& aValue, nsINavHistoryQuery* aQuery,
                      Int64QuerySetter setter) {
  nsresult rv;
  int64_t value;
  if (PR_sscanf(aValue.get(), "%lld", &value) == 1) {
    rv = (aQuery->*setter)(value);
    if (NS_FAILED(rv)) {
      NS_WARNING("Error setting Int64 key value");
    }
  } else {
    NS_WARNING("Invalid Int64 value in query string.");
  }
}

Messung V0.5
C=89 H=91 G=89

¤ Dauer der Verarbeitung: 0.16 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge