searchbox.cc revision 868fa2fe829687343ffae624259930155e16dbd8
11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Copyright 2012 The Chromium Authors. All rights reserved. 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Use of this source code is governed by a BSD-style license that can be 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// found in the LICENSE file. 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chrome/renderer/searchbox/searchbox.h" 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include <string> 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/string_number_conversions.h" 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/string_util.h" 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "base/strings/utf_string_conversions.h" 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chrome/common/chrome_switches.h" 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chrome/common/omnibox_focus_state.h" 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chrome/common/render_messages.h" 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chrome/common/url_constants.h" 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "chrome/renderer/searchbox/searchbox_extension.h" 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "content/public/renderer/render_view.h" 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "googleurl/src/gurl.h" 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "grit/renderer_resources.h" 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "net/base/escape.h" 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h" 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "ui/base/resource/resource_bundle.h" 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertnamespace { 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Size of the results cache. 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertconst size_t kMaxInstantAutocompleteResultItemCacheSize = 100; 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} // namespace 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertnamespace internal { // for testing 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Parses |url| and fills in |id| with the InstantRestrictedID obtained from the 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// |url|. |render_view_id| is the ID of the associated RenderView. 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// Valid |url| forms: 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// chrome-search://favicon/<view_id>/<restricted_id> 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// chrome-search://thumb/<view_id>/<restricted_id> 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// If the |url| is valid, returns true and fills in |id| with restricted_id 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert// value. If the |url| is invalid, returns false and |id| is not set. 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertbool GetInstantRestrictedIDFromURL(int render_view_id, 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const GURL& url, 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert InstantRestrictedID* id) { 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Strip leading path. 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert std::string path = url.path().substr(1); 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Check that the path is of Most visited item ID form. 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert std::vector<std::string> tokens; 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (Tokenize(path, "/", &tokens) != 2) 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert int view_id = 0; 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!base::StringToInt(tokens[0], &view_id) || view_id != render_view_id) 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return false; 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return base::StringToInt(tokens[1], id); 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} // namespace internal 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn BringertSearchBox::SearchBox(content::RenderView* render_view) 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert : content::RenderViewObserver(render_view), 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert content::RenderViewObserverTracker<SearchBox>(render_view), 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert verbatim_(false), 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert query_is_restricted_(false), 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert selection_start_(0), 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert selection_end_(0), 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert start_margin_(0), 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert is_focused_(false), 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert is_key_capture_enabled_(false), 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert display_instant_results_(false), 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert omnibox_font_size_(0), 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert autocomplete_results_cache_(kMaxInstantAutocompleteResultItemCacheSize), 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert most_visited_items_cache_(kMaxInstantMostVisitedItemCacheSize) { 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn BringertSearchBox::~SearchBox() { 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid SearchBox::SetSuggestions( 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert const std::vector<InstantSuggestion>& suggestions) { 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert if (!suggestions.empty() && 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert suggestions[0].behavior == INSTANT_COMPLETE_REPLACE) { 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert SetQuery(suggestions[0].text, true); 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert selection_start_ = selection_end_ = query_.size(); 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert } 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert // Explicitly allow empty vector to be sent to the browser. 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->Send(new ChromeViewHostMsg_SetSuggestions( 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->GetRoutingID(), render_view()->GetPageId(), suggestions)); 921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid SearchBox::MarkQueryAsRestricted() { 951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert query_is_restricted_ = true; 961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert query_.clear(); 971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid SearchBox::ShowInstantOverlay(int height, InstantSizeUnits units) { 1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->Send(new ChromeViewHostMsg_ShowInstantOverlay( 1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->GetRoutingID(), render_view()->GetPageId(), height, 1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert units)); 1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid SearchBox::FocusOmnibox() { 1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->Send(new ChromeViewHostMsg_FocusOmnibox( 1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->GetRoutingID(), render_view()->GetPageId(), 1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert OMNIBOX_FOCUS_VISIBLE)); 1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid SearchBox::StartCapturingKeyStrokes() { 1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->Send(new ChromeViewHostMsg_FocusOmnibox( 1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert render_view()->GetRoutingID(), render_view()->GetPageId(), 1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert OMNIBOX_FOCUS_INVISIBLE)); 1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertvoid SearchBox::StopCapturingKeyStrokes() { 118 render_view()->Send(new ChromeViewHostMsg_FocusOmnibox( 119 render_view()->GetRoutingID(), render_view()->GetPageId(), 120 OMNIBOX_FOCUS_NONE)); 121} 122 123void SearchBox::NavigateToURL(const GURL& url, 124 content::PageTransition transition, 125 WindowOpenDisposition disposition, 126 bool is_search_type) { 127 render_view()->Send(new ChromeViewHostMsg_SearchBoxNavigate( 128 render_view()->GetRoutingID(), render_view()->GetPageId(), 129 url, transition, disposition, is_search_type)); 130} 131 132void SearchBox::DeleteMostVisitedItem( 133 InstantRestrictedID most_visited_item_id) { 134 render_view()->Send(new ChromeViewHostMsg_SearchBoxDeleteMostVisitedItem( 135 render_view()->GetRoutingID(), render_view()->GetPageId(), 136 GetURLForMostVisitedItem(most_visited_item_id))); 137} 138 139void SearchBox::UndoMostVisitedDeletion( 140 InstantRestrictedID most_visited_item_id) { 141 render_view()->Send(new ChromeViewHostMsg_SearchBoxUndoMostVisitedDeletion( 142 render_view()->GetRoutingID(), render_view()->GetPageId(), 143 GetURLForMostVisitedItem(most_visited_item_id))); 144} 145 146void SearchBox::UndoAllMostVisitedDeletions() { 147 render_view()->Send( 148 new ChromeViewHostMsg_SearchBoxUndoAllMostVisitedDeletions( 149 render_view()->GetRoutingID(), render_view()->GetPageId())); 150} 151 152void SearchBox::ShowBars() { 153 DVLOG(1) << render_view() << " ShowBars"; 154 render_view()->Send(new ChromeViewHostMsg_SearchBoxShowBars( 155 render_view()->GetRoutingID(), render_view()->GetPageId())); 156} 157 158void SearchBox::HideBars() { 159 DVLOG(1) << render_view() << " HideBars"; 160 render_view()->Send(new ChromeViewHostMsg_SearchBoxHideBars( 161 render_view()->GetRoutingID(), render_view()->GetPageId())); 162} 163 164int SearchBox::GetStartMargin() const { 165 return static_cast<int>(start_margin_ / GetZoom()); 166} 167 168gfx::Rect SearchBox::GetPopupBounds() const { 169 double zoom = GetZoom(); 170 return gfx::Rect(static_cast<int>(popup_bounds_.x() / zoom), 171 static_cast<int>(popup_bounds_.y() / zoom), 172 static_cast<int>(popup_bounds_.width() / zoom), 173 static_cast<int>(popup_bounds_.height() / zoom)); 174} 175 176void SearchBox::GetAutocompleteResults( 177 std::vector<InstantAutocompleteResultIDPair>* results) const { 178 autocomplete_results_cache_.GetCurrentItems(results); 179} 180 181bool SearchBox::GetAutocompleteResultWithID( 182 InstantRestrictedID autocomplete_result_id, 183 InstantAutocompleteResult* result) const { 184 return autocomplete_results_cache_.GetItemWithRestrictedID( 185 autocomplete_result_id, result); 186} 187 188const ThemeBackgroundInfo& SearchBox::GetThemeBackgroundInfo() { 189 return theme_info_; 190} 191 192bool SearchBox::GenerateThumbnailURLFromTransientURL(const GURL& transient_url, 193 GURL* url) const { 194 InstantRestrictedID rid = 0; 195 if (!internal::GetInstantRestrictedIDFromURL(render_view()->GetRoutingID(), 196 transient_url, &rid)) { 197 return false; 198 } 199 200 GURL most_visited_item_url(GetURLForMostVisitedItem(rid)); 201 if (most_visited_item_url.is_empty()) 202 return false; 203 *url = GURL(base::StringPrintf("chrome-search://thumb/%s", 204 most_visited_item_url.spec().c_str())); 205 return true; 206} 207 208bool SearchBox::GenerateFaviconURLFromTransientURL(const GURL& transient_url, 209 GURL* url) const { 210 InstantRestrictedID rid = 0; 211 if (!internal::GetInstantRestrictedIDFromURL(render_view()->GetRoutingID(), 212 transient_url, &rid)) { 213 return false; 214 } 215 216 GURL most_visited_item_url(GetURLForMostVisitedItem(rid)); 217 if (most_visited_item_url.is_empty()) 218 return false; 219 *url = GURL(base::StringPrintf("chrome-search://favicon/%s", 220 most_visited_item_url.spec().c_str())); 221 return true; 222} 223 224bool SearchBox::OnMessageReceived(const IPC::Message& message) { 225 bool handled = true; 226 IPC_BEGIN_MESSAGE_MAP(SearchBox, message) 227 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxChange, OnChange) 228 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSubmit, OnSubmit) 229 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxCancel, OnCancel) 230 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxPopupResize, OnPopupResize) 231 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxMarginChange, OnMarginChange) 232 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxBarsHidden, OnBarsHidden) 233 IPC_MESSAGE_HANDLER(ChromeViewMsg_DetermineIfPageSupportsInstant, 234 OnDetermineIfPageSupportsInstant) 235 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxAutocompleteResults, 236 OnAutocompleteResults) 237 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxUpOrDownKeyPressed, 238 OnUpOrDownKeyPressed) 239 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxEscKeyPressed, OnEscKeyPressed) 240 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxCancelSelection, 241 OnCancelSelection) 242 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxSetDisplayInstantResults, 243 OnSetDisplayInstantResults) 244 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxFocusChanged, OnFocusChanged) 245 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxThemeChanged, 246 OnThemeChanged) 247 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxFontInformation, 248 OnFontInformationReceived) 249 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxMostVisitedItemsChanged, 250 OnMostVisitedChanged) 251 IPC_MESSAGE_HANDLER(ChromeViewMsg_SearchBoxToggleVoiceSearch, 252 OnToggleVoiceSearch) 253 IPC_MESSAGE_UNHANDLED(handled = false) 254 IPC_END_MESSAGE_MAP() 255 return handled; 256} 257 258void SearchBox::OnChange(const string16& query, 259 bool verbatim, 260 size_t selection_start, 261 size_t selection_end) { 262 SetQuery(query, verbatim); 263 selection_start_ = selection_start; 264 selection_end_ = selection_end; 265 266 // If |query| is empty, this is due to the user backspacing away all the text 267 // in the omnibox, or hitting Escape to restore the "permanent URL", or 268 // switching tabs, etc. In all these cases, there will be no corresponding 269 // OnAutocompleteResults(), so clear the autocomplete results ourselves, by 270 // adding an empty set. Don't notify the page using an "onnativesuggestions" 271 // event, though. 272 if (query.empty()) { 273 autocomplete_results_cache_.AddItems( 274 std::vector<InstantAutocompleteResult>()); 275 } 276 277 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 278 DVLOG(1) << render_view() << " OnChange"; 279 extensions_v8::SearchBoxExtension::DispatchChange( 280 render_view()->GetWebView()->mainFrame()); 281 } 282} 283 284void SearchBox::OnSubmit(const string16& query) { 285 // Submit() is called when the user hits Enter to commit the omnibox text. 286 // If |query| is non-blank, the user committed a search. If it's blank, the 287 // omnibox text was a URL, and the user is navigating to it, in which case 288 // we shouldn't update the |query_| or associated state. 289 if (!query.empty()) { 290 SetQuery(query, true); 291 selection_start_ = selection_end_ = query_.size(); 292 } 293 294 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 295 DVLOG(1) << render_view() << " OnSubmit"; 296 extensions_v8::SearchBoxExtension::DispatchSubmit( 297 render_view()->GetWebView()->mainFrame()); 298 } 299 300 if (!query.empty()) 301 Reset(); 302} 303 304void SearchBox::OnCancel(const string16& query) { 305 SetQuery(query, true); 306 selection_start_ = selection_end_ = query_.size(); 307 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 308 DVLOG(1) << render_view() << " OnCancel"; 309 extensions_v8::SearchBoxExtension::DispatchCancel( 310 render_view()->GetWebView()->mainFrame()); 311 } 312 Reset(); 313} 314 315void SearchBox::OnPopupResize(const gfx::Rect& bounds) { 316 popup_bounds_ = bounds; 317 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 318 DVLOG(1) << render_view() << " OnPopupResize"; 319 extensions_v8::SearchBoxExtension::DispatchResize( 320 render_view()->GetWebView()->mainFrame()); 321 } 322} 323 324void SearchBox::OnMarginChange(int margin, int width) { 325 start_margin_ = margin; 326 327 // Override only the width parameter of the popup bounds. 328 popup_bounds_.set_width(width); 329 330 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 331 extensions_v8::SearchBoxExtension::DispatchMarginChange( 332 render_view()->GetWebView()->mainFrame()); 333 } 334} 335 336void SearchBox::OnBarsHidden() { 337 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 338 extensions_v8::SearchBoxExtension::DispatchBarsHidden( 339 render_view()->GetWebView()->mainFrame()); 340 } 341} 342 343void SearchBox::OnDetermineIfPageSupportsInstant() { 344 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 345 bool result = extensions_v8::SearchBoxExtension::PageSupportsInstant( 346 render_view()->GetWebView()->mainFrame()); 347 DVLOG(1) << render_view() << " PageSupportsInstant: " << result; 348 render_view()->Send(new ChromeViewHostMsg_InstantSupportDetermined( 349 render_view()->GetRoutingID(), render_view()->GetPageId(), result)); 350 } 351} 352 353void SearchBox::OnAutocompleteResults( 354 const std::vector<InstantAutocompleteResult>& results) { 355 autocomplete_results_cache_.AddItems(results); 356 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 357 DVLOG(1) << render_view() << " OnAutocompleteResults"; 358 extensions_v8::SearchBoxExtension::DispatchAutocompleteResults( 359 render_view()->GetWebView()->mainFrame()); 360 } 361} 362 363void SearchBox::OnUpOrDownKeyPressed(int count) { 364 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 365 DVLOG(1) << render_view() << " OnKeyPress: " << count; 366 extensions_v8::SearchBoxExtension::DispatchUpOrDownKeyPress( 367 render_view()->GetWebView()->mainFrame(), count); 368 } 369} 370 371void SearchBox::OnEscKeyPressed() { 372 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 373 DVLOG(1) << render_view() << " OnEscKeyPressed "; 374 extensions_v8::SearchBoxExtension::DispatchEscKeyPress( 375 render_view()->GetWebView()->mainFrame()); 376 } 377} 378 379void SearchBox::OnCancelSelection(const string16& query, 380 bool verbatim, 381 size_t selection_start, 382 size_t selection_end) { 383 SetQuery(query, verbatim); 384 selection_start_ = selection_start; 385 selection_end_ = selection_end; 386 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 387 DVLOG(1) << render_view() << " OnKeyPress ESC"; 388 extensions_v8::SearchBoxExtension::DispatchEscKeyPress( 389 render_view()->GetWebView()->mainFrame()); 390 } 391} 392 393void SearchBox::OnFocusChanged(OmniboxFocusState new_focus_state, 394 OmniboxFocusChangeReason reason) { 395 bool key_capture_enabled = new_focus_state == OMNIBOX_FOCUS_INVISIBLE; 396 if (key_capture_enabled != is_key_capture_enabled_) { 397 // Tell the page if the key capture mode changed unless the focus state 398 // changed because of TYPING. This is because in that case, the browser 399 // hasn't really stopped capturing key strokes. 400 // 401 // (More practically, if we don't do this check, the page would receive 402 // onkeycapturechange before the corresponding onchange, and the page would 403 // have no way of telling whether the keycapturechange happened because of 404 // some actual user action or just because they started typing.) 405 if (reason != OMNIBOX_FOCUS_CHANGE_TYPING && 406 render_view()->GetWebView() && 407 render_view()->GetWebView()->mainFrame()) { 408 is_key_capture_enabled_ = key_capture_enabled; 409 DVLOG(1) << render_view() << " OnKeyCaptureChange"; 410 extensions_v8::SearchBoxExtension::DispatchKeyCaptureChange( 411 render_view()->GetWebView()->mainFrame()); 412 } 413 } 414 bool is_focused = new_focus_state == OMNIBOX_FOCUS_VISIBLE; 415 if (is_focused != is_focused_) { 416 is_focused_ = is_focused; 417 DVLOG(1) << render_view() << " OnFocusChange"; 418 extensions_v8::SearchBoxExtension::DispatchFocusChange( 419 render_view()->GetWebView()->mainFrame()); 420 } 421} 422 423void SearchBox::OnSetDisplayInstantResults(bool display_instant_results) { 424 display_instant_results_ = display_instant_results; 425} 426 427void SearchBox::OnThemeChanged(const ThemeBackgroundInfo& theme_info) { 428 theme_info_ = theme_info; 429 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 430 extensions_v8::SearchBoxExtension::DispatchThemeChange( 431 render_view()->GetWebView()->mainFrame()); 432 } 433} 434 435void SearchBox::OnFontInformationReceived(const string16& omnibox_font, 436 size_t omnibox_font_size) { 437 omnibox_font_ = omnibox_font; 438 omnibox_font_size_ = omnibox_font_size; 439} 440 441double SearchBox::GetZoom() const { 442 WebKit::WebView* web_view = render_view()->GetWebView(); 443 if (web_view) { 444 double zoom = WebKit::WebView::zoomLevelToZoomFactor(web_view->zoomLevel()); 445 if (zoom != 0) 446 return zoom; 447 } 448 return 1.0; 449} 450 451void SearchBox::Reset() { 452 query_.clear(); 453 verbatim_ = false; 454 query_is_restricted_ = false; 455 selection_start_ = 0; 456 selection_end_ = 0; 457 popup_bounds_ = gfx::Rect(); 458 start_margin_ = 0; 459 is_focused_ = false; 460 is_key_capture_enabled_ = false; 461 theme_info_ = ThemeBackgroundInfo(); 462 // Don't reset display_instant_results_ to prevent clearing it on committed 463 // results pages in extended mode. Otherwise resetting it is a no-op because 464 // a new loader is created when it changes; see crbug.com/164662. 465 // Also don't reset omnibox_font_ or omnibox_font_size_ since it never 466 // changes. 467} 468 469void SearchBox::SetQuery(const string16& query, bool verbatim) { 470 query_ = query; 471 verbatim_ = verbatim; 472 query_is_restricted_ = false; 473} 474 475void SearchBox::OnMostVisitedChanged( 476 const std::vector<InstantMostVisitedItem>& items) { 477 most_visited_items_cache_.AddItems(items); 478 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 479 extensions_v8::SearchBoxExtension::DispatchMostVisitedChanged( 480 render_view()->GetWebView()->mainFrame()); 481 } 482} 483 484void SearchBox::GetMostVisitedItems( 485 std::vector<InstantMostVisitedItemIDPair>* items) const { 486 return most_visited_items_cache_.GetCurrentItems(items); 487} 488 489bool SearchBox::GetMostVisitedItemWithID( 490 InstantRestrictedID most_visited_item_id, 491 InstantMostVisitedItem* item) const { 492 return most_visited_items_cache_.GetItemWithRestrictedID(most_visited_item_id, 493 item); 494} 495 496GURL SearchBox::GetURLForMostVisitedItem(InstantRestrictedID item_id) const { 497 InstantMostVisitedItem item; 498 return GetMostVisitedItemWithID(item_id, &item) ? item.url : GURL(); 499} 500 501void SearchBox::OnToggleVoiceSearch() { 502 if (render_view()->GetWebView() && render_view()->GetWebView()->mainFrame()) { 503 extensions_v8::SearchBoxExtension::DispatchToggleVoiceSearch( 504 render_view()->GetWebView()->mainFrame()); 505 } 506} 507