зеркало из https://github.com/mozilla/pjs.git
Bug 320466 r=annie.sullivan Move Autocomplete code from nsNavHistory.cpp to new
file nsNavHistoryAutoComplete.cpp (no changes to code) This file was copied in CVS from the following location: mozilla/browser/components/places/src/nsNavHistoryAutoComplete.cpp Original committer: brettw%gmail.com Original revision: 1.1 Original date: 2005/12/16 00:16:14
This commit is contained in:
Родитель
226b2c6769
Коммит
b08d3344e2
|
@ -0,0 +1,506 @@
|
||||||
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Places code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is
|
||||||
|
* Google Inc.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Brett Wilson <brettw@gmail.com>
|
||||||
|
* Joe Hewitt <hewitt@netscape.com>
|
||||||
|
* Blake Ross <blaker@netscape.com>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include "nsNavHistory.h"
|
||||||
|
|
||||||
|
#include "mozIStorageService.h"
|
||||||
|
#include "mozIStorageConnection.h"
|
||||||
|
#include "mozIStorageValueArray.h"
|
||||||
|
#include "mozIStorageStatement.h"
|
||||||
|
#include "mozIStorageFunction.h"
|
||||||
|
#include "mozStorageCID.h"
|
||||||
|
#include "mozStorageHelper.h"
|
||||||
|
|
||||||
|
#define NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID \
|
||||||
|
"@mozilla.org/autocomplete/simple-result;1"
|
||||||
|
|
||||||
|
|
||||||
|
PRInt32 ComputeAutoCompletePriority(const nsAString& aUrl, PRInt32 aVisitCount,
|
||||||
|
PRBool aWasTyped);
|
||||||
|
|
||||||
|
// nsIAutoCompleteSearch *******************************************************
|
||||||
|
|
||||||
|
|
||||||
|
// AutoCompleteIntermediateResult/Set
|
||||||
|
//
|
||||||
|
// This class holds intermediate autocomplete results so that they can be
|
||||||
|
// sorted. This list is then handed off to a result using FillResult. The
|
||||||
|
// major reason for this is so that we can use nsArray's sorting functions,
|
||||||
|
// not use COM, yet have well-defined lifetimes for the objects. This uses
|
||||||
|
// a void array, but makes sure to delete the objects on desctruction.
|
||||||
|
|
||||||
|
struct AutoCompleteIntermediateResult
|
||||||
|
{
|
||||||
|
nsString url;
|
||||||
|
nsString title;
|
||||||
|
PRUint32 priority;
|
||||||
|
};
|
||||||
|
class AutoCompleteIntermediateResultSet
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
AutoCompleteIntermediateResultSet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~AutoCompleteIntermediateResultSet()
|
||||||
|
{
|
||||||
|
for (PRInt32 i = 0; i < mArray.Count(); i ++) {
|
||||||
|
AutoCompleteIntermediateResult* cur = NS_STATIC_CAST(
|
||||||
|
AutoCompleteIntermediateResult*, mArray[i]);
|
||||||
|
delete cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PRBool Add(const nsString& aURL, const nsString& aTitle, PRInt32 aPriority)
|
||||||
|
{
|
||||||
|
AutoCompleteIntermediateResult* cur = new AutoCompleteIntermediateResult;
|
||||||
|
if (! cur)
|
||||||
|
return PR_FALSE;
|
||||||
|
cur->url = aURL;
|
||||||
|
cur->title = aTitle;
|
||||||
|
cur->priority = aPriority;
|
||||||
|
mArray.AppendElement(cur);
|
||||||
|
return PR_TRUE;
|
||||||
|
}
|
||||||
|
void Sort(nsNavHistory* navHistory)
|
||||||
|
{
|
||||||
|
mArray.Sort(nsNavHistory::AutoCompleteSortComparison, navHistory);
|
||||||
|
}
|
||||||
|
nsresult FillResult(nsIAutoCompleteSimpleResult* aResult)
|
||||||
|
{
|
||||||
|
for (PRInt32 i = 0; i < mArray.Count(); i ++)
|
||||||
|
{
|
||||||
|
AutoCompleteIntermediateResult* cur = NS_STATIC_CAST(
|
||||||
|
AutoCompleteIntermediateResult*, mArray[i]);
|
||||||
|
nsresult rv = aResult->AppendMatch(cur->url, cur->title);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
nsVoidArray mArray;
|
||||||
|
};
|
||||||
|
|
||||||
|
// nsNavHistory::StartSearch
|
||||||
|
//
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsNavHistory::StartSearch(const nsAString & aSearchString,
|
||||||
|
const nsAString & aSearchParam,
|
||||||
|
nsIAutoCompleteResult *aPreviousResult,
|
||||||
|
nsIAutoCompleteObserver *aListener)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
|
||||||
|
NS_ENSURE_ARG_POINTER(aListener);
|
||||||
|
|
||||||
|
nsCOMPtr<nsIAutoCompleteSimpleResult> result =
|
||||||
|
do_CreateInstance(NS_AUTOCOMPLETESIMPLERESULT_CONTRACTID, &rv);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
result->SetSearchString(aSearchString);
|
||||||
|
|
||||||
|
PRBool usePrevious = (aPreviousResult != nsnull);
|
||||||
|
|
||||||
|
// throw away previous results if the search string is empty after it has had
|
||||||
|
// the prefixes removed: if the user types "http://" throw away the search
|
||||||
|
// for "http:/" and start fresh with the new query.
|
||||||
|
if (usePrevious) {
|
||||||
|
nsAutoString cut(aSearchString);
|
||||||
|
AutoCompleteCutPrefix(&cut, nsnull);
|
||||||
|
if (cut.IsEmpty())
|
||||||
|
usePrevious = PR_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// throw away previous results if the new string doesn't begin with the
|
||||||
|
// previous search string
|
||||||
|
if (usePrevious) {
|
||||||
|
nsAutoString previousSearch;
|
||||||
|
aPreviousResult->GetSearchString(previousSearch);
|
||||||
|
if (previousSearch.Length() > aSearchString.Length() ||
|
||||||
|
!Substring(aSearchString, 0, previousSearch.Length()).Equals(previousSearch)) {
|
||||||
|
usePrevious = PR_FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aSearchString.IsEmpty()) {
|
||||||
|
rv = AutoCompleteTypedSearch(result);
|
||||||
|
} else if (usePrevious) {
|
||||||
|
rv = AutoCompleteRefineHistorySearch(aSearchString, aPreviousResult, result);
|
||||||
|
} else {
|
||||||
|
rv = AutoCompleteFullHistorySearch(aSearchString, result);
|
||||||
|
}
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// Determine the result of the search
|
||||||
|
PRUint32 count;
|
||||||
|
result->GetMatchCount(&count);
|
||||||
|
if (count > 0) {
|
||||||
|
result->SetSearchResult(nsIAutoCompleteResult::RESULT_SUCCESS);
|
||||||
|
result->SetDefaultIndex(0);
|
||||||
|
} else {
|
||||||
|
result->SetSearchResult(nsIAutoCompleteResult::RESULT_NOMATCH);
|
||||||
|
result->SetDefaultIndex(-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
aListener->OnSearchResult(this, result);
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::StopSearch
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsNavHistory::StopSearch()
|
||||||
|
{
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::AutoCompleteTypedSearch
|
||||||
|
//
|
||||||
|
// Called when there is no search string. This happens when you press
|
||||||
|
// down arrow from the URL bar: the most recent things you typed are listed.
|
||||||
|
//
|
||||||
|
// Ordering here is simpler because there are no boosts for typing, and there
|
||||||
|
// is no URL information to use. The ordering just comes out of the DB by
|
||||||
|
// visit count (primary) and time since last visited (secondary).
|
||||||
|
|
||||||
|
nsresult nsNavHistory::AutoCompleteTypedSearch(
|
||||||
|
nsIAutoCompleteSimpleResult* result)
|
||||||
|
{
|
||||||
|
// note: need to test against hidden = 1 since the column can also be null
|
||||||
|
// (meaning not hidden)
|
||||||
|
nsCOMPtr<mozIStorageStatement> dbSelectStatement;
|
||||||
|
nsresult rv = mDBConn->CreateStatement(
|
||||||
|
NS_LITERAL_CSTRING("SELECT url,title FROM moz_history WHERE typed = 1 AND hidden <> 1 ORDER BY visit_count DESC LIMIT 1000"),
|
||||||
|
getter_AddRefs(dbSelectStatement));
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
PRBool hasMore = PR_FALSE;
|
||||||
|
while (NS_SUCCEEDED(dbSelectStatement->ExecuteStep(&hasMore)) && hasMore) {
|
||||||
|
nsAutoString entryURL, entryTitle;
|
||||||
|
dbSelectStatement->GetString(0, entryURL);
|
||||||
|
dbSelectStatement->GetString(1, entryTitle);
|
||||||
|
|
||||||
|
rv = result->AppendMatch(entryURL, entryTitle);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::AutoCompleteFullHistorySearch
|
||||||
|
//
|
||||||
|
// A brute-force search of the entire history. This matches the given input
|
||||||
|
// with every possible history entry, and sorts them by likelihood.
|
||||||
|
//
|
||||||
|
// This may be slow for people on slow computers with large histories.
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsNavHistory::AutoCompleteFullHistorySearch(const nsAString& aSearchString,
|
||||||
|
nsIAutoCompleteSimpleResult* result)
|
||||||
|
{
|
||||||
|
// figure out whether any known prefixes are present in the search string
|
||||||
|
// so we know not to ignore them when comparing results later
|
||||||
|
AutoCompleteExclude exclude;
|
||||||
|
AutoCompleteGetExcludeInfo(aSearchString, &exclude);
|
||||||
|
|
||||||
|
mozStorageStatementScoper scoper(mDBFullAutoComplete);
|
||||||
|
nsresult rv = mDBFullAutoComplete->BindInt32Parameter(0, mAutoCompleteMaxCount);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
|
||||||
|
// load the intermediate result so it can be sorted
|
||||||
|
AutoCompleteIntermediateResultSet resultSet;
|
||||||
|
PRBool hasMore = PR_FALSE;
|
||||||
|
while (NS_SUCCEEDED(mDBFullAutoComplete->ExecuteStep(&hasMore)) && hasMore) {
|
||||||
|
|
||||||
|
PRBool typed = mDBFullAutoComplete->AsInt32(kAutoCompleteIndex_Typed);
|
||||||
|
if (!typed) {
|
||||||
|
if (mAutoCompleteOnlyTyped)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsAutoString entryurl;
|
||||||
|
mDBFullAutoComplete->GetString(kAutoCompleteIndex_URL, entryurl);
|
||||||
|
if (AutoCompleteCompare(entryurl, aSearchString, exclude)) {
|
||||||
|
nsAutoString entrytitle;
|
||||||
|
rv = mDBFullAutoComplete->GetString(kAutoCompleteIndex_Title, entrytitle);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
PRInt32 priority = ComputeAutoCompletePriority(entryurl,
|
||||||
|
mDBFullAutoComplete->AsInt32(kAutoCompleteIndex_VisitCount),
|
||||||
|
typed);
|
||||||
|
|
||||||
|
if (! resultSet.Add(entryurl, entrytitle, priority))
|
||||||
|
return NS_ERROR_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sort and populate the final result
|
||||||
|
resultSet.Sort(this);
|
||||||
|
return resultSet.FillResult(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::AutoCompleteRefineHistorySearch
|
||||||
|
//
|
||||||
|
// Called when a previous autocomplete result exists and we are adding to
|
||||||
|
// the query (making it more specific). The list is already nicely sorted,
|
||||||
|
// so we can just remove all the old elements that DON'T match the new query.
|
||||||
|
|
||||||
|
nsresult
|
||||||
|
nsNavHistory::AutoCompleteRefineHistorySearch(
|
||||||
|
const nsAString& aSearchString,
|
||||||
|
nsIAutoCompleteResult* aPreviousResult,
|
||||||
|
nsIAutoCompleteSimpleResult* aNewResult)
|
||||||
|
{
|
||||||
|
// figure out whether any known prefixes are present in the search string
|
||||||
|
// so we know not to ignore them when comparing results later
|
||||||
|
AutoCompleteExclude exclude;
|
||||||
|
AutoCompleteGetExcludeInfo(aSearchString, &exclude);
|
||||||
|
|
||||||
|
PRUint32 matchCount;
|
||||||
|
aPreviousResult->GetMatchCount(&matchCount);
|
||||||
|
|
||||||
|
for (PRUint32 i = 0; i < matchCount; i ++) {
|
||||||
|
nsAutoString cururl;
|
||||||
|
nsresult rv = aPreviousResult->GetValueAt(i, cururl);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
if (AutoCompleteCompare(cururl, aSearchString, exclude)) {
|
||||||
|
nsAutoString curcomment;
|
||||||
|
rv = aPreviousResult->GetCommentAt(i, curcomment);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
rv = aNewResult->AppendMatch(cururl, curcomment);
|
||||||
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::AutoCompleteGetExcludeInfo
|
||||||
|
//
|
||||||
|
// If aURL begins with a protocol or domain prefix from our lists, then mark
|
||||||
|
// their index in an AutocompleteExclude struct.
|
||||||
|
|
||||||
|
void
|
||||||
|
nsNavHistory::AutoCompleteGetExcludeInfo(const nsAString& aURL,
|
||||||
|
AutoCompleteExclude* aExclude)
|
||||||
|
{
|
||||||
|
aExclude->schemePrefix = -1;
|
||||||
|
aExclude->hostnamePrefix = -1;
|
||||||
|
|
||||||
|
PRInt32 index = 0;
|
||||||
|
PRInt32 i;
|
||||||
|
for (i = 0; i < mIgnoreSchemes.Count(); ++i) {
|
||||||
|
nsString* string = mIgnoreSchemes.StringAt(i);
|
||||||
|
if (Substring(aURL, 0, string->Length()).Equals(*string)) {
|
||||||
|
aExclude->schemePrefix = i;
|
||||||
|
index = string->Length();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < mIgnoreHostnames.Count(); ++i) {
|
||||||
|
nsString* string = mIgnoreHostnames.StringAt(i);
|
||||||
|
if (Substring(aURL, index, string->Length()).Equals(*string)) {
|
||||||
|
aExclude->hostnamePrefix = i;
|
||||||
|
index += string->Length();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
aExclude->postPrefixOffset = index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::AutoCompleteCutPrefix
|
||||||
|
//
|
||||||
|
// Cut any protocol and domain prefixes from aURL, except for those which
|
||||||
|
// are specified in aExclude.
|
||||||
|
//
|
||||||
|
// aExclude can be NULL to cut all possible prefixes
|
||||||
|
//
|
||||||
|
// This comparison is case-sensitive. Therefore, it assumes that aUserURL
|
||||||
|
// is a potential URL whose host name is in all lower case.
|
||||||
|
//
|
||||||
|
// The aExclude identifies which prefixes were present in the user's typed
|
||||||
|
// entry, which we DON'T want to cut so that it can match the user input.
|
||||||
|
// For example. Typed "xyz.com" matches "xyz.com" AND "http://www.xyz.com"
|
||||||
|
// but "www.xyz.com" still matches "www.xyz.com".
|
||||||
|
|
||||||
|
void
|
||||||
|
nsNavHistory::AutoCompleteCutPrefix(nsString* aURL,
|
||||||
|
const AutoCompleteExclude* aExclude)
|
||||||
|
{
|
||||||
|
PRInt32 idx = 0;
|
||||||
|
PRInt32 i;
|
||||||
|
for (i = 0; i < mIgnoreSchemes.Count(); ++i) {
|
||||||
|
if (aExclude && i == aExclude->schemePrefix)
|
||||||
|
continue;
|
||||||
|
nsString* string = mIgnoreSchemes.StringAt(i);
|
||||||
|
if (Substring(*aURL, 0, string->Length()).Equals(*string)) {
|
||||||
|
idx = string->Length();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx > 0)
|
||||||
|
aURL->Cut(0, idx);
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
for (i = 0; i < mIgnoreHostnames.Count(); ++i) {
|
||||||
|
if (aExclude && i == aExclude->hostnamePrefix)
|
||||||
|
continue;
|
||||||
|
nsString* string = mIgnoreHostnames.StringAt(i);
|
||||||
|
if (Substring(*aURL, 0, string->Length()).Equals(*string)) {
|
||||||
|
idx = string->Length();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx > 0)
|
||||||
|
aURL->Cut(0, idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// nsNavHistory::AutoCompleteCompare
|
||||||
|
//
|
||||||
|
// Determines if a given URL from the history matches the user input.
|
||||||
|
// See AutoCompleteCutPrefix for the meaning of aExclude.
|
||||||
|
|
||||||
|
PRBool
|
||||||
|
nsNavHistory::AutoCompleteCompare(const nsAString& aHistoryURL,
|
||||||
|
const nsAString& aUserURL,
|
||||||
|
const AutoCompleteExclude& aExclude)
|
||||||
|
{
|
||||||
|
nsAutoString cutHistoryURL(aHistoryURL);
|
||||||
|
AutoCompleteCutPrefix(&cutHistoryURL, &aExclude);
|
||||||
|
return StringBeginsWith(cutHistoryURL, aUserURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// nsGlobalHistory::AutoCompleteSortComparison
|
||||||
|
//
|
||||||
|
// The design and reasoning behind the following autocomplete sort
|
||||||
|
// implementation is documented in bug 78270. In most cases, the precomputed
|
||||||
|
// priorities (by ComputeAutoCompletePriority) are used without further
|
||||||
|
// computation.
|
||||||
|
|
||||||
|
PRInt32 PR_CALLBACK // static
|
||||||
|
nsNavHistory::AutoCompleteSortComparison(const void* match1Void,
|
||||||
|
const void* match2Void,
|
||||||
|
void *navHistoryVoid)
|
||||||
|
{
|
||||||
|
// get our class pointer (this is a static function)
|
||||||
|
nsNavHistory* navHistory = NS_STATIC_CAST(nsNavHistory*, navHistoryVoid);
|
||||||
|
|
||||||
|
const AutoCompleteIntermediateResult* match1 = NS_STATIC_CAST(
|
||||||
|
const AutoCompleteIntermediateResult*, match1Void);
|
||||||
|
const AutoCompleteIntermediateResult* match2 = NS_STATIC_CAST(
|
||||||
|
const AutoCompleteIntermediateResult*, match2Void);
|
||||||
|
|
||||||
|
// In most cases the priorities will be different and we just use them
|
||||||
|
if (match1->priority != match2->priority)
|
||||||
|
{
|
||||||
|
return match2->priority - match1->priority;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// secondary sorting gives priority to site names and paths (ending in a /)
|
||||||
|
PRBool isPath1 = PR_FALSE, isPath2 = PR_FALSE;
|
||||||
|
if (!match1->url.IsEmpty())
|
||||||
|
isPath1 = (match1->url.Last() == PRUnichar('/'));
|
||||||
|
if (!match2->url.IsEmpty())
|
||||||
|
isPath2 = (match2->url.Last() == PRUnichar('/'));
|
||||||
|
|
||||||
|
if (isPath1 && !isPath2) return -1; // match1->url is a website/path, match2->url isn't
|
||||||
|
if (!isPath1 && isPath2) return 1; // match1->url isn't a website/path, match2->url is
|
||||||
|
|
||||||
|
// find the prefixes so we can sort by the stuff after the prefixes
|
||||||
|
AutoCompleteExclude prefix1, prefix2;
|
||||||
|
navHistory->AutoCompleteGetExcludeInfo(match1->url, &prefix1);
|
||||||
|
navHistory->AutoCompleteGetExcludeInfo(match2->url, &prefix2);
|
||||||
|
|
||||||
|
// compare non-prefixed urls
|
||||||
|
PRInt32 ret = Compare(
|
||||||
|
Substring(match1->url, prefix1.postPrefixOffset, match1->url.Length()),
|
||||||
|
Substring(match2->url, prefix2.postPrefixOffset, match2->url.Length()));
|
||||||
|
if (ret != 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
// sort http://xyz.com before http://www.xyz.com
|
||||||
|
return prefix1.postPrefixOffset - prefix2.postPrefixOffset;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ComputeAutoCompletePriority
|
||||||
|
//
|
||||||
|
// Favor websites and webpaths more than webpages by boosting
|
||||||
|
// their visit counts. This assumes that URLs have been normalized,
|
||||||
|
// appending a trailing '/'.
|
||||||
|
//
|
||||||
|
// We use addition to boost the visit count rather than multiplication
|
||||||
|
// since we want URLs with large visit counts to remain pretty much
|
||||||
|
// in raw visit count order - we assume the user has visited these urls
|
||||||
|
// often for a reason and there shouldn't be a problem with putting them
|
||||||
|
// high in the autocomplete list regardless of whether they are sites/
|
||||||
|
// paths or pages. However for URLs visited only a few times, sites
|
||||||
|
// & paths should be presented before pages since they are generally
|
||||||
|
// more likely to be visited again.
|
||||||
|
|
||||||
|
PRInt32
|
||||||
|
ComputeAutoCompletePriority(const nsAString& aUrl, PRInt32 aVisitCount,
|
||||||
|
PRBool aWasTyped)
|
||||||
|
{
|
||||||
|
PRInt32 aPriority = aVisitCount;
|
||||||
|
|
||||||
|
if (!aUrl.IsEmpty()) {
|
||||||
|
// url is a site/path if it has a trailing slash
|
||||||
|
if (aUrl.Last() == PRUnichar('/'))
|
||||||
|
aPriority += AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (aWasTyped)
|
||||||
|
aPriority += AUTOCOMPLETE_NONPAGE_VISIT_COUNT_BOOST;
|
||||||
|
|
||||||
|
return aPriority;
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче