зеркало из https://github.com/mozilla/gecko-dev.git
Bug 455555 - Use asynchronous queries for places AutoComplete.
This changes the location bar's AutoComplete provider to use asynchronous queries instead of synchronous ones. No more blocking the main thread FTW! r=mak r=Mardak r=dietrich
This commit is contained in:
Родитель
e0702433c2
Коммит
421808700f
|
@ -238,6 +238,7 @@ bin/components/txEXSLTRegExFunctions.js
|
|||
bin/components/nsLivemarkService.js
|
||||
bin/components/nsTaggingService.js
|
||||
bin/components/nsPlacesDBFlush.js
|
||||
bin/components/nsPlacesAutoComplete.js
|
||||
bin/components/nsDefaultCLH.js
|
||||
bin/components/nsContentPrefService.js
|
||||
bin/components/nsContentDispatchChooser.js
|
||||
|
|
|
@ -245,6 +245,7 @@ bin\components\txEXSLTRegExFunctions.js
|
|||
bin\components\nsLivemarkService.js
|
||||
bin\components\nsTaggingService.js
|
||||
bin\components\nsPlacesDBFlush.js
|
||||
bin\components\nsPlacesAutoComplete.js
|
||||
bin\components\nsDefaultCLH.js
|
||||
bin\components\nsContentPrefService.js
|
||||
bin\components\nsContentDispatchChooser.js
|
||||
|
|
|
@ -61,4 +61,6 @@
|
|||
#include "mozStorageHelper.h"
|
||||
#include "mozStorageCID.h"
|
||||
|
||||
#include "mozilla/storage/Variant.h"
|
||||
|
||||
#endif // mozilla_storage_h_
|
||||
|
|
|
@ -61,6 +61,7 @@ XPIDLSRCS += \
|
|||
nsITaggingService.idl \
|
||||
nsPIPlacesDatabase.idl \
|
||||
nsPIPlacesHistoryListenersNotifier.idl \
|
||||
mozIPlacesAutoComplete.idl \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=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
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* 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 "nsISupports.idl"
|
||||
|
||||
/**
|
||||
* This interface provides some constants used by the Places AutoComplete
|
||||
* search provider.
|
||||
*/
|
||||
[scriptable, uuid(a5ae8332-333c-412a-bb02-a35df8247714)]
|
||||
interface mozIPlacesAutoComplete : nsISupports
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Matching Constants
|
||||
|
||||
/**
|
||||
* Match anywhere in each searchable term.
|
||||
*/
|
||||
const long MATCH_ANYWHERE = 0;
|
||||
|
||||
/**
|
||||
* Match first on word boundaries, and if we do not get enough results, then
|
||||
* match anywhere in each searchable term.
|
||||
*/
|
||||
const long MATCH_BOUNDARY_ANYWHERE = 1;
|
||||
|
||||
/**
|
||||
* Match on word boundaries in each searchable term.
|
||||
*/
|
||||
const long MATCH_BOUNDARY = 2;
|
||||
|
||||
/**
|
||||
* Match only the beginning of each search term.
|
||||
*/
|
||||
const long MATCH_BEGINNING = 3;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// Search Behavior Constants
|
||||
|
||||
/**
|
||||
* Search through history.
|
||||
*/
|
||||
const long BEHAVIOR_HISTORY = 1 << 0;
|
||||
|
||||
/**
|
||||
* Search though bookmarks.
|
||||
*/
|
||||
const long BEHAVIOR_BOOKMARK = 1 << 1;
|
||||
|
||||
/**
|
||||
* Search through tags.
|
||||
*/
|
||||
const long BEHAVIOR_TAG = 1 << 2;
|
||||
|
||||
/**
|
||||
* Search the title of pages.
|
||||
*/
|
||||
const long BEHAVIOR_TITLE = 1 << 3;
|
||||
|
||||
/**
|
||||
* Search the URL of pages.
|
||||
*/
|
||||
const long BEHAVIOR_URL = 1 << 4;
|
||||
|
||||
/**
|
||||
* Search for typed pages.
|
||||
*/
|
||||
const long BEHAVIOR_TYPED = 1 << 5;
|
||||
|
||||
/**
|
||||
* Search javascript: URLs.
|
||||
*/
|
||||
const long BEHAVIOR_JAVASCRIPT = 1 << 6;
|
||||
};
|
|
@ -87,14 +87,9 @@ CPPSRCS = \
|
|||
nsMaybeWeakPtr.cpp \
|
||||
nsMorkHistoryImporter.cpp \
|
||||
nsPlacesModule.cpp \
|
||||
SQLFunctions.cpp \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_XUL
|
||||
CPPSRCS += \
|
||||
nsNavHistoryAutoComplete.cpp \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
EXTRA_DSO_LDOPTS += \
|
||||
$(DEPTH)/db/morkreader/$(LIB_PREFIX)morkreader_s.$(LIB_SUFFIX) \
|
||||
$(MOZ_UNICHARUTIL_LIBS) \
|
||||
|
@ -103,10 +98,18 @@ EXTRA_DSO_LDOPTS += \
|
|||
|
||||
LOCAL_INCLUDES += -I$(srcdir)/../../build
|
||||
|
||||
EXTRA_PP_COMPONENTS = nsLivemarkService.js \
|
||||
nsTaggingService.js \
|
||||
nsPlacesDBFlush.js \
|
||||
$(NULL)
|
||||
EXTRA_PP_COMPONENTS = \
|
||||
nsLivemarkService.js \
|
||||
nsTaggingService.js \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_COMPONENTS = \
|
||||
nsPlacesDBFlush.js \
|
||||
$(NULL)
|
||||
|
||||
ifdef MOZ_XUL
|
||||
EXTRA_COMPONENTS += nsPlacesAutoComplete.js
|
||||
endif
|
||||
|
||||
EXTRA_JS_MODULES = \
|
||||
utils.js \
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
/* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
||||
* ***** 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
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* 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 "mozilla/storage.h"
|
||||
#include "nsString.h"
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsWhitespaceTokenizer.h"
|
||||
#include "nsEscape.h"
|
||||
#include "mozIPlacesAutoComplete.h"
|
||||
#include "SQLFunctions.h"
|
||||
|
||||
using namespace mozilla::storage;
|
||||
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AutoComplete Matching Function
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// MatchAutoCompleteFunction
|
||||
|
||||
/* static */
|
||||
nsresult
|
||||
MatchAutoCompleteFunction::create(mozIStorageConnection *aDBConn)
|
||||
{
|
||||
nsRefPtr<MatchAutoCompleteFunction> function(new MatchAutoCompleteFunction);
|
||||
NS_ENSURE_TRUE(function, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsresult rv = aDBConn->CreateFunction(
|
||||
NS_LITERAL_CSTRING("autocomplete_match"), kArgIndexLength, function
|
||||
);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/* static */
|
||||
nsString
|
||||
MatchAutoCompleteFunction::fixupURISpec(const nsDependentCString &aURISpec)
|
||||
{
|
||||
nsCAutoString unescapedSpec;
|
||||
(void)NS_UnescapeURL(aURISpec, esc_SkipControl | esc_AlwaysCopy,
|
||||
unescapedSpec);
|
||||
|
||||
// If this unescaped string is valid UTF-8, we'll convert it. Otherwise,
|
||||
// we will simply convert our original string.
|
||||
nsString fixedSpec;
|
||||
if (IsUTF8(unescapedSpec))
|
||||
CopyUTF8toUTF16(unescapedSpec, fixedSpec);
|
||||
else
|
||||
CopyUTF8toUTF16(aURISpec, fixedSpec);
|
||||
|
||||
if (StringBeginsWith(fixedSpec, NS_LITERAL_STRING("http://")))
|
||||
fixedSpec.Cut(0, 7);
|
||||
else if (StringBeginsWith(fixedSpec, NS_LITERAL_STRING("https://")))
|
||||
fixedSpec.Cut(0, 8);
|
||||
else if (StringBeginsWith(fixedSpec, NS_LITERAL_STRING("ftp://")))
|
||||
fixedSpec.Cut(0, 6);
|
||||
|
||||
return fixedSpec;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MatchAutoCompleteFunction::findAnywhere(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString)
|
||||
{
|
||||
return !!CaseInsensitiveFindInReadable(aToken, aSourceString);
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MatchAutoCompleteFunction::findBeginning(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString)
|
||||
{
|
||||
return !!StringBeginsWith(aSourceString, aToken,
|
||||
nsCaseInsensitiveStringComparator());
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MatchAutoCompleteFunction::findOnBoundary(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString)
|
||||
{
|
||||
// We cannot match anything if there is nothing to search.
|
||||
if (aSourceString.IsEmpty())
|
||||
return false;
|
||||
|
||||
// Define a const instance of this class so it is created once.
|
||||
const nsCaseInsensitiveStringComparator caseInsensitiveCompare;
|
||||
|
||||
const_wchar_iterator tokenStart(aToken.BeginReading()),
|
||||
tokenEnd(aToken.EndReading()),
|
||||
sourceStart(aSourceString.BeginReading()),
|
||||
sourceEnd(aSourceString.EndReading());
|
||||
|
||||
// The start of aSourceString is considered a word boundary, so start there.
|
||||
do {
|
||||
// We are on a word boundary, so start by copying the iterators.
|
||||
const_wchar_iterator testTokenItr(tokenStart),
|
||||
testSourceItr(sourceStart);
|
||||
|
||||
// Keep trying to match the token one by one until it doesn't match.
|
||||
while (!caseInsensitiveCompare(*testTokenItr, *testSourceItr)) {
|
||||
// We matched something, so move down one.
|
||||
testTokenItr++;
|
||||
testSourceItr++;
|
||||
|
||||
// Matched the full token, so we are done!
|
||||
if (testTokenItr == tokenEnd)
|
||||
return true;
|
||||
|
||||
// However, if we ran into the end of the source while matching the
|
||||
// token, we will not find it.
|
||||
if (testSourceItr == sourceEnd)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Always advance our starting iterator, and if we are not currently on a
|
||||
// word boundary, advance to the next word boundary.
|
||||
if (!isWordBoundary(ToLowerCase(*sourceStart++)))
|
||||
sourceStart = nextWordBoundary(sourceStart, sourceEnd);
|
||||
} while (sourceStart != sourceEnd);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */
|
||||
MatchAutoCompleteFunction::const_wchar_iterator
|
||||
MatchAutoCompleteFunction::nextWordBoundary(const_wchar_iterator aStart,
|
||||
const_wchar_iterator aEnd)
|
||||
{
|
||||
while (aStart != aEnd && !isWordBoundary(*aStart))
|
||||
aStart++;
|
||||
return aStart;
|
||||
}
|
||||
|
||||
/* static */
|
||||
bool
|
||||
MatchAutoCompleteFunction::isWordBoundary(const PRUnichar &aChar)
|
||||
{
|
||||
// Only check lowercase alphabetic characters so we can match CamelCase
|
||||
// words. This means that matches will happen after an upper-case
|
||||
// character.
|
||||
return !(PRUnichar('a') <= aChar && aChar <= PRUnichar('z'));
|
||||
}
|
||||
|
||||
/* static */
|
||||
MatchAutoCompleteFunction::searchFunctionPtr
|
||||
MatchAutoCompleteFunction::getSearchFunction(PRInt32 aBehavior)
|
||||
{
|
||||
switch (aBehavior) {
|
||||
case mozIPlacesAutoComplete::MATCH_ANYWHERE:
|
||||
return findAnywhere;
|
||||
case mozIPlacesAutoComplete::MATCH_BEGINNING:
|
||||
return findBeginning;
|
||||
case mozIPlacesAutoComplete::MATCH_BOUNDARY:
|
||||
default:
|
||||
return findOnBoundary;
|
||||
};
|
||||
}
|
||||
|
||||
NS_IMPL_THREADSAFE_ISUPPORTS1(
|
||||
MatchAutoCompleteFunction,
|
||||
mozIStorageFunction
|
||||
)
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//// mozIStorageFunction
|
||||
|
||||
NS_IMETHODIMP
|
||||
MatchAutoCompleteFunction::OnFunctionCall(mozIStorageValueArray *aArguments,
|
||||
nsIVariant **_result)
|
||||
{
|
||||
// Macro to make the code a bit cleaner and easier to read. Operates on
|
||||
// searchBehavior.
|
||||
PRInt32 searchBehavior = aArguments->AsInt32(kArgIndexSearchBehavior);
|
||||
#define HAS_BEHAVIOR(aBitName) \
|
||||
(searchBehavior & mozIPlacesAutoComplete::BEHAVIOR_##aBitName)
|
||||
|
||||
nsDependentString searchString;
|
||||
(void)aArguments->GetString(kArgSearchString, searchString);
|
||||
nsDependentCString url;
|
||||
(void)aArguments->GetUTF8String(kArgIndexURL, url);
|
||||
|
||||
// We only want to filter javascript: URLs if we are not supposed to search
|
||||
// for them, and the search does not start with "javascript:".
|
||||
if (!HAS_BEHAVIOR(JAVASCRIPT) &&
|
||||
!StringBeginsWith(searchString, NS_LITERAL_STRING("javascript:")) &&
|
||||
StringBeginsWith(url, NS_LITERAL_CSTRING("javascript:"))) {
|
||||
NS_IF_ADDREF(*_result = new IntegerVariant(0));
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRInt32 visitCount = aArguments->AsInt32(kArgIndexVisitCount);
|
||||
bool typed = aArguments->AsInt32(kArgIndexTyped) ? true : false;
|
||||
bool bookmark = aArguments->AsInt32(kArgIndexBookmark) ? true : false;
|
||||
nsDependentString tags;
|
||||
(void)aArguments->GetString(kArgIndexTags, tags);
|
||||
|
||||
// Make sure we match all the filter requirements. If a given restriction
|
||||
// is active, make sure the corresponding condition is not true.
|
||||
bool matches = !(
|
||||
(HAS_BEHAVIOR(HISTORY) && visitCount == 0) ||
|
||||
(HAS_BEHAVIOR(TYPED) && !typed) ||
|
||||
(HAS_BEHAVIOR(BOOKMARK) && !bookmark) ||
|
||||
(HAS_BEHAVIOR(TAG) && tags.IsVoid())
|
||||
);
|
||||
if (!matches) {
|
||||
NS_IF_ADDREF(*_result = new IntegerVariant(0));
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Clean up our URI spec and prepare it for searching.
|
||||
nsString fixedURI = fixupURISpec(url);
|
||||
|
||||
// Obtain our search function.
|
||||
PRInt32 matchBehavior = aArguments->AsInt32(kArgIndexMatchBehavior);
|
||||
searchFunctionPtr searchFunction = getSearchFunction(matchBehavior);
|
||||
|
||||
nsDependentString title;
|
||||
(void)aArguments->GetString(kArgIndexTitle, title);
|
||||
|
||||
// Determine if every token matches either the bookmark title, tags, page
|
||||
// title, or page URL.
|
||||
nsWhitespaceTokenizer tokenizer(searchString);
|
||||
while (matches && tokenizer.hasMoreTokens()) {
|
||||
const nsDependentSubstring &token = tokenizer.nextToken();
|
||||
|
||||
bool matchTags = searchFunction(token, tags);
|
||||
bool matchTitle = searchFunction(token, title);
|
||||
|
||||
// Make sure we match something in the title or tags if we have to.
|
||||
matches = matchTags || matchTitle;
|
||||
if (HAS_BEHAVIOR(TITLE) && !matches)
|
||||
break;
|
||||
|
||||
bool matchURL = searchFunction(token, fixedURI);
|
||||
// If we do not match the URL when we have to, reset matches to false.
|
||||
// Otherwise, keep track that we did match the current search.
|
||||
if (HAS_BEHAVIOR(URL) && !matchURL)
|
||||
matches = false;
|
||||
else
|
||||
matches = matches || matchURL;
|
||||
}
|
||||
|
||||
NS_IF_ADDREF(*_result = new IntegerVariant(matches ? 1 : 0));
|
||||
NS_ENSURE_TRUE(*_result, NS_ERROR_OUT_OF_MEMORY);
|
||||
return NS_OK;
|
||||
#undef HAS_BEHAVIOR
|
||||
}
|
||||
|
||||
} // namespace places
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,208 @@
|
|||
/* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
||||
* ***** 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
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2009
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Shawn Wilsher <me@shawnwilsher.com> (Original Author)
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
#ifndef mozilla_places_SQLFunctions_h_
|
||||
#define mozilla_places_SQLFunctions_h_
|
||||
|
||||
/**
|
||||
* This file contains functions that Places adds to the database handle that can
|
||||
* be accessed by SQL queries.
|
||||
*/
|
||||
|
||||
#include "mozIStorageFunction.h"
|
||||
|
||||
class mozIStorageConnection;
|
||||
|
||||
namespace mozilla {
|
||||
namespace places {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//// AutoComplete Matching Function
|
||||
|
||||
/**
|
||||
* This function is used to determine if a given set of data should match an
|
||||
* AutoComplete query.
|
||||
*
|
||||
* In SQL, you'd use it in the WHERE clause like so:
|
||||
* WHERE AUTOCOMPLETE_MATCH(aSearchString, aURL, aTitle, aTags, aVisitCount,
|
||||
* aTyped)
|
||||
*
|
||||
* @param aSearchString
|
||||
* The string to compare against.
|
||||
* @param aURL
|
||||
* The URL to test for an AutoComplete match.
|
||||
* @param aTitle
|
||||
* The title to test for an AutoComplete match.
|
||||
* @param aTags
|
||||
* The tags to test for an AutoComplete match.
|
||||
* @param aVisitCount
|
||||
* The number of visits aURL has.
|
||||
* @param aTyped
|
||||
* Indicates if aURL is a typed URL or not. Treated as a boolean.
|
||||
* @param aBookmark
|
||||
* Indicates if aURL is a bookmark or not. Treated as a boolean.
|
||||
* @param aMatchBehavior
|
||||
* The match behavior to use for this search.
|
||||
* @param aSearchBehavior
|
||||
* A bitfield dictating the search behavior.
|
||||
*/
|
||||
class MatchAutoCompleteFunction : public mozIStorageFunction
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGEFUNCTION
|
||||
|
||||
/**
|
||||
* Registers the function with the specified database connection.
|
||||
*
|
||||
* @param aDBConn
|
||||
* The database connection to register with.
|
||||
*/
|
||||
static nsresult create(mozIStorageConnection *aDBConn);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Argument Indexes
|
||||
*/
|
||||
static const PRUint32 kArgSearchString = 0;
|
||||
static const PRUint32 kArgIndexURL = 1;
|
||||
static const PRUint32 kArgIndexTitle = 2;
|
||||
static const PRUint32 kArgIndexTags = 3;
|
||||
static const PRUint32 kArgIndexVisitCount = 4;
|
||||
static const PRUint32 kArgIndexTyped = 5;
|
||||
static const PRUint32 kArgIndexBookmark = 6;
|
||||
static const PRUint32 kArgIndexMatchBehavior = 7;
|
||||
static const PRUint32 kArgIndexSearchBehavior = 8;
|
||||
static const PRUint32 kArgIndexLength = 9;
|
||||
|
||||
/**
|
||||
* Typedefs
|
||||
*/
|
||||
typedef bool (*searchFunctionPtr)(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString);
|
||||
|
||||
typedef nsAString::const_char_iterator const_wchar_iterator;
|
||||
|
||||
/**
|
||||
* Obtains the search function to match on.
|
||||
*
|
||||
* @param aBehavior
|
||||
* The matching behavior to use defined by one of the
|
||||
* mozIPlacesAutoComplete::MATCH_* values.
|
||||
* @return a pointer to the function that will perform the proper search.
|
||||
*/
|
||||
static searchFunctionPtr getSearchFunction(PRInt32 aBehavior);
|
||||
|
||||
/**
|
||||
* Searches aSourceString for aToken anywhere in the string in a case-
|
||||
* insensitive way.
|
||||
*
|
||||
* @param aToken
|
||||
* The string to search for.
|
||||
* @param aSourceString
|
||||
* The string to search.
|
||||
* @return true if found, false otherwise.
|
||||
*/
|
||||
static bool findAnywhere(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString);
|
||||
|
||||
/**
|
||||
* Tests if aSourceString starts with aToken.
|
||||
*
|
||||
* @param aToken
|
||||
* The string to search for.
|
||||
* @param aSourceString
|
||||
* The string to search.
|
||||
* @return true if found, false otherwise.
|
||||
*/
|
||||
static bool findBeginning(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString);
|
||||
|
||||
/**
|
||||
* Tests if aToken is found on a word boundary in aSourceString.
|
||||
*
|
||||
* @param aToken
|
||||
* The string to search for.
|
||||
* @param aSourceString
|
||||
* The string to search.
|
||||
* @return true if found, false otherwise.
|
||||
*/
|
||||
static bool findOnBoundary(const nsDependentSubstring &aToken,
|
||||
const nsAString &aSourceString);
|
||||
|
||||
/**
|
||||
* Obtains an iterator to the next word boundary as defined by isWordBoundary.
|
||||
*
|
||||
* @param aStart
|
||||
* An iterator pointing to the start of the string.
|
||||
* @param aEnd
|
||||
* An iterator pointing to the end of the string.
|
||||
* @return an iterator pointing to the next word boundary.
|
||||
*/
|
||||
static const_wchar_iterator nextWordBoundary(const_wchar_iterator aStart,
|
||||
const_wchar_iterator aEnd);
|
||||
/**
|
||||
* Determines if aChar is a word boundary. A 'word boundary' is anything that
|
||||
* is not used to build up a word from a string of characters. We are very
|
||||
* conservative here because anything that we do not list will be treated as a
|
||||
* word boundary. This means searching for that not-actually-a-word-boundary
|
||||
* character can still be matched in the middle of a word.
|
||||
*
|
||||
* @param aChar
|
||||
* The Unicode character to check against.
|
||||
* @return true if the character is considered a word boundary, false
|
||||
* otherwise.
|
||||
*/
|
||||
static inline bool isWordBoundary(const PRUnichar &aChar);
|
||||
|
||||
/**
|
||||
* Fixes a URI's spec such that it is ready to be searched. This includes
|
||||
* unescaping escaped characters and removing certain specs that we do not
|
||||
* care to search for.
|
||||
*
|
||||
* @param aURISpec
|
||||
* The spec of the URI to prepare for searching.
|
||||
* @return the new string to use for the URI spec.
|
||||
*/
|
||||
static nsString fixupURISpec(const nsDependentCString &aURISpec);
|
||||
};
|
||||
|
||||
} // namespace places
|
||||
} // namespace storage
|
||||
|
||||
#endif // mozilla_places_SQLFunctions_h_
|
|
@ -54,6 +54,7 @@
|
|||
#include "nsPlacesIndexes.h"
|
||||
#include "nsPlacesTriggers.h"
|
||||
#include "nsPlacesMacros.h"
|
||||
#include "SQLFunctions.h"
|
||||
|
||||
#include "nsIArray.h"
|
||||
#include "nsTArray.h"
|
||||
|
@ -89,20 +90,18 @@
|
|||
#include "nsIIDNService.h"
|
||||
#include "nsIClassInfoImpl.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
#include "mozIStorageConnection.h"
|
||||
#include "mozIStorageFunction.h"
|
||||
#include "mozIStoragePendingStatement.h"
|
||||
#include "mozIStorageService.h"
|
||||
#include "mozIStorageStatement.h"
|
||||
#include "mozIStorageValueArray.h"
|
||||
#include "mozStorageCID.h"
|
||||
#include "mozStorageHelper.h"
|
||||
#include "mozIStorageError.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "mozilla/storage.h"
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIAutoCompleteInput.h"
|
||||
#include "nsIAutoCompletePopup.h"
|
||||
#endif
|
||||
|
||||
#include "nsMathUtils.h" // for NS_ceilf()
|
||||
|
||||
using namespace mozilla::places;
|
||||
|
||||
// Microsecond timeout for "recent" events such as typed and bookmark following.
|
||||
// If you typed it more than this time ago, it's not recent.
|
||||
// This is 15 minutes m s/m us/s
|
||||
|
@ -124,20 +123,6 @@
|
|||
#define PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN "history_expire_days_min"
|
||||
#define PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX "history_expire_days"
|
||||
#define PREF_BROWSER_HISTORY_EXPIRE_SITES "history_expire_sites"
|
||||
#define PREF_AUTOCOMPLETE_ENABLED "urlbar.autocomplete.enabled"
|
||||
#define PREF_AUTOCOMPLETE_MATCH_BEHAVIOR "urlbar.matchBehavior"
|
||||
#define PREF_AUTOCOMPLETE_FILTER_JAVASCRIPT "urlbar.filter.javascript"
|
||||
#define PREF_AUTOCOMPLETE_ENABLED "urlbar.autocomplete.enabled"
|
||||
#define PREF_AUTOCOMPLETE_MAX_RICH_RESULTS "urlbar.maxRichResults"
|
||||
#define PREF_AUTOCOMPLETE_DEFAULT_BEHAVIOR "urlbar.default.behavior"
|
||||
#define PREF_AUTOCOMPLETE_RESTRICT_HISTORY "urlbar.restrict.history"
|
||||
#define PREF_AUTOCOMPLETE_RESTRICT_BOOKMARK "urlbar.restrict.bookmark"
|
||||
#define PREF_AUTOCOMPLETE_RESTRICT_TAG "urlbar.restrict.tag"
|
||||
#define PREF_AUTOCOMPLETE_MATCH_TITLE "urlbar.match.title"
|
||||
#define PREF_AUTOCOMPLETE_MATCH_URL "urlbar.match.url"
|
||||
#define PREF_AUTOCOMPLETE_RESTRICT_TYPED "urlbar.restrict.typed"
|
||||
#define PREF_AUTOCOMPLETE_SEARCH_CHUNK_SIZE "urlbar.search.chunkSize"
|
||||
#define PREF_AUTOCOMPLETE_SEARCH_TIMEOUT "urlbar.search.timeout"
|
||||
#define PREF_DB_CACHE_PERCENTAGE "history_cache_percentage"
|
||||
#define PREF_FRECENCY_NUM_VISITS "places.frecency.numVisits"
|
||||
#define PREF_FRECENCY_FIRST_BUCKET_CUTOFF "places.frecency.firstBucketCutoff"
|
||||
|
@ -160,6 +145,8 @@
|
|||
#define PREF_FRECENCY_UNVISITED_BOOKMARK_BONUS "places.frecency.unvisitedBookmarkBonus"
|
||||
#define PREF_FRECENCY_UNVISITED_TYPED_BONUS "places.frecency.unvisitedTypedBonus"
|
||||
|
||||
#define PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC "places-autocomplete-feedback-updated"
|
||||
|
||||
// Default (integer) value of PREF_DB_CACHE_PERCENTAGE from 0-100
|
||||
// This is 6% of machine memory, giving 15MB for a user with 256MB of memory.
|
||||
// The most that will be used is the size of the DB file. Normal history sizes
|
||||
|
@ -239,10 +226,6 @@ NS_INTERFACE_MAP_BEGIN(nsNavHistory)
|
|||
NS_INTERFACE_MAP_ENTRY(nsICharsetResolver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsPIPlacesDatabase)
|
||||
NS_INTERFACE_MAP_ENTRY(nsPIPlacesHistoryListenersNotifier)
|
||||
#ifdef MOZ_XUL
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteSearch)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAutoCompleteSimpleResultListener)
|
||||
#endif
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsINavHistoryService)
|
||||
NS_IMPL_QUERY_CLASSINFO(nsNavHistory)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -366,21 +349,6 @@ const PRInt32 nsNavHistory::kGetInfoIndex_ItemId = 8;
|
|||
const PRInt32 nsNavHistory::kGetInfoIndex_ItemDateAdded = 9;
|
||||
const PRInt32 nsNavHistory::kGetInfoIndex_ItemLastModified = 10;
|
||||
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_URL = 0;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_Title = 1;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_FaviconURL = 2;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_ParentId = 3;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_BookmarkTitle = 4;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_Tags = 5;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_VisitCount = 6;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteIndex_Typed = 7;
|
||||
|
||||
const PRInt32 nsNavHistory::kAutoCompleteBehaviorHistory = 1 << 0;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteBehaviorBookmark = 1 << 1;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteBehaviorTag = 1 << 2;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteBehaviorTitle = 1 << 3;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteBehaviorUrl = 1 << 4;
|
||||
const PRInt32 nsNavHistory::kAutoCompleteBehaviorTyped = 1 << 5;
|
||||
|
||||
static const char* gQuitApplicationGrantedMessage = "quit-application-granted";
|
||||
static const char* gXpcomShutdown = "xpcom-shutdown";
|
||||
|
@ -424,21 +392,6 @@ nsNavHistory::nsNavHistory() : mBatchLevel(0),
|
|||
mNowValid(PR_FALSE),
|
||||
mExpireNowTimer(nsnull),
|
||||
mExpire(this),
|
||||
mAutoCompleteEnabled(PR_TRUE),
|
||||
mAutoCompleteMatchBehavior(MATCH_BOUNDARY_ANYWHERE),
|
||||
mAutoCompleteMaxResults(25),
|
||||
mAutoCompleteRestrictHistory(NS_LITERAL_STRING("^")),
|
||||
mAutoCompleteRestrictBookmark(NS_LITERAL_STRING("*")),
|
||||
mAutoCompleteRestrictTag(NS_LITERAL_STRING("+")),
|
||||
mAutoCompleteMatchTitle(NS_LITERAL_STRING("#")),
|
||||
mAutoCompleteMatchUrl(NS_LITERAL_STRING("@")),
|
||||
mAutoCompleteRestrictTyped(NS_LITERAL_STRING("~")),
|
||||
mAutoCompleteSearchChunkSize(100),
|
||||
mAutoCompleteSearchTimeout(100),
|
||||
mAutoCompleteDefaultBehavior(0),
|
||||
mAutoCompleteCurrentBehavior(0),
|
||||
mPreviousChunkOffset(-1),
|
||||
mAutoCompleteFinishedSearch(PR_FALSE),
|
||||
mExpireDaysMin(0),
|
||||
mExpireDaysMax(0),
|
||||
mExpireSites(0),
|
||||
|
@ -519,11 +472,6 @@ nsNavHistory::Init()
|
|||
rv = NS_DispatchToMainThread(completeEvent);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
rv = InitAutoComplete();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#endif
|
||||
|
||||
// extract the last session ID so we know where to pick up. There is no index
|
||||
// over sessions so the naive statement "SELECT MAX(session) FROM
|
||||
// moz_historyvisits" won't have good performance.
|
||||
|
@ -565,19 +513,6 @@ nsNavHistory::Init()
|
|||
|
||||
nsCOMPtr<nsIPrefBranch2> pbi = do_QueryInterface(mPrefBranch);
|
||||
if (pbi) {
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_ENABLED, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_MATCH_BEHAVIOR, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_FILTER_JAVASCRIPT, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_MAX_RICH_RESULTS, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_DEFAULT_BEHAVIOR, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_HISTORY, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_BOOKMARK, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_TAG, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_MATCH_TITLE, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_MATCH_URL, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_RESTRICT_TYPED, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_SEARCH_CHUNK_SIZE, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_AUTOCOMPLETE_SEARCH_TIMEOUT, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MAX, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_DAYS_MIN, this, PR_FALSE);
|
||||
pbi->AddObserver(PREF_BROWSER_HISTORY_EXPIRE_SITES, this, PR_FALSE);
|
||||
|
@ -1151,11 +1086,15 @@ nsNavHistory::InitViews()
|
|||
nsresult
|
||||
nsNavHistory::InitFunctions()
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<mozIStorageFunction> func =
|
||||
new mozStorageFunctionGetUnreversedHost;
|
||||
NS_ENSURE_TRUE(func, NS_ERROR_OUT_OF_MEMORY);
|
||||
nsresult rv = mDBConn->CreateFunction(
|
||||
NS_LITERAL_CSTRING("get_unreversed_host"), 1, func
|
||||
);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBConn->CreateFunction(
|
||||
NS_LITERAL_CSTRING("get_unreversed_host"), 1,
|
||||
new mozStorageFunctionGetUnreversedHost);
|
||||
rv = MatchAutoCompleteFunction::create(mDBConn);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
|
@ -2146,62 +2085,6 @@ nsNavHistory::LoadPrefs(PRBool aInitializing)
|
|||
if (NS_FAILED(mPrefBranch->GetIntPref(PREF_BROWSER_HISTORY_EXPIRE_SITES,
|
||||
&mExpireSites)))
|
||||
mExpireSites = EXPIRATION_CAP_SITES;
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
mPrefBranch->GetBoolPref(PREF_AUTOCOMPLETE_ENABLED, &mAutoCompleteEnabled);
|
||||
|
||||
PRInt32 matchBehavior = 1;
|
||||
mPrefBranch->GetIntPref(PREF_AUTOCOMPLETE_MATCH_BEHAVIOR,
|
||||
&matchBehavior);
|
||||
switch (matchBehavior) {
|
||||
case 0:
|
||||
mAutoCompleteMatchBehavior = MATCH_ANYWHERE;
|
||||
break;
|
||||
case 2:
|
||||
mAutoCompleteMatchBehavior = MATCH_BOUNDARY;
|
||||
break;
|
||||
case 3:
|
||||
mAutoCompleteMatchBehavior = MATCH_BEGINNING;
|
||||
break;
|
||||
case 1:
|
||||
default:
|
||||
mAutoCompleteMatchBehavior = MATCH_BOUNDARY_ANYWHERE;
|
||||
break;
|
||||
}
|
||||
|
||||
mPrefBranch->GetBoolPref(PREF_AUTOCOMPLETE_FILTER_JAVASCRIPT,
|
||||
&mAutoCompleteFilterJavascript);
|
||||
mPrefBranch->GetIntPref(PREF_AUTOCOMPLETE_MAX_RICH_RESULTS,
|
||||
&mAutoCompleteMaxResults);
|
||||
mPrefBranch->GetIntPref(PREF_AUTOCOMPLETE_SEARCH_CHUNK_SIZE,
|
||||
&mAutoCompleteSearchChunkSize);
|
||||
mPrefBranch->GetIntPref(PREF_AUTOCOMPLETE_SEARCH_TIMEOUT,
|
||||
&mAutoCompleteSearchTimeout);
|
||||
mPrefBranch->GetIntPref(PREF_AUTOCOMPLETE_DEFAULT_BEHAVIOR,
|
||||
&mAutoCompleteDefaultBehavior);
|
||||
nsXPIDLCString prefStr;
|
||||
mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_RESTRICT_HISTORY,
|
||||
getter_Copies(prefStr));
|
||||
CopyUTF8toUTF16(prefStr, mAutoCompleteRestrictHistory);
|
||||
mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_RESTRICT_BOOKMARK,
|
||||
getter_Copies(prefStr));
|
||||
CopyUTF8toUTF16(prefStr, mAutoCompleteRestrictBookmark);
|
||||
mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_RESTRICT_TAG,
|
||||
getter_Copies(prefStr));
|
||||
CopyUTF8toUTF16(prefStr, mAutoCompleteRestrictTag);
|
||||
mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_MATCH_TITLE,
|
||||
getter_Copies(prefStr));
|
||||
CopyUTF8toUTF16(prefStr, mAutoCompleteMatchTitle);
|
||||
mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_MATCH_URL,
|
||||
getter_Copies(prefStr));
|
||||
CopyUTF8toUTF16(prefStr, mAutoCompleteMatchUrl);
|
||||
mPrefBranch->GetCharPref(PREF_AUTOCOMPLETE_RESTRICT_TYPED,
|
||||
getter_Copies(prefStr));
|
||||
CopyUTF8toUTF16(prefStr, mAutoCompleteRestrictTyped);
|
||||
|
||||
// Clear out the search on any pref change to invalidate cached search
|
||||
mCurrentSearchString = EmptyString();
|
||||
#endif
|
||||
|
||||
// get the frecency prefs
|
||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService("@mozilla.org/preferences-service;1"));
|
||||
|
@ -5657,10 +5540,6 @@ nsNavHistory::Observe(nsISupports *aSubject, const char *aTopic,
|
|||
mIdleTimer->Cancel();
|
||||
mIdleTimer = nsnull;
|
||||
}
|
||||
if (mAutoCompleteTimer) {
|
||||
mAutoCompleteTimer->Cancel();
|
||||
mAutoCompleteTimer = nsnull;
|
||||
}
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIPrefService> prefService =
|
||||
do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
|
||||
|
@ -5682,7 +5561,6 @@ nsNavHistory::Observe(nsISupports *aSubject, const char *aTopic,
|
|||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
observerService->RemoveObserver(this, NS_PRIVATE_BROWSING_SWITCH_TOPIC);
|
||||
observerService->RemoveObserver(this, gIdleDaily);
|
||||
observerService->RemoveObserver(this, gAutoCompleteFeedback);
|
||||
observerService->RemoveObserver(this, gXpcomShutdown);
|
||||
observerService->RemoveObserver(this, gQuitApplicationGrantedMessage);
|
||||
}
|
||||
|
@ -7746,6 +7624,131 @@ nsNavHistory::FixInvalidFrecencies()
|
|||
}
|
||||
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
|
||||
namespace {
|
||||
|
||||
// Used to notify a topic to system observers on async execute completion.
|
||||
class AutoCompleteStatementCallbackNotifier : public mozIStorageStatementCallback
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_MOZISTORAGESTATEMENTCALLBACK
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS1(AutoCompleteStatementCallbackNotifier,
|
||||
mozIStorageStatementCallback)
|
||||
|
||||
NS_IMETHODIMP
|
||||
AutoCompleteStatementCallbackNotifier::HandleCompletion(PRUint16 aReason)
|
||||
{
|
||||
if (aReason != mozIStorageStatementCallback::REASON_FINISHED)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIObserverService> observerService =
|
||||
do_GetService("@mozilla.org/observer-service;1", &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = observerService->NotifyObservers(nsnull,
|
||||
PLACES_AUTOCOMPLETE_FEEDBACK_UPDATED_TOPIC,
|
||||
nsnull);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AutoCompleteStatementCallbackNotifier::HandleError(mozIStorageError *aError)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
PRInt32 result;
|
||||
nsresult rv = aError->GetResult(&result);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCAutoString message;
|
||||
rv = aError->GetMessage(message);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCAutoString warnMsg;
|
||||
warnMsg.Append("An error occured while executing an async statement: ");
|
||||
warnMsg.Append(result);
|
||||
warnMsg.Append(" ");
|
||||
warnMsg.Append(message);
|
||||
NS_WARNING(warnMsg.get());
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
AutoCompleteStatementCallbackNotifier::HandleResult(mozIStorageResultSet *aResultSet)
|
||||
{
|
||||
NS_ASSERTION(PR_FALSE, "You cannot use AutoCompleteStatementCallbackNotifier to get async statements resultset");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
nsresult
|
||||
nsNavHistory::AutoCompleteFeedback(PRInt32 aIndex,
|
||||
nsIAutoCompleteController *aController)
|
||||
{
|
||||
// We do not track user choices in the location bar in private browsing mode.
|
||||
if (InPrivateBrowsingMode())
|
||||
return NS_OK;
|
||||
|
||||
mozIStorageStatement *stmt = GetDBFeedbackIncrease();
|
||||
mozStorageStatementScoper scope(stmt);
|
||||
|
||||
nsAutoString input;
|
||||
nsresult rv = aController->GetSearchString(input);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindStringParameter(0, input);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsAutoString url;
|
||||
rv = aController->GetValueAt(aIndex, url);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = stmt->BindStringParameter(1, url);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We do the update asynchronously and we do not care about failures.
|
||||
nsCOMPtr<AutoCompleteStatementCallbackNotifier> callback =
|
||||
new AutoCompleteStatementCallbackNotifier();
|
||||
nsCOMPtr<mozIStoragePendingStatement> canceler;
|
||||
rv = stmt->ExecuteAsync(callback, getter_AddRefs(canceler));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
mozIStorageStatement*
|
||||
nsNavHistory::GetDBFeedbackIncrease()
|
||||
{
|
||||
if (mDBFeedbackIncrease)
|
||||
return mDBFeedbackIncrease;
|
||||
|
||||
nsresult rv = mDBConn->CreateStatement(NS_LITERAL_CSTRING(
|
||||
// Leverage the PRIMARY KEY (place_id, input) to insert/update entries.
|
||||
"INSERT OR REPLACE INTO moz_inputhistory "
|
||||
// use_count will asymptotically approach the max of 10.
|
||||
"SELECT h.id, IFNULL(i.input, ?1), IFNULL(i.use_count, 0) * .9 + 1 "
|
||||
"FROM moz_places_temp h "
|
||||
"LEFT JOIN moz_inputhistory i ON i.place_id = h.id AND i.input = ?1 "
|
||||
"WHERE url = ?2 "
|
||||
"UNION ALL "
|
||||
"SELECT h.id, IFNULL(i.input, ?1), IFNULL(i.use_count, 0) * .9 + 1 "
|
||||
"FROM moz_places h "
|
||||
"LEFT JOIN moz_inputhistory i ON i.place_id = h.id AND i.input = ?1 "
|
||||
"WHERE url = ?2 "
|
||||
"AND h.id NOT IN (SELECT id FROM moz_places_temp)"),
|
||||
getter_AddRefs(mDBFeedbackIncrease));
|
||||
NS_ENSURE_SUCCESS(rv, nsnull);
|
||||
|
||||
return mDBFeedbackIncrease;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
nsICollation *
|
||||
nsNavHistory::GetCollation()
|
||||
{
|
||||
|
@ -7901,6 +7904,9 @@ nsNavHistory::GetDBBookmarkToUrlResult()
|
|||
nsresult
|
||||
nsNavHistory::FinalizeStatements() {
|
||||
mozIStorageStatement* stmts[] = {
|
||||
#ifdef MOZ_XUL
|
||||
mDBFeedbackIncrease,
|
||||
#endif
|
||||
mDBGetURLPageInfo,
|
||||
mDBGetIdPageInfo,
|
||||
mDBRecentVisitOfURL,
|
||||
|
@ -7920,16 +7926,6 @@ nsNavHistory::FinalizeStatements() {
|
|||
mDBUpdateFrecencyAndHidden,
|
||||
mDBGetPlaceVisitStats,
|
||||
mDBFullVisitCount,
|
||||
mDBCurrentQuery,
|
||||
mDBAutoCompleteQuery,
|
||||
mDBAutoCompleteTypedQuery,
|
||||
mDBAutoCompleteHistoryQuery,
|
||||
mDBAutoCompleteStarQuery,
|
||||
mDBAutoCompleteTagsQuery,
|
||||
mDBPreviousQuery,
|
||||
mDBAdaptiveQuery,
|
||||
mDBKeywordQuery,
|
||||
mDBFeedbackIncrease
|
||||
};
|
||||
|
||||
for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(stmts); i++) {
|
||||
|
|
|
@ -52,14 +52,6 @@
|
|||
#include "nsINavHistoryService.h"
|
||||
#include "nsPIPlacesDatabase.h"
|
||||
#include "nsPIPlacesHistoryListenersNotifier.h"
|
||||
#ifdef MOZ_XUL
|
||||
#include "nsIAutoCompleteController.h"
|
||||
#include "nsIAutoCompleteInput.h"
|
||||
#include "nsIAutoCompletePopup.h"
|
||||
#include "nsIAutoCompleteSearch.h"
|
||||
#include "nsIAutoCompleteResult.h"
|
||||
#include "nsIAutoCompleteSimpleResult.h"
|
||||
#endif
|
||||
#include "nsIBrowserHistory.h"
|
||||
#include "nsICollation.h"
|
||||
#include "nsIGlobalHistory.h"
|
||||
|
@ -109,8 +101,6 @@
|
|||
#define PLACES_INIT_COMPLETE_EVENT_TOPIC "places-init-complete"
|
||||
#define PLACES_DB_LOCKED_EVENT_TOPIC "places-database-locked"
|
||||
|
||||
struct AutoCompleteIntermediateResult;
|
||||
class AutoCompleteResultComparator;
|
||||
class mozIAnnotationService;
|
||||
class nsNavHistory;
|
||||
class nsNavBookmarks;
|
||||
|
@ -118,6 +108,7 @@ class QueryKeyValuePair;
|
|||
class nsIEffectiveTLDService;
|
||||
class nsIIDNService;
|
||||
class PlacesSQLQueryBuilder;
|
||||
class nsIAutoCompleteController;
|
||||
|
||||
// nsNavHistory
|
||||
|
||||
|
@ -130,13 +121,7 @@ class nsNavHistory : public nsSupportsWeakReference
|
|||
, public nsICharsetResolver
|
||||
, public nsPIPlacesDatabase
|
||||
, public nsPIPlacesHistoryListenersNotifier
|
||||
#ifdef MOZ_XUL
|
||||
, public nsIAutoCompleteSearch
|
||||
, public nsIAutoCompleteSimpleResultListener
|
||||
#endif
|
||||
{
|
||||
friend class AutoCompleteIntermediateResultSet;
|
||||
friend class AutoCompleteResultComparator;
|
||||
friend class PlacesSQLQueryBuilder;
|
||||
|
||||
public:
|
||||
|
@ -152,10 +137,6 @@ public:
|
|||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSPIPLACESDATABASE
|
||||
NS_DECL_NSPIPLACESHISTORYLISTENERSNOTIFIER
|
||||
#ifdef MOZ_XUL
|
||||
NS_DECL_NSIAUTOCOMPLETESEARCH
|
||||
NS_DECL_NSIAUTOCOMPLETESIMPLERESULTLISTENER
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
|
@ -658,124 +639,15 @@ protected:
|
|||
PRInt64 mLastSessionID;
|
||||
PRInt64 GetNewSessionID() { mLastSessionID ++; return mLastSessionID; }
|
||||
|
||||
//
|
||||
#ifdef MOZ_XUL
|
||||
// AutoComplete stuff
|
||||
//
|
||||
static const PRInt32 kAutoCompleteIndex_URL;
|
||||
static const PRInt32 kAutoCompleteIndex_Title;
|
||||
static const PRInt32 kAutoCompleteIndex_FaviconURL;
|
||||
static const PRInt32 kAutoCompleteIndex_ParentId;
|
||||
static const PRInt32 kAutoCompleteIndex_BookmarkTitle;
|
||||
static const PRInt32 kAutoCompleteIndex_Tags;
|
||||
static const PRInt32 kAutoCompleteIndex_VisitCount;
|
||||
static const PRInt32 kAutoCompleteIndex_Typed;
|
||||
nsCOMPtr<mozIStorageStatement> mDBCurrentQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteTypedQuery; // kAutoCompleteIndex_* results
|
||||
mozIStorageStatement* GetDBAutoCompleteHistoryQuery();
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteHistoryQuery; // kAutoCompleteIndex_* results
|
||||
mozIStorageStatement* GetDBAutoCompleteStarQuery();
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteStarQuery; // kAutoCompleteIndex_* results
|
||||
mozIStorageStatement* GetDBAutoCompleteTagsQuery();
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteTagsQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBPreviousQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBAdaptiveQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBKeywordQuery; // kAutoCompleteIndex_* results
|
||||
mozIStorageStatement* GetDBFeedbackIncrease();
|
||||
nsCOMPtr<mozIStorageStatement> mDBFeedbackIncrease;
|
||||
|
||||
/**
|
||||
* AutoComplete word matching behavior to determine if words should match on
|
||||
* word boundaries or not or both.
|
||||
*/
|
||||
enum MatchType {
|
||||
MATCH_ANYWHERE,
|
||||
MATCH_BOUNDARY_ANYWHERE,
|
||||
MATCH_BOUNDARY,
|
||||
MATCH_BEGINNING
|
||||
};
|
||||
|
||||
nsresult InitAutoComplete();
|
||||
nsresult CreateAutoCompleteQueries();
|
||||
PRBool mAutoCompleteEnabled;
|
||||
MatchType mAutoCompleteMatchBehavior;
|
||||
PRBool mAutoCompleteFilterJavascript;
|
||||
PRInt32 mAutoCompleteMaxResults;
|
||||
nsString mAutoCompleteRestrictHistory;
|
||||
nsString mAutoCompleteRestrictBookmark;
|
||||
nsString mAutoCompleteRestrictTag;
|
||||
nsString mAutoCompleteMatchTitle;
|
||||
nsString mAutoCompleteMatchUrl;
|
||||
nsString mAutoCompleteRestrictTyped;
|
||||
PRInt32 mAutoCompleteSearchChunkSize;
|
||||
PRInt32 mAutoCompleteSearchTimeout;
|
||||
nsCOMPtr<nsITimer> mAutoCompleteTimer;
|
||||
|
||||
static const PRInt32 kAutoCompleteBehaviorHistory;
|
||||
static const PRInt32 kAutoCompleteBehaviorBookmark;
|
||||
static const PRInt32 kAutoCompleteBehaviorTag;
|
||||
static const PRInt32 kAutoCompleteBehaviorTitle;
|
||||
static const PRInt32 kAutoCompleteBehaviorUrl;
|
||||
static const PRInt32 kAutoCompleteBehaviorTyped;
|
||||
|
||||
PRInt32 mAutoCompleteDefaultBehavior; // kAutoCompleteBehavior* bitmap
|
||||
PRInt32 mAutoCompleteCurrentBehavior; // kAutoCompleteBehavior* bitmap
|
||||
|
||||
// Original search string for case-sensitive usage
|
||||
nsString mOrigSearchString;
|
||||
// Search string and tokens for case-insensitive matching
|
||||
nsString mCurrentSearchString;
|
||||
nsTArray<nsString> mCurrentSearchTokens;
|
||||
void GenerateSearchTokens();
|
||||
void AddSearchToken(nsAutoString &aToken);
|
||||
void ProcessTokensForSpecialSearch();
|
||||
|
||||
#ifdef MOZ_XUL
|
||||
nsresult AutoCompleteFeedback(PRInt32 aIndex,
|
||||
nsIAutoCompleteController *aController);
|
||||
|
||||
nsCOMPtr<nsIAutoCompleteObserver> mCurrentListener;
|
||||
nsCOMPtr<nsIAutoCompleteSimpleResult> mCurrentResult;
|
||||
#endif
|
||||
|
||||
MatchType mCurrentMatchType;
|
||||
MatchType mPreviousMatchType;
|
||||
nsDataHashtable<nsStringHashKey, PRBool> mCurrentResultURLs;
|
||||
PRInt32 mCurrentChunkOffset;
|
||||
PRInt32 mPreviousChunkOffset;
|
||||
|
||||
nsDataHashtable<nsTrimInt64HashKey, PRBool> mLivemarkFeedItemIds;
|
||||
nsDataHashtable<nsStringHashKey, PRBool> mLivemarkFeedURIs;
|
||||
|
||||
nsresult AutoCompleteFullHistorySearch(PRBool* aHasMoreResults);
|
||||
nsresult AutoCompletePreviousSearch();
|
||||
nsresult AutoCompleteAdaptiveSearch();
|
||||
nsresult AutoCompleteKeywordSearch();
|
||||
|
||||
/**
|
||||
* Query type passed to AutoCompleteProcessSearch to determine what style to
|
||||
* use and if results should be filtered
|
||||
*/
|
||||
enum QueryType {
|
||||
QUERY_KEYWORD,
|
||||
QUERY_FILTERED
|
||||
};
|
||||
nsresult AutoCompleteProcessSearch(mozIStorageStatement* aQuery,
|
||||
const QueryType aType,
|
||||
PRBool *aHasMoreResults = nsnull);
|
||||
PRBool AutoCompleteHasEnoughResults();
|
||||
|
||||
nsresult PerformAutoComplete();
|
||||
nsresult StartAutoCompleteTimer(PRUint32 aMilliseconds);
|
||||
static void AutoCompleteTimerCallback(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
PRBool mAutoCompleteFinishedSearch;
|
||||
void DoneSearching(PRBool aFinished);
|
||||
|
||||
// Used to unescape encoded URI strings for searching
|
||||
nsCOMPtr<nsITextToSubURI> mTextURIService;
|
||||
nsString FixupURIText(const nsAString &aURIText);
|
||||
|
||||
PRInt32 mExpireDaysMin;
|
||||
PRInt32 mExpireDaysMax;
|
||||
PRInt32 mExpireSites;
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -37,12 +37,6 @@ static const nsModuleComponentInfo components[] =
|
|||
nsNavHistoryConstructor,
|
||||
NS_NAVHISTORY_CLASSINFO },
|
||||
|
||||
{ "Browser Navigation History",
|
||||
NS_NAVHISTORYSERVICE_CID,
|
||||
"@mozilla.org/autocomplete/search;1?name=history",
|
||||
nsNavHistoryConstructor,
|
||||
NS_NAVHISTORY_CLASSINFO },
|
||||
|
||||
{ "Download Navigation History",
|
||||
NS_NAVHISTORYSERVICE_CID,
|
||||
NS_DOWNLOADHISTORY_CONTRACTID,
|
||||
|
|
|
@ -113,7 +113,7 @@ function ensure_results(aSearch, aExpected)
|
|||
let value = controller.getValueAt(i);
|
||||
let comment = controller.getCommentAt(i);
|
||||
|
||||
print("Looking for " + value + ", " + comment + " in expected results...");
|
||||
print("Looking for '" + value + "', '" + comment + "' in expected results...");
|
||||
let j;
|
||||
for (j = 0; j < aExpected.length; j++) {
|
||||
// Skip processed expected results
|
||||
|
@ -126,6 +126,7 @@ function ensure_results(aSearch, aExpected)
|
|||
title = kTitles[title];
|
||||
if (tags && appendTags)
|
||||
title += " \u2013 " + tags.map(function(aTag) kTitles[aTag]);
|
||||
print("Checking against expected '" + uri + "', '" + title + "'...");
|
||||
|
||||
// Got a match on both uri and title?
|
||||
if (uri == value && title == comment) {
|
||||
|
@ -138,10 +139,12 @@ function ensure_results(aSearch, aExpected)
|
|||
|
||||
// We didn't hit the break, so we must have not found it
|
||||
if (j == aExpected.length)
|
||||
do_throw("Didn't find the current result (" + value + ", " + comment + ") in expected: " + aExpected);
|
||||
do_throw("Didn't find the current result ('" + value + "', '" + comment + "') in expected: " + aExpected);
|
||||
}
|
||||
|
||||
// Make sure we have the right number of results
|
||||
print("Expecting " + aExpected.length + " results; got " +
|
||||
controller.matchCount + " results");
|
||||
do_check_eq(controller.matchCount, aExpected.length);
|
||||
|
||||
// If we expect results, make sure we got matches
|
||||
|
@ -156,7 +159,7 @@ function ensure_results(aSearch, aExpected)
|
|||
do_test_finished();
|
||||
};
|
||||
|
||||
print("Searching for.. " + aSearch);
|
||||
print("Searching for.. '" + aSearch + "'");
|
||||
controller.startSearch(aSearch);
|
||||
}
|
||||
|
||||
|
|
|
@ -241,8 +241,8 @@ AutoCompleteInput.prototype = {
|
|||
|
||||
function run_test() {
|
||||
var controller = Components.classes["@mozilla.org/autocomplete/controller;1"].
|
||||
getService(Components.interfaces.nsIAutoCompleteController);
|
||||
|
||||
getService(Components.interfaces.nsIAutoCompleteController);
|
||||
|
||||
// Make an AutoCompleteInput that uses our searches
|
||||
// and confirms results on search complete
|
||||
var input = new AutoCompleteInput(["history"]);
|
||||
|
@ -264,7 +264,7 @@ function run_test() {
|
|||
|
||||
input.onSearchComplete = function() {
|
||||
do_check_eq(numSearchesStarted, 1);
|
||||
do_check_eq(controller.searchStatus,
|
||||
do_check_eq(controller.searchStatus,
|
||||
Ci.nsIAutoCompleteController.STATUS_COMPLETE_MATCH);
|
||||
|
||||
// test that all records with non-zero frecency were matched
|
||||
|
@ -283,7 +283,8 @@ function run_test() {
|
|||
// undefined), so check if frecency matches. This is okay because we
|
||||
// can still ensure the correct number of expected frecencies.
|
||||
let getFrecency = function(aURL) aURL.match(/frecency:(-?\d+)$/)[1];
|
||||
print("### searchURL: '"+searchURL+"', expectedURL: '"+expectedURL+"'");
|
||||
print("### checking for same frecency between '" + searchURL +
|
||||
"' and '" + expectURL + "'");
|
||||
do_check_eq(getFrecency(searchURL), getFrecency(expectURL));
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче