| OLD | NEW |
| 1 // Copyright 2012 The Chromium Authors. All rights reserved. | 1 // Copyright 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/renderer/searchbox/searchbox.h" | 5 #include "chrome/renderer/searchbox/searchbox.h" |
| 6 | 6 |
| 7 #include "base/utf_string_conversions.h" | 7 #include "chrome/common/instant_messages.h" |
| 8 #include "chrome/common/render_messages.h" | |
| 9 #include "chrome/renderer/searchbox/searchbox_extension.h" | 8 #include "chrome/renderer/searchbox/searchbox_extension.h" |
| 10 #include "content/public/renderer/render_view.h" | 9 #include "content/public/renderer/render_view.h" |
| 11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
| 12 | 11 |
| 13 namespace { | |
| 14 | |
| 15 // Prefix for a thumbnail URL. | |
| 16 const char kThumbnailUrlPrefix[] = "chrome-search://thumb/"; | |
| 17 | |
| 18 // Prefix for a thumbnail URL. | |
| 19 const char kFaviconUrlPrefix[] = "chrome-search://favicon/"; | |
| 20 | |
| 21 } | |
| 22 | |
| 23 SearchBox::SearchBox(content::RenderView* render_view) | 12 SearchBox::SearchBox(content::RenderView* render_view) |
| 24 : content::RenderViewObserver(render_view), | 13 : content::RenderViewObserver(render_view), |
| 25 content::RenderViewObserverTracker<SearchBox>(render_view), | 14 content::RenderViewObserverTracker<SearchBox>(render_view), |
| 26 verbatim_(false), | 15 verbatim_(false), |
| 27 selection_start_(0), | 16 selection_start_(0), |
| 28 selection_end_(0), | 17 selection_end_(0) { |
| 29 results_base_(0), | |
| 30 start_margin_(0), | |
| 31 last_results_base_(0), | |
| 32 is_key_capture_enabled_(false), | |
| 33 display_instant_results_(false), | |
| 34 omnibox_font_size_(0), | |
| 35 last_restricted_id_(0) { | |
| 36 } | 18 } |
| 37 | 19 |
| 38 SearchBox::~SearchBox() { | 20 SearchBox::~SearchBox() { |
| 39 } | 21 } |
| 40 | 22 |
| 41 void SearchBox::SetSuggestions( | |
| 42 const std::vector<InstantSuggestion>& suggestions) { | |
| 43 if (!suggestions.empty() && | |
| 44 suggestions[0].behavior == INSTANT_COMPLETE_REPLACE) { | |
| 45 query_ = suggestions[0].text; | |
| 46 verbatim_ = true; | |
| 47 selection_start_ = selection_end_ = query_.size(); | |
| 48 } | |
| 49 // Explicitly allow empty vector to be sent to the browser. | |
| 50 render_view()->Send(new ChromeViewHostMsg_SetSuggestions( | |
| 51 render_view()->GetRoutingID(), render_view()->GetPageId(), suggestions)); | |
| 52 } | |
| 53 | |
| 54 void SearchBox::ShowInstantOverlay(InstantShownReason reason, | |
| 55 int height, | |
| 56 InstantSizeUnits units) { | |
| 57 render_view()->Send(new ChromeViewHostMsg_ShowInstantOverlay( | |
| 58 render_view()->GetRoutingID(), render_view()->GetPageId(), reason, | |
| 59 height, units)); | |
| 60 } | |
| 61 | |
| 62 void SearchBox::StartCapturingKeyStrokes() { | |
| 63 render_view()->Send(new ChromeViewHostMsg_StartCapturingKeyStrokes( | |
| 64 render_view()->GetRoutingID(), render_view()->GetPageId())); | |
| 65 } | |
| 66 | |
| 67 void SearchBox::StopCapturingKeyStrokes() { | |
| 68 render_view()->Send(new ChromeViewHostMsg_StopCapturingKeyStrokes( | |
| 69 render_view()->GetRoutingID(), render_view()->GetPageId())); | |
| 70 } | |
| 71 | |
| 72 void SearchBox::NavigateToURL(const GURL& url, | |
| 73 content::PageTransition transition, | |
| 74 WindowOpenDisposition disposition) { | |
| 75 render_view()->Send(new ChromeViewHostMsg_SearchBoxNavigate( | |
| 76 render_view()->GetRoutingID(), render_view()->GetPageId(), | |
| 77 url, transition, disposition)); | |
| 78 } | |
| 79 | |
| 80 void SearchBox::DeleteMostVisitedItem(int restrict_id) { | |
| 81 string16 url = RestrictedIdToURL(restrict_id); | |
| 82 render_view()->Send(new ChromeViewHostMsg_InstantDeleteMostVisitedItem( | |
| 83 render_view()->GetRoutingID(), GURL(url))); | |
| 84 } | |
| 85 | |
| 86 void SearchBox::UndoMostVisitedDeletion(int restrict_id) { | |
| 87 string16 url = RestrictedIdToURL(restrict_id); | |
| 88 render_view()->Send(new ChromeViewHostMsg_InstantUndoMostVisitedDeletion( | |
| 89 render_view()->GetRoutingID(), GURL(url))); | |
| 90 } | |
| 91 | |
| 92 void SearchBox::UndoAllMostVisitedDeletions() { | |
| 93 render_view()->Send(new ChromeViewHostMsg_InstantUndoAllMostVisitedDeletions( | |
| 94 render_view()->GetRoutingID())); | |
| 95 } | |
| 96 | |
| 97 int SearchBox::GetStartMargin() const { | |
| 98 return static_cast<int>(start_margin_ / GetZoom()); | |
| 99 } | |
| 100 | |
| 101 gfx::Rect SearchBox::GetPopupBounds() const { | 23 gfx::Rect SearchBox::GetPopupBounds() const { |
| 102 double zoom = GetZoom(); | 24 double zoom = GetZoom(); |
| 103 return gfx::Rect(static_cast<int>(popup_bounds_.x() / zoom), | 25 return gfx::Rect(static_cast<int>(popup_bounds_.x() / zoom), |
| 104 static_cast<int>(popup_bounds_.y() / zoom), | 26 static_cast<int>(popup_bounds_.y() / zoom), |
| 105 static_cast<int>(popup_bounds_.width() / zoom), | 27 static_cast<int>(popup_bounds_.width() / zoom), |
| 106 static_cast<int>(popup_bounds_.height() / zoom)); | 28 static_cast<int>(popup_bounds_.height() / zoom)); |
| 107 } | 29 } |
| 108 | 30 |
| 109 const std::vector<InstantAutocompleteResult>& | 31 void SearchBox::SetSuggestion(const InstantSuggestion& suggestion) { |
| 110 SearchBox::GetAutocompleteResults() { | 32 Send(new ChromeViewHostMsg_SearchBoxSetSuggestion( |
| 111 // Remember the last requested autocomplete_results to account for race | 33 routing_id(), render_view()->GetPageId(), suggestion)); |
| 112 // conditions between autocomplete providers returning new data and the user | |
| 113 // clicking on a suggestion. | |
| 114 last_autocomplete_results_ = autocomplete_results_; | |
| 115 last_results_base_ = results_base_; | |
| 116 return autocomplete_results_; | |
| 117 } | |
| 118 | |
| 119 const InstantAutocompleteResult* SearchBox::GetAutocompleteResultWithId( | |
| 120 size_t restricted_id) const { | |
| 121 if (restricted_id < last_results_base_ || | |
| 122 restricted_id >= last_results_base_ + last_autocomplete_results_.size()) | |
| 123 return NULL; | |
| 124 return &last_autocomplete_results_[restricted_id - last_results_base_]; | |
| 125 } | |
| 126 | |
| 127 const ThemeBackgroundInfo& SearchBox::GetThemeBackgroundInfo() { | |
| 128 return theme_info_; | |
| 129 } | 34 } |
| 130 | 35 |
| 131 bool SearchBox::OnMessageReceived(const IPC::Message& message) { | 36 bool SearchBox::OnMessageReceived(const IPC::Message& message) { |
| 132 bool handled = true; | 37 bool handled = true; |
| 133 IPC_BEGIN_MESSAGE_MAP(SearchBox, message) | 38 IPC_BEGIN_MESSAGE_MAP(SearchBox, message) |
| 39 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxDetermineInstantSupport, |
| 40 OnDetermineInstantSupport) |
| 134 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxChange, OnChange) | 41 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxChange, OnChange) |
| 135 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSubmit, OnSubmit) | 42 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSubmit, OnSubmit) |
| 136 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxCancel, OnCancel) | 43 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxBlur, OnBlur) |
| 137 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxPopupResize, OnPopupResize) | 44 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxPopupBounds, OnPopupBounds) |
| 138 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxMarginChange, OnMarginChange) | |
| 139 IPC_MESSAGE_HANDLER(ChromeViewMsg_DetermineIfPageSupportsInstant, | |
| 140 OnDetermineIfPageSupportsInstant) | |
| 141 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxAutocompleteResults, | |
| 142 OnAutocompleteResults) | |
| 143 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxUpOrDownKeyPressed, | |
| 144 OnUpOrDownKeyPressed) | |
| 145 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxCancelSelection, | |
| 146 OnCancelSelection) | |
| 147 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSetDisplayInstantResults, | |
| 148 OnSetDisplayInstantResults) | |
| 149 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxKeyCaptureChanged, | |
| 150 OnKeyCaptureChange) | |
| 151 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxThemeChanged, | |
| 152 OnThemeChanged) | |
| 153 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxFontInformation, | |
| 154 OnFontInformationReceived) | |
| 155 IPC_MESSAGE_HANDLER(ChromeViewMsg_InstantMostVisitedItemsChanged, | |
| 156 OnMostVisitedChanged) | |
| 157 IPC_MESSAGE_UNHANDLED(handled = false) | 45 IPC_MESSAGE_UNHANDLED(handled = false) |
| 158 IPC_END_MESSAGE_MAP() | 46 IPC_END_MESSAGE_MAP() |
| 159 return handled; | 47 return handled; |
| 160 } | 48 } |
| 161 | 49 |
| 162 void SearchBox::DidClearWindowObject(WebKit::WebFrame* frame) { | 50 void SearchBox::OnDetermineInstantSupport() { |
| 163 extensions_v8::SearchBoxExtension::DispatchOnWindowReady(frame); | 51 bool supports_instant = |
| 52 extensions_v8::SearchBoxExtension::DetermineInstantSupport(render_view()); |
| 53 Send(new ChromeViewHostMsg_SearchBoxInstantSupportDetermined( |
| 54 routing_id(), render_view()->GetPageId(), supports_instant)); |
| 164 } | 55 } |
| 165 | 56 |
| 166 void SearchBox::OnChange(const string16& query, | 57 void SearchBox::OnChange(const string16& query, |
| 167 bool verbatim, | 58 bool verbatim, |
| 168 size_t selection_start, | 59 size_t selection_start, |
| 169 size_t selection_end) { | 60 size_t selection_end) { |
| 61 if (query_ == query && verbatim_ == verbatim && |
| 62 selection_start_ == selection_start && selection_end_ == selection_end) |
| 63 return; |
| 64 |
| 170 query_ = query; | 65 query_ = query; |
| 171 verbatim_ = verbatim; | 66 verbatim_ = verbatim; |
| 172 selection_start_ = selection_start; | 67 selection_start_ = selection_start; |
| 173 selection_end_ = selection_end; | 68 selection_end_ = selection_end; |
| 174 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | 69 extensions_v8::SearchBoxExtension::Change(render_view()); |
| 175 DVLOG(1) << render_view() << " OnChange"; | |
| 176 extensions_v8::SearchBoxExtension::DispatchChange( | |
| 177 render_view()->GetWebView()->mainFrame()); | |
| 178 } | |
| 179 } | 70 } |
| 180 | 71 |
| 181 void SearchBox::OnSubmit(const string16& query) { | 72 void SearchBox::OnSubmit(const string16& query) { |
| 182 query_ = query; | 73 query_ = query; |
| 183 verbatim_ = true; | 74 verbatim_ = true; |
| 184 selection_start_ = selection_end_ = query_.size(); | 75 selection_start_ = selection_end_ = query_.size(); |
| 185 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | 76 extensions_v8::SearchBoxExtension::Submit(render_view()); |
| 186 DVLOG(1) << render_view() << " OnSubmit"; | |
| 187 extensions_v8::SearchBoxExtension::DispatchSubmit( | |
| 188 render_view()->GetWebView()->mainFrame()); | |
| 189 } | |
| 190 Reset(); | |
| 191 } | 77 } |
| 192 | 78 |
| 193 void SearchBox::OnCancel(const string16& query) { | 79 void SearchBox::OnBlur(const string16& query) { |
| 194 query_ = query; | 80 query_ = query; |
| 195 verbatim_ = true; | 81 verbatim_ = true; |
| 196 selection_start_ = selection_end_ = query_.size(); | 82 selection_start_ = selection_end_ = query_.size(); |
| 197 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | 83 extensions_v8::SearchBoxExtension::Blur(render_view()); |
| 198 DVLOG(1) << render_view() << " OnCancel"; | |
| 199 extensions_v8::SearchBoxExtension::DispatchCancel( | |
| 200 render_view()->GetWebView()->mainFrame()); | |
| 201 } | |
| 202 Reset(); | |
| 203 } | 84 } |
| 204 | 85 |
| 205 void SearchBox::OnPopupResize(const gfx::Rect& bounds) { | 86 void SearchBox::OnPopupBounds(const gfx::Rect& bounds) { |
| 87 if (popup_bounds_ == bounds) |
| 88 return; |
| 89 |
| 206 popup_bounds_ = bounds; | 90 popup_bounds_ = bounds; |
| 207 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | 91 extensions_v8::SearchBoxExtension::PopupBounds(render_view()); |
| 208 DVLOG(1) << render_view() << " OnPopupResize"; | |
| 209 extensions_v8::SearchBoxExtension::DispatchResize( | |
| 210 render_view()->GetWebView()->mainFrame()); | |
| 211 } | |
| 212 } | |
| 213 | |
| 214 void SearchBox::OnMarginChange(int margin, int width) { | |
| 215 start_margin_ = margin; | |
| 216 | |
| 217 // Override only the width parameter of the popup bounds. | |
| 218 popup_bounds_.set_width(width); | |
| 219 | |
| 220 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 221 extensions_v8::SearchBoxExtension::DispatchMarginChange( | |
| 222 render_view()->GetWebView()->mainFrame()); | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 void SearchBox::OnDetermineIfPageSupportsInstant() { | |
| 227 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 228 bool result = extensions_v8::SearchBoxExtension::PageSupportsInstant( | |
| 229 render_view()->GetWebView()->mainFrame()); | |
| 230 DVLOG(1) << render_view() << " PageSupportsInstant: " << result; | |
| 231 render_view()->Send(new ChromeViewHostMsg_InstantSupportDetermined( | |
| 232 render_view()->GetRoutingID(), render_view()->GetPageId(), result)); | |
| 233 } | |
| 234 } | |
| 235 | |
| 236 void SearchBox::OnAutocompleteResults( | |
| 237 const std::vector<InstantAutocompleteResult>& results) { | |
| 238 results_base_ += autocomplete_results_.size(); | |
| 239 autocomplete_results_ = results; | |
| 240 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 241 DVLOG(1) << render_view() << " OnAutocompleteResults"; | |
| 242 extensions_v8::SearchBoxExtension::DispatchAutocompleteResults( | |
| 243 render_view()->GetWebView()->mainFrame()); | |
| 244 } | |
| 245 } | |
| 246 | |
| 247 void SearchBox::OnUpOrDownKeyPressed(int count) { | |
| 248 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 249 DVLOG(1) << render_view() << " OnKeyPress: " << count; | |
| 250 extensions_v8::SearchBoxExtension::DispatchUpOrDownKeyPress( | |
| 251 render_view()->GetWebView()->mainFrame(), count); | |
| 252 } | |
| 253 } | |
| 254 | |
| 255 void SearchBox::OnCancelSelection(const string16& query) { | |
| 256 // TODO(sreeram): crbug.com/176101 The state reset below are somewhat wrong. | |
| 257 query_ = query; | |
| 258 verbatim_ = true; | |
| 259 selection_start_ = selection_end_ = query_.size(); | |
| 260 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 261 DVLOG(1) << render_view() << " OnKeyPress ESC"; | |
| 262 extensions_v8::SearchBoxExtension::DispatchEscKeyPress( | |
| 263 render_view()->GetWebView()->mainFrame()); | |
| 264 } | |
| 265 } | |
| 266 | |
| 267 void SearchBox::OnKeyCaptureChange(bool is_key_capture_enabled) { | |
| 268 if (is_key_capture_enabled != is_key_capture_enabled_ && | |
| 269 render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 270 is_key_capture_enabled_ = is_key_capture_enabled; | |
| 271 DVLOG(1) << render_view() << " OnKeyCaptureChange"; | |
| 272 extensions_v8::SearchBoxExtension::DispatchKeyCaptureChange( | |
| 273 render_view()->GetWebView()->mainFrame()); | |
| 274 } | |
| 275 } | |
| 276 | |
| 277 void SearchBox::OnSetDisplayInstantResults(bool display_instant_results) { | |
| 278 display_instant_results_ = display_instant_results; | |
| 279 } | |
| 280 | |
| 281 void SearchBox::OnThemeChanged(const ThemeBackgroundInfo& theme_info) { | |
| 282 theme_info_ = theme_info; | |
| 283 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 284 extensions_v8::SearchBoxExtension::DispatchThemeChange( | |
| 285 render_view()->GetWebView()->mainFrame()); | |
| 286 } | |
| 287 } | 92 } |
| 288 | 93 |
| 289 double SearchBox::GetZoom() const { | 94 double SearchBox::GetZoom() const { |
| 290 WebKit::WebView* web_view = render_view()->GetWebView(); | 95 WebKit::WebView* web_view = render_view()->GetWebView(); |
| 291 if (web_view) { | 96 if (web_view) { |
| 292 double zoom = WebKit::WebView::zoomLevelToZoomFactor(web_view->zoomLevel()); | 97 double zoom = WebKit::WebView::zoomLevelToZoomFactor(web_view->zoomLevel()); |
| 293 if (zoom != 0) | 98 if (zoom != 0) |
| 294 return zoom; | 99 return zoom; |
| 295 } | 100 } |
| 296 return 1.0; | 101 return 1.0; |
| 297 } | 102 } |
| 298 | |
| 299 void SearchBox::OnFontInformationReceived(const string16& omnibox_font, | |
| 300 size_t omnibox_font_size) { | |
| 301 omnibox_font_ = omnibox_font; | |
| 302 omnibox_font_size_ = omnibox_font_size; | |
| 303 } | |
| 304 | |
| 305 void SearchBox::Reset() { | |
| 306 query_.clear(); | |
| 307 verbatim_ = false; | |
| 308 selection_start_ = 0; | |
| 309 selection_end_ = 0; | |
| 310 results_base_ = 0; | |
| 311 popup_bounds_ = gfx::Rect(); | |
| 312 start_margin_ = 0; | |
| 313 autocomplete_results_.clear(); | |
| 314 is_key_capture_enabled_ = false; | |
| 315 theme_info_ = ThemeBackgroundInfo(); | |
| 316 // Don't reset display_instant_results_ to prevent clearing it on committed | |
| 317 // results pages in extended mode. Otherwise resetting it is a no-op because | |
| 318 // a new loader is created when it changes; see crbug.com/164662. | |
| 319 // Also don't reset omnibox_font_ or omnibox_font_size_ since it never | |
| 320 // changes. | |
| 321 } | |
| 322 | |
| 323 void SearchBox::OnMostVisitedChanged( | |
| 324 const std::vector<MostVisitedItem>& items) { | |
| 325 most_visited_items_ = items; | |
| 326 | |
| 327 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { | |
| 328 extensions_v8::SearchBoxExtension::DispatchMostVisitedChanged( | |
| 329 render_view()->GetWebView()->mainFrame()); | |
| 330 } | |
| 331 } | |
| 332 | |
| 333 const std::vector<MostVisitedItem>& SearchBox::GetMostVisitedItems() { | |
| 334 return most_visited_items_; | |
| 335 } | |
| 336 | |
| 337 int SearchBox::UrlToRestrictedId(string16 url) { | |
| 338 if (url_to_restricted_id_map_[url]) | |
| 339 return url_to_restricted_id_map_[url]; | |
| 340 | |
| 341 last_restricted_id_++; | |
| 342 url_to_restricted_id_map_[url] = last_restricted_id_; | |
| 343 restricted_id_to_url_map_[last_restricted_id_] = url; | |
| 344 | |
| 345 return last_restricted_id_; | |
| 346 } | |
| 347 | |
| 348 string16 SearchBox::RestrictedIdToURL(int id) { | |
| 349 return restricted_id_to_url_map_[id]; | |
| 350 } | |
| 351 | |
| 352 string16 SearchBox::GenerateThumbnailUrl(int id) { | |
| 353 std::ostringstream ostr; | |
| 354 ostr << kThumbnailUrlPrefix << id; | |
| 355 GURL url = GURL(ostr.str()); | |
| 356 return UTF8ToUTF16(url.spec()); | |
| 357 } | |
| 358 | |
| 359 string16 SearchBox::GenerateFaviconUrl(int id) { | |
| 360 std::ostringstream ostr; | |
| 361 ostr << kFaviconUrlPrefix << id; | |
| 362 GURL url = GURL(ostr.str()); | |
| 363 return UTF8ToUTF16(url.spec()); | |
| 364 } | |
| OLD | NEW |