summaryrefslogtreecommitdiffstats
path: root/toolkit/components/autocomplete
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/autocomplete')
-rw-r--r--toolkit/components/autocomplete/nsAutoCompleteController.cpp122
-rw-r--r--toolkit/components/autocomplete/nsAutoCompleteSimpleResult.cpp23
-rw-r--r--toolkit/components/autocomplete/nsAutoCompleteSimpleResult.h2
-rw-r--r--toolkit/components/autocomplete/nsIAutoCompleteResult.idl7
-rw-r--r--toolkit/components/autocomplete/nsIAutoCompleteSimpleResult.idl6
-rw-r--r--toolkit/components/autocomplete/tests/unit/head_autocomplete.js5
-rw-r--r--toolkit/components/autocomplete/tests/unit/test_hiddenResult.js76
-rw-r--r--toolkit/components/autocomplete/tests/unit/test_popupSelectionVsDefaultCompleteValue.js71
-rw-r--r--toolkit/components/autocomplete/tests/unit/xpcshell.ini2
9 files changed, 262 insertions, 52 deletions
diff --git a/toolkit/components/autocomplete/nsAutoCompleteController.cpp b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
index 5d69ea1a3..9ca382fe5 100644
--- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
@@ -1637,58 +1637,72 @@ nsAutoCompleteController::ProcessResult(int32_t aSearchIndex, nsIAutoCompleteRes
MOZ_ASSERT(mResults.Count() >= aSearchIndex + 1,
"aSearchIndex should always be valid for mResults");
- uint32_t oldRowCount = mRowCount;
- // If the search failed, increase the match count to include the error
- // description.
- if (searchResult == nsIAutoCompleteResult::RESULT_FAILURE) {
- nsAutoString error;
- aResult->GetErrorDescription(error);
- if (!error.IsEmpty()) {
- ++mRowCount;
- if (mTree) {
- mTree->RowCountChanged(oldRowCount, 1);
+ bool isTypeAheadResult = false;
+ aResult->GetTypeAheadResult(&isTypeAheadResult);
+
+ if (!isTypeAheadResult) {
+ uint32_t oldRowCount = mRowCount;
+ // If the search failed, increase the match count to include the error
+ // description.
+ if (searchResult == nsIAutoCompleteResult::RESULT_FAILURE) {
+ nsAutoString error;
+ aResult->GetErrorDescription(error);
+ if (!error.IsEmpty()) {
+ ++mRowCount;
+ if (mTree) {
+ mTree->RowCountChanged(oldRowCount, 1);
+ }
}
- }
- } else if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
- searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
- // Increase the match count for all matches in this result.
- uint32_t totalMatchCount = 0;
- for (uint32_t i = 0; i < mResults.Length(); i++) {
- nsIAutoCompleteResult* result = mResults.SafeObjectAt(i);
- if (result) {
- uint32_t matchCount = 0;
- result->GetMatchCount(&matchCount);
- totalMatchCount += matchCount;
+ } else if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
+ searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
+ // Increase the match count for all matches in this result.
+ uint32_t totalMatchCount = 0;
+ for (uint32_t i = 0; i < mResults.Length(); i++) {
+ nsIAutoCompleteResult* result = mResults.SafeObjectAt(i);
+ if (result) {
+ // not all results implement this, so it can likely fail.
+ bool typeAhead = false;
+ result->GetTypeAheadResult(&typeAhead);
+ if (!typeAhead) {
+ uint32_t matchCount = 0;
+ result->GetMatchCount(&matchCount);
+ totalMatchCount += matchCount;
+ }
+ }
}
- }
- uint32_t delta = totalMatchCount - oldRowCount;
+ uint32_t delta = totalMatchCount - oldRowCount;
- mRowCount += delta;
- if (mTree) {
- mTree->RowCountChanged(oldRowCount, delta);
+ mRowCount += delta;
+ if (mTree) {
+ mTree->RowCountChanged(oldRowCount, delta);
+ }
}
- }
- // Try to autocomplete the default index for this search.
- // Do this before invalidating so the binding knows about it.
- CompleteDefaultIndex(aSearchIndex);
+ // Try to autocomplete the default index for this search.
+ // Do this before invalidating so the binding knows about it.
+ CompleteDefaultIndex(aSearchIndex);
- // Refresh the popup view to display the new search results
- nsCOMPtr<nsIAutoCompletePopup> popup;
- input->GetPopup(getter_AddRefs(popup));
- NS_ENSURE_TRUE(popup != nullptr, NS_ERROR_FAILURE);
- popup->Invalidate(nsIAutoCompletePopup::INVALIDATE_REASON_NEW_RESULT);
+ // Refresh the popup view to display the new search results
+ nsCOMPtr<nsIAutoCompletePopup> popup;
+ input->GetPopup(getter_AddRefs(popup));
+ NS_ENSURE_TRUE(popup != nullptr, NS_ERROR_FAILURE);
+ popup->Invalidate(nsIAutoCompletePopup::INVALIDATE_REASON_NEW_RESULT);
- uint32_t minResults;
- input->GetMinResultsForPopup(&minResults);
+ uint32_t minResults;
+ input->GetMinResultsForPopup(&minResults);
- // Make sure the popup is open, if necessary, since we now have at least one
- // search result ready to display. Don't force the popup closed if we might
- // get results in the future to avoid unnecessarily canceling searches.
- if (mRowCount || !minResults) {
- OpenPopup();
- } else if (mSearchesOngoing == 0) {
- ClosePopup();
+ // Make sure the popup is open, if necessary, since we now have at least one
+ // search result ready to display. Don't force the popup closed if we might
+ // get results in the future to avoid unnecessarily canceling searches.
+ if (mRowCount || !minResults) {
+ OpenPopup();
+ } else if (mSearchesOngoing == 0) {
+ ClosePopup();
+ }
+ } else if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
+ searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
+ // Try to autocomplete the default index for this search.
+ CompleteDefaultIndex(aSearchIndex);
}
return NS_OK;
@@ -2033,14 +2047,20 @@ nsAutoCompleteController::RowIndexToSearch(int32_t aRowIndex, int32_t *aSearchIn
uint32_t rowCount = 0;
- uint16_t searchResult;
- result->GetSearchResult(&searchResult);
+ // Skip past the result completely if it is marked as hidden
+ bool isTypeAheadResult = false;
+ result->GetTypeAheadResult(&isTypeAheadResult);
- // Find out how many results were provided by the
- // current nsIAutoCompleteSearch.
- if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
- searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
- result->GetMatchCount(&rowCount);
+ if (!isTypeAheadResult) {
+ uint16_t searchResult;
+ result->GetSearchResult(&searchResult);
+
+ // Find out how many results were provided by the
+ // current nsIAutoCompleteSearch.
+ if (searchResult == nsIAutoCompleteResult::RESULT_SUCCESS ||
+ searchResult == nsIAutoCompleteResult::RESULT_SUCCESS_ONGOING) {
+ result->GetMatchCount(&rowCount);
+ }
}
// If the given row index is within the results range
diff --git a/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.cpp b/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.cpp
index 9fd2c0022..683ac462a 100644
--- a/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.cpp
@@ -43,7 +43,8 @@ struct AutoCompleteSimpleResultMatch
nsAutoCompleteSimpleResult::nsAutoCompleteSimpleResult() :
mDefaultIndex(-1),
- mSearchResult(RESULT_NOMATCH)
+ mSearchResult(RESULT_NOMATCH),
+ mTypeAheadResult(false)
{
}
@@ -66,6 +67,12 @@ nsAutoCompleteSimpleResult::AppendResult(nsIAutoCompleteResult* aResult)
mErrorDescription = errorDescription;
}
+ bool typeAheadResult = false;
+ if (NS_SUCCEEDED(aResult->GetTypeAheadResult(&typeAheadResult)) &&
+ typeAheadResult) {
+ mTypeAheadResult = typeAheadResult;
+ }
+
int32_t defaultIndex = -1;
if (NS_SUCCEEDED(aResult->GetDefaultIndex(&defaultIndex)) &&
defaultIndex >= 0) {
@@ -166,6 +173,20 @@ nsAutoCompleteSimpleResult::SetErrorDescription(
return NS_OK;
}
+// typeAheadResult
+NS_IMETHODIMP
+nsAutoCompleteSimpleResult::GetTypeAheadResult(bool *aTypeAheadResult)
+{
+ *aTypeAheadResult = mTypeAheadResult;
+ return NS_OK;
+}
+NS_IMETHODIMP
+nsAutoCompleteSimpleResult::SetTypeAheadResult(bool aTypeAheadResult)
+{
+ mTypeAheadResult = aTypeAheadResult;
+ return NS_OK;
+}
+
NS_IMETHODIMP
nsAutoCompleteSimpleResult::InsertMatchAt(int32_t aIndex,
const nsAString& aValue,
diff --git a/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.h b/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.h
index 28968aa57..61ee542e4 100644
--- a/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.h
+++ b/toolkit/components/autocomplete/nsAutoCompleteSimpleResult.h
@@ -38,6 +38,8 @@ protected:
int32_t mDefaultIndex;
uint32_t mSearchResult;
+ bool mTypeAheadResult;
+
nsCOMPtr<nsIAutoCompleteSimpleResultListener> mListener;
};
diff --git a/toolkit/components/autocomplete/nsIAutoCompleteResult.idl b/toolkit/components/autocomplete/nsIAutoCompleteResult.idl
index c719d9427..9ae22ade7 100644
--- a/toolkit/components/autocomplete/nsIAutoCompleteResult.idl
+++ b/toolkit/components/autocomplete/nsIAutoCompleteResult.idl
@@ -50,6 +50,13 @@ interface nsIAutoCompleteResult : nsISupports
readonly attribute unsigned long matchCount;
/**
+ * If true, the results will not be displayed in the popup. However,
+ * if a default index is specified, the default item will still be
+ * completed in the input.
+ */
+ readonly attribute boolean typeAheadResult;
+
+ /**
* Get the value of the result at the given index
*/
AString getValueAt(in long index);
diff --git a/toolkit/components/autocomplete/nsIAutoCompleteSimpleResult.idl b/toolkit/components/autocomplete/nsIAutoCompleteSimpleResult.idl
index 5e92e037a..6a8827ab8 100644
--- a/toolkit/components/autocomplete/nsIAutoCompleteSimpleResult.idl
+++ b/toolkit/components/autocomplete/nsIAutoCompleteSimpleResult.idl
@@ -42,6 +42,12 @@ interface nsIAutoCompleteSimpleResult : nsIAutoCompleteResult
void setSearchResult(in unsigned short aSearchResult);
/**
+ * A writer for the readonly attribute 'typeAheadResult', typically set
+ * because a result is only intended for type-ahead completion.
+ */
+ void setTypeAheadResult(in boolean aHidden);
+
+ /**
* Inserts a match consisting of the given value, comment, image, style and
* the value to use for defaultIndex completion at a given position.
* @param aIndex
diff --git a/toolkit/components/autocomplete/tests/unit/head_autocomplete.js b/toolkit/components/autocomplete/tests/unit/head_autocomplete.js
index 1443879f0..5a458bdf4 100644
--- a/toolkit/components/autocomplete/tests/unit/head_autocomplete.js
+++ b/toolkit/components/autocomplete/tests/unit/head_autocomplete.js
@@ -85,6 +85,11 @@ AutoCompleteResultBase.prototype = {
defaultIndex: -1,
+ _typeAheadResult: false,
+ get typeAheadResult() {
+ return this._typeAheadResult;
+ },
+
get matchCount() {
return this._values.length;
},
diff --git a/toolkit/components/autocomplete/tests/unit/test_hiddenResult.js b/toolkit/components/autocomplete/tests/unit/test_hiddenResult.js
new file mode 100644
index 000000000..8e2485716
--- /dev/null
+++ b/toolkit/components/autocomplete/tests/unit/test_hiddenResult.js
@@ -0,0 +1,76 @@
+/* Any copyright is dedicated to the Public Domain.
+ http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function AutoCompleteResult(aValues) {
+ this._values = aValues;
+ this.defaultIndex = -1;
+ this._typeAheadResult = false;
+}
+AutoCompleteResult.prototype = Object.create(AutoCompleteResultBase.prototype);
+
+function AutoCompleteTypeAheadResult(aValues) {
+ this._values = aValues;
+ this.defaultIndex = 0;
+ this._typeAheadResult = true;
+}
+AutoCompleteTypeAheadResult.prototype = Object.create(AutoCompleteResultBase.prototype);
+
+
+/**
+ * Test AutoComplete with multiple AutoCompleteSearch sources, with one of them
+ * being hidden from the popup, but can still do typeahead completion.
+ */
+function run_test() {
+ do_test_pending();
+
+ var inputStr = "moz";
+
+ // Type ahead result
+ var searchTypeAhead = new AutoCompleteSearchBase("search1",
+ new AutoCompleteTypeAheadResult(["mozillaTest1"]));
+ // Regular result
+ var searchNormal = new AutoCompleteSearchBase("search2",
+ new AutoCompleteResult(["mozillaTest2"]));
+
+ // Register searches so AutoCompleteController can find them
+ registerAutoCompleteSearch(searchNormal);
+ registerAutoCompleteSearch(searchTypeAhead);
+
+ // Make an AutoCompleteInput that uses our searches
+ // and confirms results on search complete.
+ var input = new AutoCompleteInputBase([searchTypeAhead.name, searchNormal.name]);
+ input.completeDefaultIndex = true;
+ input.textValue = inputStr;
+
+ // Caret must be at the end. Autofill doesn't happen unless you're typing
+ // characters at the end.
+ var strLen = inputStr.length;
+ input.selectTextRange(strLen, strLen);
+ do_check_eq(input.selectionStart, strLen);
+ do_check_eq(input.selectionEnd, strLen);
+
+ var controller = Cc["@mozilla.org/autocomplete/controller;1"].
+ getService(Ci.nsIAutoCompleteController);
+
+ controller.input = input;
+ controller.startSearch(inputStr);
+
+ input.onSearchComplete = function() {
+ // Hidden results should still be able to do inline autocomplete
+ do_check_eq(input.textValue, "mozillaTest1");
+
+ // Now, let's fill the textbox with the first result of the popup.
+ // The first search is marked as hidden, so we must always get the
+ // second search.
+ controller.handleEnter(true);
+ do_check_eq(input.textValue, "mozillaTest2");
+
+ // Only one item in the popup.
+ do_check_eq(controller.matchCount, 1);
+
+ // Unregister searches
+ unregisterAutoCompleteSearch(searchNormal);
+ unregisterAutoCompleteSearch(searchTypeAhead);
+ do_test_finished();
+ };
+}
diff --git a/toolkit/components/autocomplete/tests/unit/test_popupSelectionVsDefaultCompleteValue.js b/toolkit/components/autocomplete/tests/unit/test_popupSelectionVsDefaultCompleteValue.js
new file mode 100644
index 000000000..fb4153355
--- /dev/null
+++ b/toolkit/components/autocomplete/tests/unit/test_popupSelectionVsDefaultCompleteValue.js
@@ -0,0 +1,71 @@
+/* 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/. */
+
+function AutoCompleteTypeAheadResult(aValues, aFinalCompleteValues) {
+ this._values = aValues;
+ this._finalCompleteValues = aFinalCompleteValues;
+ this.defaultIndex = 0;
+ this._typeAheadResult = true;
+}
+AutoCompleteTypeAheadResult.prototype = Object.create(AutoCompleteResultBase.prototype);
+
+function AutoCompleteResult(aValues) {
+ this._values = aValues;
+}
+AutoCompleteResult.prototype = Object.create(AutoCompleteResultBase.prototype);
+
+function AutoCompleteInput(aSearches) {
+ this.searches = aSearches;
+ this.popupOpen = true;
+ this.completeDefaultIndex = true;
+ this.completeSelectedIndex = true;
+}
+AutoCompleteInput.prototype = Object.create(AutoCompleteInputBase.prototype);
+
+function run_test() {
+ run_next_test();
+}
+
+add_test(function test_handleEnter() {
+ doSearch("moz", function(aController) {
+ do_check_eq(aController.input.textValue, "mozilla.com");
+ aController.handleEnter(true);
+ do_check_eq(aController.input.textValue, "mozilla.org");
+ });
+});
+
+function doSearch(aSearchString, aOnCompleteCallback) {
+ let typeAheadSearch = new AutoCompleteSearchBase(
+ "typeAheadSearch",
+ new AutoCompleteTypeAheadResult([ "mozilla.com" ], [ "http://www.mozilla.com" ])
+ );
+ registerAutoCompleteSearch(typeAheadSearch);
+
+ let search = new AutoCompleteSearchBase(
+ "search",
+ new AutoCompleteResult([ "mozilla.org" ])
+ );
+ registerAutoCompleteSearch(search);
+
+ let controller = Cc["@mozilla.org/autocomplete/controller;1"].
+ getService(Ci.nsIAutoCompleteController);
+
+ // Make an AutoCompleteInput that uses our searches and confirms results.
+ let input = new AutoCompleteInput([ typeAheadSearch.name, search.name ]);
+ input.textValue = aSearchString;
+
+ // Caret must be at the end for autofill to happen.
+ let strLen = aSearchString.length;
+ input.selectTextRange(strLen, strLen);
+ controller.input = input;
+ controller.startSearch(aSearchString);
+
+ input.onSearchComplete = function onSearchComplete() {
+ aOnCompleteCallback(controller);
+
+ // Clean up.
+ unregisterAutoCompleteSearch(search);
+ run_next_test();
+ };
+}
diff --git a/toolkit/components/autocomplete/tests/unit/xpcshell.ini b/toolkit/components/autocomplete/tests/unit/xpcshell.ini
index 4d193965c..daf89db17 100644
--- a/toolkit/components/autocomplete/tests/unit/xpcshell.ini
+++ b/toolkit/components/autocomplete/tests/unit/xpcshell.ini
@@ -18,7 +18,9 @@ tail =
[test_finalCompleteValue_forceComplete.js]
[test_finalCompleteValueSelectedIndex.js]
[test_finalDefaultCompleteValue.js]
+[test_hiddenResult.js]
[test_immediate_search.js]
[test_insertMatchAt.js]
+[test_popupSelectionVsDefaultCompleteValue.js]
[test_previousResult.js]
[test_stopSearch.js]