All pastes #88717 Raw Edit

Anonymous

public text v1 · immutable
#88717 ·published 2006-07-15 07:44 UTC
rendered paste body
==Searchbar autocomplete background==
nsSearchSuggest implements nsIAutoCompleteSearch, and is used for the search suggest and form history results for the search bar. When it's startSearch is called, it sends an async request for the autocomplete results (using XMLHttpRequest), and calls startSearch on the form history implementation of nsIAutoCompleteSearch (1). It implements nsIAutoCompleteObserver to retrieve the results from that search.

(1) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/nsSearchSuggestions.js&rev=1.6&mark=634,638#592
(2) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/nsSearchSuggestions.js&rev=1.6#337

The request to form history always comes back first, because it's faster than the XMLHttpRequest. This calls onSearchResult (3), where the form history results are cached and one of two things happen:

1) if the request was never sent, the search results are sent to the search bar immediately
2) if the XMLHttpRequest is still pending, a 500 ms ONE_SHOT timer is started

(3) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/nsSearchSuggestions.js&rev=1.6#337

In the second case, notify is called 500ms later to check on the progress of the suggest results (4).

(4) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/nsSearchSuggestions.js&rev=1.6#318

If the request still hasn't returned (if ._listener is non-null), then the form history results are sent and the request is canceled.

So the two ways that the listener gets notified of results is: at the end of a successful XMLHttpRequest (5), or after the XMLHttpRequest has timed out (6).

(5) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/nsSearchSuggestions.js&rev=1.6&mark=551#530
(6) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/nsSearchSuggestions.js&rev=1.6&mark=323#318

==Autocomplete widget==
The autocomplete widget used in the search bar (and the location bar) works like this:
On each input, calls nsAutoCompleteController::HandleText(), which starts a 200 ms timer, which is reset after each input event. If the timer expires, nsAutoCompleteController::StartSearch is called, which calls startSearch on all of the input's nsIAutoCompleteSearch's (the search bar only has one, the one described above). This starts the asynchronous search for autocomplete results.

When you press enter, the autocomplete widget caches the enter event, and calls nsAutoCompleteController::HandleEnter() (7). HandleEnter calls EnterMatch, which checks for in-progress searches and sets a member variable (mEnterAfterSearch) and returns if there are any searches pending (8). When the search finishes, it calls nsAutoCompleteController::onSearchResult(), which notices that this is the last pending search and calls ProcessResult, which calls HandleEnter, which sees that mEnterAfterSearch is true, so eventually calls mInput->onTextEntered (10) (mInput is the autocomplete textbox). This call to onTextEntered is what triggers the search (11).

(7) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp&rev=1.50#274
(8) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp&rev=1.50&mark=1061#1057
(9) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp&rev=1.50#637
(10) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp&mark=1114&rev=1.50#1113
(11) http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/browser/components/search/content/search.xml&rev=1.77#653

Here's the bug:
HandleText calls stopSearch on the nsIAutocompleteSearch, since it is assumed that we have a new string and thus want to start a new search. In testing, this can happen after the form history results are in (after onResultsReady in nsSearchSuggestions is called), but before the timer has expired on the search. The implementation of stopSearch in nsSearchSuggestions cancels the timer, which means that the timer will never run out, and the listener will never receive results. Since the listener (the nsIAutoCompleteObserver implementation in nsAutocompleteController) depends on receiving the results to know when to fire the onTextEntered event, the event is never fired, and no search happens.