• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
6 #define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
7 
8 #include "base/gtest_prod_util.h"
9 #include "base/i18n/rtl.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/strings/string16.h"
12 #include "chrome/browser/ui/autofill/autofill_popup_controller.h"
13 #include "content/public/browser/render_widget_host.h"
14 #include "ui/gfx/font.h"
15 #include "ui/gfx/rect.h"
16 #include "ui/gfx/rect_f.h"
17 
18 namespace content {
19 struct NativeWebKeyboardEvent;
20 class RenderViewHost;
21 class WebContents;
22 }
23 
24 namespace gfx {
25 class Display;
26 }
27 
28 namespace ui {
29 class KeyEvent;
30 }
31 
32 namespace autofill {
33 
34 class AutofillPopupDelegate;
35 class AutofillPopupView;
36 
37 // This class is a controller for an AutofillPopupView. It implements
38 // AutofillPopupController to allow calls from AutofillPopupView. The
39 // other, public functions are available to its instantiator.
40 class AutofillPopupControllerImpl : public AutofillPopupController {
41  public:
42   // Creates a new |AutofillPopupControllerImpl|, or reuses |previous| if the
43   // construction arguments are the same. |previous| may be invalidated by this
44   // call. The controller will listen for keyboard input routed to
45   // |web_contents| while the popup is showing, unless |web_contents| is NULL.
46   static base::WeakPtr<AutofillPopupControllerImpl> GetOrCreate(
47       base::WeakPtr<AutofillPopupControllerImpl> previous,
48       base::WeakPtr<AutofillPopupDelegate> delegate,
49       content::WebContents* web_contents,
50       gfx::NativeView container_view,
51       const gfx::RectF& element_bounds,
52       base::i18n::TextDirection text_direction);
53 
54   // Shows the popup, or updates the existing popup with the given values.
55   void Show(const std::vector<base::string16>& names,
56             const std::vector<base::string16>& subtexts,
57             const std::vector<base::string16>& icons,
58             const std::vector<int>& identifiers);
59 
60   // Updates the data list values currently shown with the popup.
61   void UpdateDataListValues(const std::vector<base::string16>& values,
62                             const std::vector<base::string16>& labels);
63 
64   // Hides the popup and destroys the controller. This also invalidates
65   // |delegate_|.
66   virtual void Hide() OVERRIDE;
67 
68   // Invoked when the view was destroyed by by someone other than this class.
69   virtual void ViewDestroyed() OVERRIDE;
70 
71   bool HandleKeyPressEvent(const content::NativeWebKeyboardEvent& event);
72 
73   // Tells the view to capture mouse events. Must be called before |Show()|.
74   void set_hide_on_outside_click(bool hide_on_outside_click);
75 
76  protected:
77   FRIEND_TEST_ALL_PREFIXES(AutofillExternalDelegateBrowserTest,
78                            CloseWidgetAndNoLeaking);
79   FRIEND_TEST_ALL_PREFIXES(AutofillPopupControllerUnitTest,
80                            ProperlyResetController);
81 
82   AutofillPopupControllerImpl(base::WeakPtr<AutofillPopupDelegate> delegate,
83                               content::WebContents* web_contents,
84                               gfx::NativeView container_view,
85                               const gfx::RectF& element_bounds,
86                               base::i18n::TextDirection text_direction);
87   virtual ~AutofillPopupControllerImpl();
88 
89   // AutofillPopupController implementation.
90   virtual void UpdateBoundsAndRedrawPopup() OVERRIDE;
91   virtual void LineSelectedAtPoint(int x, int y) OVERRIDE;
92   virtual void LineAcceptedAtPoint(int x, int y) OVERRIDE;
93   virtual void SelectionCleared() OVERRIDE;
94   virtual bool ShouldRepostEvent(const ui::MouseEvent& event) OVERRIDE;
95   virtual void AcceptSuggestion(size_t index) OVERRIDE;
96   virtual int GetIconResourceID(
97       const base::string16& resource_name) const OVERRIDE;
98   virtual bool CanDelete(size_t index) const OVERRIDE;
99   virtual bool IsWarning(size_t index) const OVERRIDE;
100   virtual gfx::Rect GetRowBounds(size_t index) OVERRIDE;
101   virtual void SetPopupBounds(const gfx::Rect& bounds) OVERRIDE;
102   virtual const gfx::Rect& popup_bounds() const OVERRIDE;
103   virtual gfx::NativeView container_view() const OVERRIDE;
104   virtual const gfx::RectF& element_bounds() const OVERRIDE;
105   virtual bool IsRTL() const OVERRIDE;
106 
107   virtual const std::vector<base::string16>& names() const OVERRIDE;
108   virtual const std::vector<base::string16>& subtexts() const OVERRIDE;
109   virtual const std::vector<base::string16>& icons() const OVERRIDE;
110   virtual const std::vector<int>& identifiers() const OVERRIDE;
111 #if !defined(OS_ANDROID)
112   virtual const gfx::Font& GetNameFontForRow(size_t index) const OVERRIDE;
113   virtual const gfx::Font& subtext_font() const OVERRIDE;
114 #endif
115   virtual int selected_line() const OVERRIDE;
116   virtual bool hide_on_outside_click() const OVERRIDE;
117 
118   // Change which line is currently selected by the user.
119   void SetSelectedLine(int selected_line);
120 
121   // Increase the selected line by 1, properly handling wrapping.
122   void SelectNextLine();
123 
124   // Decrease the selected line by 1, properly handling wrapping.
125   void SelectPreviousLine();
126 
127   // The user has choosen the selected line.
128   bool AcceptSelectedLine();
129 
130   // The user has removed a suggestion.
131   bool RemoveSelectedLine();
132 
133   // Convert a y-coordinate to the closest line.
134   int LineFromY(int y);
135 
136   // Returns the height of a row depending on its type.
137   int GetRowHeightFromId(int identifier) const;
138 
139   // Returns true if the given id refers to an element that can be accepted.
140   bool CanAccept(int id);
141 
142   // Returns true if the popup still has non-options entries to show the user.
143   bool HasSuggestions();
144 
145   // Set the Autofill entry values. Exposed to allow tests to set these values
146   // without showing the popup.
147   void SetValues(const std::vector<base::string16>& names,
148                  const std::vector<base::string16>& subtexts,
149                  const std::vector<base::string16>& icons,
150                  const std::vector<int>& identifier);
151 
view()152   AutofillPopupView* view() { return view_; }
153 
154   // |view_| pass throughs (virtual for testing).
155   virtual void ShowView();
156   virtual void InvalidateRow(size_t row);
157 
158   // Protected so tests can access.
159 #if !defined(OS_ANDROID)
160   // Calculates the desired width of the popup based on its contents.
161   int GetDesiredPopupWidth() const;
162 
163   // Calculates the desired height of the popup based on its contents.
164   int GetDesiredPopupHeight() const;
165 
166   // Calculate the width of the row, excluding all the text. This provides
167   // the size of the row that won't be reducible (since all the text can be
168   // elided if there isn't enough space).
169   int RowWidthWithoutText(int row) const;
170 #endif
171 
172   base::WeakPtr<AutofillPopupControllerImpl> GetWeakPtr();
173 
174  private:
175   // Clear the internal state of the controller. This is needed to ensure that
176   // when the popup is reused it doesn't leak values between uses.
177   void ClearState();
178 
179   const gfx::Rect RoundedElementBounds() const;
180 #if !defined(OS_ANDROID)
181   // Calculates and sets the bounds of the popup, including placing it properly
182   // to prevent it from going off the screen.
183   void UpdatePopupBounds();
184 #endif
185 
186   // A helper function to get the display closest to the given point (virtual
187   // for testing).
188   virtual gfx::Display GetDisplayNearestPoint(const gfx::Point& point) const;
189 
190   // Calculates the width of the popup and the x position of it. These values
191   // will stay on the screen.
192   std::pair<int, int> CalculatePopupXAndWidth(
193       const gfx::Display& left_display,
194       const gfx::Display& right_display,
195       int popup_required_width) const;
196 
197   // Calculates the height of the popup and the y position of it. These values
198   // will stay on the screen.
199   std::pair<int, int> CalculatePopupYAndHeight(
200       const gfx::Display& top_display,
201       const gfx::Display& bottom_display,
202       int popup_required_height) const;
203 
204   AutofillPopupView* view_;  // Weak reference.
205   base::WeakPtr<AutofillPopupDelegate> delegate_;
206 
207   // The WebContents in which this object should listen for keyboard events
208   // while showing the popup. Can be NULL, in which case this object will not
209   // listen for keyboard events.
210   content::WebContents* web_contents_;
211 
212   gfx::NativeView container_view_;  // Weak reference.
213 
214   // The bounds of the text element that is the focus of the Autofill.
215   // These coordinates are in screen space.
216   const gfx::RectF element_bounds_;
217 
218   // The bounds of the Autofill popup.
219   gfx::Rect popup_bounds_;
220 
221   // The text direction of the popup.
222   base::i18n::TextDirection text_direction_;
223 
224   // The RenderViewHost that this object has registered its keyboard press
225   // callback with.
226   content::RenderViewHost* registered_key_press_event_callback_with_;
227 
228   // The current Autofill query values.
229   std::vector<base::string16> names_;
230   std::vector<base::string16> subtexts_;
231   std::vector<base::string16> icons_;
232   std::vector<int> identifiers_;
233 
234   // Since names_ can be elided to ensure that it fits on the screen, we need to
235   // keep an unelided copy of the names to be able to pass to the delegate.
236   std::vector<base::string16> full_names_;
237 
238 #if !defined(OS_ANDROID)
239   // The fonts for the popup text.
240   gfx::Font name_font_;
241   gfx::Font subtext_font_;
242   gfx::Font warning_font_;
243 #endif
244 
245   // The line that is currently selected by the user.
246   // |kNoSelection| indicates that no line is currently selected.
247   int selected_line_;
248 
249   // Whether the popup view should hide on mouse presses outside of it.
250   bool hide_on_outside_click_;
251 
252   content::RenderWidgetHost::KeyPressEventCallback key_press_event_callback_;
253 
254   base::WeakPtrFactory<AutofillPopupControllerImpl> weak_ptr_factory_;
255 };
256 
257 }  // namespace autofill
258 
259 #endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_POPUP_CONTROLLER_IMPL_H_
260