searchbox.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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#include "chrome/renderer/searchbox/searchbox.h"
6
7#include "chrome/common/render_messages.h"
8#include "chrome/renderer/searchbox/searchbox_extension.h"
9#include "content/public/renderer/render_view.h"
10#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
11
12SearchBox::SearchBox(content::RenderView* render_view)
13    : content::RenderViewObserver(render_view),
14      content::RenderViewObserverTracker<SearchBox>(render_view),
15      verbatim_(false),
16      selection_start_(0),
17      selection_end_(0),
18      results_base_(0),
19      last_results_base_(0),
20      is_focused_(false),
21      active_tab_is_ntp_(false) {
22}
23
24SearchBox::~SearchBox() {
25}
26
27void SearchBox::SetSuggestions(
28    const std::vector<InstantSuggestion>& suggestions) {
29  if (!suggestions.empty() &&
30      suggestions[0].behavior == INSTANT_COMPLETE_REPLACE) {
31    query_ = suggestions[0].text;
32    verbatim_ = true;
33    selection_start_ = selection_end_ = query_.size();
34  }
35  // Explicitly allow empty vector to be sent to the browser.
36  render_view()->Send(new ChromeViewHostMsg_SetSuggestions(
37      render_view()->GetRoutingID(), render_view()->GetPageId(), suggestions));
38}
39
40void SearchBox::ShowInstantPreview(InstantShownReason reason,
41                                   int height,
42                                   InstantSizeUnits units) {
43  render_view()->Send(new ChromeViewHostMsg_ShowInstantPreview(
44      render_view()->GetRoutingID(), render_view()->GetPageId(), reason,
45      height, units));
46}
47
48gfx::Rect SearchBox::GetRect() {
49  // Need to adjust for scale.
50  if (rect_.IsEmpty())
51    return rect_;
52  WebKit::WebView* web_view = render_view()->GetWebView();
53  if (!web_view)
54    return rect_;
55  double zoom = WebKit::WebView::zoomLevelToZoomFactor(web_view->zoomLevel());
56  if (zoom == 0)
57    return rect_;
58  return gfx::Rect(static_cast<int>(static_cast<float>(rect_.x()) / zoom),
59                   static_cast<int>(static_cast<float>(rect_.y()) / zoom),
60                   static_cast<int>(static_cast<float>(rect_.width()) / zoom),
61                   static_cast<int>(static_cast<float>(rect_.height()) / zoom));
62}
63
64const std::vector<InstantAutocompleteResult>&
65    SearchBox::GetAutocompleteResults() {
66  // Remember the last requested autocomplete_results to account for race
67  // conditions between autocomplete providers returning new data and the user
68  // clicking on a suggestion.
69  last_autocomplete_results_ = autocomplete_results_;
70  last_results_base_ = results_base_;
71  return autocomplete_results_;
72}
73
74const InstantAutocompleteResult* SearchBox::GetAutocompleteResultWithId(
75    size_t restricted_id) const {
76  if (restricted_id < last_results_base_ ||
77      restricted_id >= last_results_base_ + last_autocomplete_results_.size())
78    return NULL;
79  return &last_autocomplete_results_[restricted_id - last_results_base_];
80}
81
82bool SearchBox::OnMessageReceived(const IPC::Message& message) {
83  bool handled = true;
84  IPC_BEGIN_MESSAGE_MAP(SearchBox, message)
85    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxChange, OnChange)
86    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSubmit, OnSubmit)
87    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxCancel, OnCancel)
88    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxResize, OnResize)
89    IPC_MESSAGE_HANDLER(ChromeViewMsg_DetermineIfPageSupportsInstant,
90                        OnDetermineIfPageSupportsInstant)
91    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxAutocompleteResults,
92                        OnAutocompleteResults)
93    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxUpOrDownKeyPressed,
94                        OnUpOrDownKeyPressed)
95    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxFocus, OnFocus)
96    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxBlur, OnBlur)
97    IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxActiveTabModeChanged,
98                        OnActiveTabModeChanged)
99    IPC_MESSAGE_UNHANDLED(handled = false)
100  IPC_END_MESSAGE_MAP()
101  return handled;
102}
103
104void SearchBox::OnChange(const string16& query,
105                         bool verbatim,
106                         size_t selection_start,
107                         size_t selection_end) {
108  query_ = query;
109  verbatim_ = verbatim;
110  selection_start_ = selection_start;
111  selection_end_ = selection_end;
112  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
113    extensions_v8::SearchBoxExtension::DispatchChange(
114        render_view()->GetWebView()->mainFrame());
115  }
116}
117
118void SearchBox::OnSubmit(const string16& query) {
119  query_ = query;
120  verbatim_ = true;
121  selection_start_ = selection_end_ = query_.size();
122  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
123    extensions_v8::SearchBoxExtension::DispatchSubmit(
124        render_view()->GetWebView()->mainFrame());
125  }
126  Reset();
127}
128
129void SearchBox::OnCancel(const string16& query) {
130  query_ = query;
131  verbatim_ = true;
132  selection_start_ = selection_end_ = query_.size();
133  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
134    extensions_v8::SearchBoxExtension::DispatchCancel(
135        render_view()->GetWebView()->mainFrame());
136  }
137  Reset();
138}
139
140void SearchBox::OnResize(const gfx::Rect& bounds) {
141  rect_ = bounds;
142  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
143    extensions_v8::SearchBoxExtension::DispatchResize(
144        render_view()->GetWebView()->mainFrame());
145  }
146}
147
148void SearchBox::OnDetermineIfPageSupportsInstant() {
149  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
150    bool result = extensions_v8::SearchBoxExtension::PageSupportsInstant(
151        render_view()->GetWebView()->mainFrame());
152    render_view()->Send(new ChromeViewHostMsg_InstantSupportDetermined(
153        render_view()->GetRoutingID(), render_view()->GetPageId(), result));
154  }
155}
156
157void SearchBox::OnAutocompleteResults(
158    const std::vector<InstantAutocompleteResult>& results) {
159  results_base_ += autocomplete_results_.size();
160  autocomplete_results_ = results;
161  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
162    extensions_v8::SearchBoxExtension::DispatchAutocompleteResults(
163        render_view()->GetWebView()->mainFrame());
164  }
165}
166
167void SearchBox::OnUpOrDownKeyPressed(int count) {
168  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
169    extensions_v8::SearchBoxExtension::DispatchUpOrDownKeyPress(
170        render_view()->GetWebView()->mainFrame(), count);
171  }
172}
173
174void SearchBox::OnFocus() {
175  is_focused_ = true;
176  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
177    extensions_v8::SearchBoxExtension::DispatchFocus(
178        render_view()->GetWebView()->mainFrame());
179  }
180}
181
182void SearchBox::OnBlur() {
183  is_focused_ = false;
184  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
185    extensions_v8::SearchBoxExtension::DispatchBlur(
186        render_view()->GetWebView()->mainFrame());
187  }
188}
189
190void SearchBox::OnActiveTabModeChanged(bool active_tab_is_ntp) {
191  active_tab_is_ntp_ = active_tab_is_ntp;
192  if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) {
193    extensions_v8::SearchBoxExtension::DispatchContextChange(
194        render_view()->GetWebView()->mainFrame());
195  }
196}
197
198void SearchBox::Reset() {
199  query_.clear();
200  verbatim_ = false;
201  selection_start_ = selection_end_ = 0;
202  results_base_ = 0;
203  rect_ = gfx::Rect();
204  autocomplete_results_.clear();
205  is_focused_ = false;
206}
207