mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 392143 - show keywords as url bar autocomplete choices. r=dietrich, r=gavin
This commit is contained in:
parent
87d96aafd9
commit
1bef7eb888
@ -1039,6 +1039,13 @@ toolbar[iconsize="small"] #paste-button[disabled="true"] {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.ac-result-type-keyword,
|
||||
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
|
||||
list-style-image: url(chrome://browser/skin/Search-glass.png);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.ac-result-type-tag,
|
||||
.autocomplete-treebody::-moz-tree-image(tag, treecolAutoCompleteImage) {
|
||||
list-style-image: url("chrome://browser/skin/places/tag.png");
|
||||
|
@ -993,6 +993,13 @@ statusbarpanel#statusbar-display {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.ac-result-type-keyword,
|
||||
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
|
||||
list-style-image: url(chrome://global/skin/icons/search-textbox.png);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
richlistitem[selected="true"][current="true"] > hbox > .ac-result-type-bookmark,
|
||||
.autocomplete-treebody::-moz-tree-image(selected, current, bookmark, treecolAutoCompleteImage) {
|
||||
list-style-image: url("chrome://browser/skin/places/star-icons.png");
|
||||
|
@ -1184,6 +1184,14 @@ statusbarpanel#statusbar-display {
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.ac-result-type-keyword,
|
||||
.autocomplete-treebody::-moz-tree-image(keyword, treecolAutoCompleteImage) {
|
||||
list-style-image: url(chrome://browser/skin/Search-glass.png);
|
||||
-moz-image-region: rect(0px 32px 16px 16px);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
.ac-result-type-tag,
|
||||
.autocomplete-treebody::-moz-tree-image(tag, treecolAutoCompleteImage) {
|
||||
list-style-image: url("chrome://browser/skin/places/tag.png");
|
||||
|
@ -645,6 +645,7 @@ protected:
|
||||
nsCOMPtr<mozIStorageStatement> mDBAutoCompleteQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBPreviousQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBAdaptiveQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBKeywordQuery; // kAutoCompleteIndex_* results
|
||||
nsCOMPtr<mozIStorageStatement> mDBFeedbackIncrease;
|
||||
|
||||
/**
|
||||
@ -667,6 +668,8 @@ protected:
|
||||
PRInt32 mAutoCompleteSearchTimeout;
|
||||
nsCOMPtr<nsITimer> mAutoCompleteTimer;
|
||||
|
||||
// Original search string for case-sensitive usage
|
||||
nsString mOrigSearchString;
|
||||
// Search string and tokens for case-insensitive matching
|
||||
nsString mCurrentSearchString;
|
||||
nsStringArray mCurrentSearchTokens;
|
||||
@ -693,12 +696,14 @@ protected:
|
||||
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_ADAPTIVE,
|
||||
QUERY_FULL
|
||||
};
|
||||
|
@ -286,6 +286,24 @@ nsNavHistory::CreateAutoCompleteQueries()
|
||||
rv = mDBConn->CreateStatement(sql, getter_AddRefs(mDBAdaptiveQuery));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
sql = NS_LITERAL_CSTRING(
|
||||
"SELECT REPLACE(s.url, '%s', ?2) search_url, h.title, IFNULL(f.url, "
|
||||
"(SELECT f.url "
|
||||
"FROM moz_places r "
|
||||
"JOIN moz_favicons f ON f.id = r.favicon_id "
|
||||
"WHERE r.rev_host = s.rev_host "
|
||||
"ORDER BY r.frecency DESC LIMIT 1)), "
|
||||
"b.parent, b.title, NULL "
|
||||
"FROM moz_keywords k "
|
||||
"JOIN moz_bookmarks b ON b.keyword_id = k.id "
|
||||
"JOIN moz_places s ON s.id = b.fk "
|
||||
"LEFT OUTER JOIN moz_places h ON h.url = search_url "
|
||||
"LEFT OUTER JOIN moz_favicons f ON f.id = h.favicon_id "
|
||||
"WHERE LOWER(k.keyword) = LOWER(?1) "
|
||||
"ORDER BY h.frecency DESC");
|
||||
rv = mDBConn->CreateStatement(sql, getter_AddRefs(mDBKeywordQuery));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
sql = NS_LITERAL_CSTRING(
|
||||
// Leverage the PRIMARY KEY (place_id, input) to insert/update entries
|
||||
"INSERT OR REPLACE INTO moz_inputhistory "
|
||||
@ -340,6 +358,12 @@ nsNavHistory::PerformAutoComplete()
|
||||
nsresult rv;
|
||||
// Only do some extra searches on the first chunk
|
||||
if (!mCurrentChunkOffset) {
|
||||
// Only show keywords if there's a search
|
||||
if (mCurrentSearchTokens.Count()) {
|
||||
rv = AutoCompleteKeywordSearch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
// Get adaptive results first
|
||||
rv = AutoCompleteAdaptiveSearch();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -444,10 +468,12 @@ nsNavHistory::StartSearch(const nsAString & aSearchString,
|
||||
PRUint32 prevMatchCount = mCurrentResultURLs.Count();
|
||||
nsAutoString prevSearchString(mCurrentSearchString);
|
||||
|
||||
// Keep a copy of the original search for case-sensitive usage
|
||||
mOrigSearchString = aSearchString;
|
||||
// Remove whitespace, see bug #392141 for details
|
||||
mOrigSearchString.Trim(" \r\n\t\b");
|
||||
// Copy the input search string for case-insensitive search
|
||||
ToLowerCase(aSearchString, mCurrentSearchString);
|
||||
// remove whitespace, see bug #392141 for details
|
||||
mCurrentSearchString.Trim(" \r\n\t\b");
|
||||
ToLowerCase(mOrigSearchString, mCurrentSearchString);
|
||||
|
||||
mCurrentListener = aListener;
|
||||
|
||||
@ -608,6 +634,34 @@ nsNavHistory::AddSearchToken(nsAutoString &aToken)
|
||||
mCurrentSearchTokens.AppendString(aToken);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistory::AutoCompleteKeywordSearch()
|
||||
{
|
||||
mozStorageStatementScoper scope(mDBKeywordQuery);
|
||||
|
||||
// Get the keyword parameters to replace the %s in the keyword search
|
||||
nsCAutoString params;
|
||||
PRInt32 paramPos = mOrigSearchString.FindChar(' ') + 1;
|
||||
// Make sure to escape them as if they were the query in a url, so " " become
|
||||
// "+"; "+" become "%2B"; non-ascii escaped
|
||||
NS_Escape(NS_ConvertUTF16toUTF8(Substring(mOrigSearchString, paramPos)),
|
||||
params, url_XPAlphas);
|
||||
|
||||
// The first search term might be a keyword
|
||||
const nsAString &keyword = Substring(mOrigSearchString, 0,
|
||||
paramPos ? paramPos - 1 : mOrigSearchString.Length());
|
||||
nsresult rv = mDBKeywordQuery->BindStringParameter(0, keyword);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mDBKeywordQuery->BindUTF8StringParameter(1, params);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = AutoCompleteProcessSearch(mDBKeywordQuery, QUERY_KEYWORD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNavHistory::AutoCompleteAdaptiveSearch()
|
||||
{
|
||||
@ -734,6 +788,17 @@ nsNavHistory::AutoCompleteProcessSearch(mozIStorageStatement* aQuery,
|
||||
|
||||
nsString style;
|
||||
switch (aType) {
|
||||
case QUERY_KEYWORD: {
|
||||
// If we don't have a title, then we must have a keyword, so let the
|
||||
// UI know it's a keyword; otherwise, we found an exact page match,
|
||||
// so just show the page like a regular result
|
||||
if (entryTitle.IsEmpty())
|
||||
style = NS_LITERAL_STRING("keyword");
|
||||
else
|
||||
title = entryTitle;
|
||||
|
||||
break;
|
||||
}
|
||||
case QUERY_FULL: {
|
||||
// If we get any results, there's potentially another chunk to proces
|
||||
if (aHasMoreResults)
|
||||
@ -776,10 +841,15 @@ nsNavHistory::AutoCompleteProcessSearch(mozIStorageStatement* aQuery,
|
||||
|
||||
// Tags have a special style to show a tag icon; otherwise, style the
|
||||
// bookmarks that aren't feed items and feed URIs as bookmark
|
||||
style = showTags ? NS_LITERAL_STRING("tag") : (parentId &&
|
||||
!mLivemarkFeedItemIds.Get(parentId, &dummy)) ||
|
||||
mLivemarkFeedURIs.Get(escapedEntryURL, &dummy) ?
|
||||
NS_LITERAL_STRING("bookmark") : NS_LITERAL_STRING("favicon");
|
||||
if (style.IsEmpty()) {
|
||||
if (showTags)
|
||||
style = NS_LITERAL_STRING("tag");
|
||||
else if ((parentId && !mLivemarkFeedItemIds.Get(parentId, &dummy)) ||
|
||||
mLivemarkFeedURIs.Get(escapedEntryURL, &dummy))
|
||||
style = NS_LITERAL_STRING("bookmark");
|
||||
else
|
||||
style = NS_LITERAL_STRING("favicon");
|
||||
}
|
||||
|
||||
// Get the URI for the favicon
|
||||
nsCAutoString faviconSpec;
|
||||
|
@ -0,0 +1,88 @@
|
||||
/* ***** 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 Test Code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Edward Lee <edward.lee@engineering.uiuc.edu>.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2008
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
*
|
||||
* 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 ***** */
|
||||
|
||||
/**
|
||||
* Test for bug 392143 that puts keyword results into the autocomplete. Makes
|
||||
* sure that multiple parameter queries get spaces converted to +, + converted
|
||||
* to %2B, non-ascii become escaped, and pages in history that match the
|
||||
* keyword uses the page's title.
|
||||
*/
|
||||
|
||||
// Details for the keyword bookmark
|
||||
let keyBase = "http://abc/?search=";
|
||||
let keyKey = "key";
|
||||
|
||||
let unescaped = "ユニコード";
|
||||
let pageInHistory = "ThisPageIsInHistory";
|
||||
|
||||
// Define some shared uris and titles (each page needs its own uri)
|
||||
let kURIs = [
|
||||
keyBase + "%s",
|
||||
keyBase + "term",
|
||||
keyBase + "multi+word",
|
||||
keyBase + "blocking%2B",
|
||||
keyBase + unescaped,
|
||||
keyBase + pageInHistory,
|
||||
];
|
||||
let kTitles = [
|
||||
"Generic page title",
|
||||
"Keyword title",
|
||||
];
|
||||
|
||||
// Add the keyword bookmark
|
||||
addPageBook(0, 0, 1, [], keyKey);
|
||||
// Add in the "fake pages" for keyword searches
|
||||
gPages[1] = [1,1];
|
||||
gPages[2] = [2,1];
|
||||
gPages[3] = [3,1];
|
||||
gPages[4] = [4,1];
|
||||
// Add a page into history
|
||||
addPageBook(5, 0);
|
||||
|
||||
// Provide for each test: description; search terms; array of gPages indices of
|
||||
// pages that should match; optional function to be run before the test
|
||||
let gTests = [
|
||||
["0: Plain keyword query",
|
||||
keyKey + " term", [1]],
|
||||
["1: Multi-word keyword query",
|
||||
keyKey + " multi word", [2]],
|
||||
["2: Keyword query with +",
|
||||
keyKey + " blocking+", [3]],
|
||||
["3: Unescaped term in query",
|
||||
keyKey + " " + unescaped, [4]],
|
||||
["4: Keyword that happens to match a page",
|
||||
keyKey + " " + pageInHistory, [5]],
|
||||
];
|
@ -1152,6 +1152,7 @@
|
||||
<xul:description anonid="title" class="ac-normal-text ac-comment" xbl:inherits="selected"/>
|
||||
<xul:hbox anonid="extra-box" class="ac-extra" align="center" hidden="true">
|
||||
<xul:image class="ac-result-type-tag"/>
|
||||
<xul:label class="ac-normal-text ac-comment" xbl:inherits="selected" value=":"/>
|
||||
<xul:description anonid="extra" class="ac-normal-text ac-comment" xbl:inherits="selected"/>
|
||||
</xul:hbox>
|
||||
</xul:hbox>
|
||||
@ -1385,6 +1386,8 @@
|
||||
if (type == "tag") {
|
||||
// Configure the extra box for tags display
|
||||
this._extraBox.hidden = false;
|
||||
this._extraBox.childNodes[0].hidden = false;
|
||||
this._extraBox.childNodes[1].hidden = true;
|
||||
this._extraBox.flex = 1;
|
||||
this._extraBox.pack = "end";
|
||||
|
||||
@ -1400,6 +1403,23 @@
|
||||
|
||||
// Treat tagged matches as bookmarks for the star
|
||||
type = "bookmark";
|
||||
} else if (type == "keyword") {
|
||||
// Configure the extra box for keyword display
|
||||
this._extraBox.hidden = false;
|
||||
this._extraBox.childNodes[0].hidden = true;
|
||||
this._extraBox.childNodes[1].hidden = false;
|
||||
this._extraBox.flex = 0;
|
||||
this._extraBox.pack = "start";
|
||||
|
||||
// Put the parameters next to the title if we have any
|
||||
let search = this.getAttribute("text");
|
||||
let params = search.substr(search.indexOf(' ') + 1);
|
||||
|
||||
// Emphasize the keyword parameters
|
||||
this._setUpDescription(this._extra, params);
|
||||
|
||||
// Don't emphasize keyword searches in the title or url
|
||||
this.setAttribute("text", "");
|
||||
} else {
|
||||
// Hide the title's extra box if we don't need extra stuff
|
||||
this._extraBox.hidden = true;
|
||||
|
Loading…
Reference in New Issue
Block a user