summaryrefslogtreecommitdiffstats
path: root/toolkit/components/autocomplete/nsAutoCompleteController.h
blob: fdaf245f56bb7e1c62b9baf6d6cecab0e90b2e1e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/* 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/. */

#ifndef __nsAutoCompleteController__
#define __nsAutoCompleteController__

#include "nsIAutoCompleteController.h"

#include "nsCOMPtr.h"
#include "nsIAutoCompleteInput.h"
#include "nsIAutoCompletePopup.h"
#include "nsIAutoCompleteResult.h"
#include "nsIAutoCompleteSearch.h"
#include "nsINamed.h"
#include "nsString.h"
#include "nsITimer.h"
#include "nsTArray.h"
#include "nsCOMArray.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/dom/Element.h"

class nsAutoCompleteController final : public nsIAutoCompleteController,
                                       public nsIAutoCompleteObserver,
                                       public nsITimerCallback,
                                       public nsINamed {
 public:
  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
  NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsAutoCompleteController,
                                           nsIAutoCompleteController)
  NS_DECL_NSIAUTOCOMPLETECONTROLLER
  NS_DECL_NSIAUTOCOMPLETEOBSERVER
  NS_DECL_NSITIMERCALLBACK
  NS_DECL_NSINAMED

  nsAutoCompleteController();

 protected:
  MOZ_CAN_RUN_SCRIPT virtual ~nsAutoCompleteController();

  /**
   * SetValueOfInputTo() sets value of mInput to aValue.
   */
  void SetValueOfInputTo(const nsString& aValue);

  /**
   * SetSearchStringInternal() sets both mSearchString and mSetValue to
   * aSearchString.
   */
  void SetSearchStringInternal(const nsAString& aSearchString) {
    mSearchString = mSetValue = aSearchString;
  }

  MOZ_CAN_RUN_SCRIPT nsresult OpenPopup();
  MOZ_CAN_RUN_SCRIPT nsresult ClosePopup();

  nsresult StartSearch();

  MOZ_CAN_RUN_SCRIPT nsresult DoSearches();
  nsresult BeforeSearches();
  MOZ_CAN_RUN_SCRIPT nsresult StartSearches();
  MOZ_CAN_RUN_SCRIPT void AfterSearches();
  nsresult ClearSearchTimer();
  void MaybeCompletePlaceholder();

  MOZ_CAN_RUN_SCRIPT nsresult ProcessResult(int32_t aSearchIndex,
                                            nsIAutoCompleteResult* aResult);
  MOZ_CAN_RUN_SCRIPT nsresult PostSearchCleanup();

  MOZ_CAN_RUN_SCRIPT nsresult EnterMatch(bool aIsPopupSelection,
                                         mozilla::dom::Event* aEvent);
  nsresult RevertTextValue();

  nsresult CompleteDefaultIndex(int32_t aResultIndex);
  nsresult CompleteValue(nsString& aValue);

  nsresult GetResultAt(int32_t aIndex, nsIAutoCompleteResult** aResult,
                       int32_t* aMatchIndex);
  nsresult GetResultValueAt(int32_t aIndex, bool aGetFinalValue,
                            nsAString& _retval);
  nsresult GetResultLabelAt(int32_t aIndex, nsAString& _retval);

  /**
   * Returns autocomplete popup for the autocomplete input. nsIAutoCompleteInput
   * can be implemented two different ways to return a popup. The first one is
   * to return a popup object implementing nsIAutoCompletePopup interface,
   * the second one is a DOM element representing a popup and implementing
   * that interface.
   */
  already_AddRefed<nsIAutoCompletePopup> GetPopup() {
    nsCOMPtr<nsIAutoCompletePopup> popup;
    mInput->GetPopup(getter_AddRefs(popup));
    if (popup) {
      return popup.forget();
    }

    nsCOMPtr<mozilla::dom::Element> popupEl;
    mInput->GetPopupElement(getter_AddRefs(popupEl));
    if (popupEl) {
      return popupEl->AsAutoCompletePopup();
    }
    return nullptr;
  }

 private:
  nsresult GetResultValueLabelAt(int32_t aIndex, bool aGetFinalValue,
                                 bool aGetValue, nsAString& _retval);

  /**
   * Gets and validates the defaultComplete result and the relative
   * defaultIndex value.
   *
   * @param aResultIndex
   *        Index of the defaultComplete result to be used.  Pass -1 to search
   *        for the first result providing a valid defaultIndex.
   * @param _result
   *        The found result.
   * @param _defaultIndex
   *        The defaultIndex relative to _result.
   */
  nsresult GetDefaultCompleteResult(int32_t aResultIndex,
                                    nsIAutoCompleteResult** _result,
                                    int32_t* _defaultIndex);

  /**
   * Gets the defaultComplete value to be suggested to the user.
   *
   * @param aResultIndex
   *        Index of the defaultComplete result to be used.
   * @param aPreserveCasing
   *        Whether user casing should be preserved.
   * @param _retval
   *        The value to be completed.
   */
  nsresult GetDefaultCompleteValue(int32_t aResultIndex, bool aPreserveCasing,
                                   nsAString& _retval);

  /**
   * Gets the defaultComplete value to be used when the user confirms the
   * current match.
   * The value is returned only if it case-insensitively matches the current
   * input text, otherwise the method returns NS_ERROR_FAILURE.
   * This happens because we don't want to replace text if the user backspaces
   * just before Enter.
   *
   * @param _retval
   *        The value to be completed.
   */
  nsresult GetFinalDefaultCompleteValue(nsAString& _retval);

  nsresult ClearResults(bool aIsSearching = false);

  nsresult MatchIndexToSearch(int32_t aMatchIndex, int32_t* aSearchIndex,
                              int32_t* aItemIndex);

  // members //////////////////////////////////////////

  nsCOMPtr<nsIAutoCompleteInput> mInput;

  nsCOMArray<nsIAutoCompleteSearch> mSearches;
  // This is used as a sparse array, always use SafeObjectAt to access it.
  nsCOMArray<nsIAutoCompleteResult> mResults;
  // Temporarily keeps the results alive while invoking startSearch() for each
  // search.  This is needed to allow the searches to reuse the previous result,
  // since otherwise the first search clears mResults.
  nsCOMArray<nsIAutoCompleteResult> mResultCache;

  nsCOMPtr<nsITimer> mTimer;

  // mSearchString stores value which is the original value of the input or
  // typed by the user.  When user is choosing an item from the popup, this
  // is NOT modified by the item because this is used for reverting the input
  // value when user cancels choosing an item from the popup.
  // This should be set through only SetSearchStringInternal().
  nsString mSearchString;
  nsString mPlaceholderCompletionString;
  // mSetValue stores value which is expected in the input.  So, if input's
  // value and mSetValue are different, it means somebody has changed the
  // value like JS of the web content.
  // This is set only by SetValueOfInputTo() or when modifying mSearchString
  // through SetSearchStringInternal().
  nsString mSetValue;
  bool mDefaultIndexCompleted;
  bool mPopupClosedByCompositionStart;

  // Whether autofill is allowed for the next search.
  bool mProhibitAutoFill;

  // Indicates whether the user cleared the autofilled part, returning to the
  // originally entered search string.
  bool mUserClearedAutoFill;

  enum CompositionState {
    eCompositionState_None,
    eCompositionState_Composing,
    eCompositionState_Committing
  };
  CompositionState mCompositionState;
  uint16_t mSearchStatus;
  uint32_t mMatchCount;
  uint32_t mSearchesOngoing;
  uint32_t mSearchesFailed;
  // The index of the match on the popup that was selected using the keyboard,
  // if the completeselectedindex attribute is set.
  // This is used to distinguish that selection (which would have been put in
  // the input on being selected) from a moused-over selectedIndex value. This
  // distinction is used to prevent mouse moves from inadvertently changing
  // what happens once the user hits Enter on the keyboard.
  // See bug 1043584 for more details.
  int32_t mCompletedSelectionIndex;
};

#endif /* __nsAutoCompleteController__ */