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 3 // found in the LICENSE file. 4 5 #include "chrome/renderer/searchbox/searchbox_extension.h" 6 7 #include "base/i18n/rtl.h" 8 #include "base/json/string_escape.h" 9 #include "base/strings/string_number_conversions.h" 10 #include "base/strings/string_util.h" 11 #include "base/strings/stringprintf.h" 12 #include "base/strings/utf_string_conversions.h" 13 #include "chrome/common/autocomplete_match_type.h" 14 #include "chrome/common/instant_types.h" 15 #include "chrome/common/ntp_logging_events.h" 16 #include "chrome/common/url_constants.h" 17 #include "chrome/renderer/searchbox/searchbox.h" 18 #include "content/public/renderer/render_view.h" 19 #include "extensions/common/extension.h" 20 #include "grit/renderer_resources.h" 21 #include "third_party/WebKit/public/platform/WebURLRequest.h" 22 #include "third_party/WebKit/public/web/WebDocument.h" 23 #include "third_party/WebKit/public/web/WebLocalFrame.h" 24 #include "third_party/WebKit/public/web/WebScriptSource.h" 25 #include "third_party/WebKit/public/web/WebView.h" 26 #include "ui/base/resource/resource_bundle.h" 27 #include "ui/base/window_open_disposition.h" 28 #include "ui/events/keycodes/keyboard_codes.h" 29 #include "url/gurl.h" 30 #include "url/url_constants.h" 31 #include "v8/include/v8.h" 32 33 namespace { 34 35 const char kCSSBackgroundImageFormat[] = "-webkit-image-set(" 36 "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND?%s) 1x, " 37 "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND@2x?%s) 2x)"; 38 39 const char kCSSBackgroundColorFormat[] = "rgba(%d,%d,%d,%s)"; 40 41 const char kCSSBackgroundPositionCenter[] = "center"; 42 const char kCSSBackgroundPositionLeft[] = "left"; 43 const char kCSSBackgroundPositionTop[] = "top"; 44 const char kCSSBackgroundPositionRight[] = "right"; 45 const char kCSSBackgroundPositionBottom[] = "bottom"; 46 47 const char kCSSBackgroundRepeatNo[] = "no-repeat"; 48 const char kCSSBackgroundRepeatX[] = "repeat-x"; 49 const char kCSSBackgroundRepeatY[] = "repeat-y"; 50 const char kCSSBackgroundRepeat[] = "repeat"; 51 52 const char kThemeAttributionFormat[] = "-webkit-image-set(" 53 "url(chrome-search://theme/IDR_THEME_NTP_ATTRIBUTION?%s) 1x, " 54 "url(chrome-search://theme/IDR_THEME_NTP_ATTRIBUTION@2x?%s) 2x)"; 55 56 const char kLTRHtmlTextDirection[] = "ltr"; 57 const char kRTLHtmlTextDirection[] = "rtl"; 58 59 // Converts a V8 value to a string16. 60 base::string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { 61 v8::String::Value s(v); 62 return base::string16(reinterpret_cast<const base::char16*>(*s), s.length()); 63 } 64 65 // Converts string16 to V8 String. 66 v8::Handle<v8::String> UTF16ToV8String(v8::Isolate* isolate, 67 const base::string16& s) { 68 return v8::String::NewFromTwoByte(isolate, 69 reinterpret_cast<const uint16_t*>(s.data()), 70 v8::String::kNormalString, 71 s.size()); 72 } 73 74 // Converts std::string to V8 String. 75 v8::Handle<v8::String> UTF8ToV8String(v8::Isolate* isolate, 76 const std::string& s) { 77 return v8::String::NewFromUtf8( 78 isolate, s.data(), v8::String::kNormalString, s.size()); 79 } 80 81 void Dispatch(blink::WebFrame* frame, const blink::WebString& script) { 82 if (!frame) return; 83 frame->executeScript(blink::WebScriptSource(script)); 84 } 85 86 v8::Handle<v8::String> GenerateThumbnailURL( 87 v8::Isolate* isolate, 88 int render_view_id, 89 InstantRestrictedID most_visited_item_id) { 90 return UTF8ToV8String( 91 isolate, 92 base::StringPrintf( 93 "chrome-search://thumb/%d/%d", render_view_id, most_visited_item_id)); 94 } 95 96 // Populates a Javascript MostVisitedItem object from |mv_item|. 97 // NOTE: Includes "url", "title" and "domain" which are private data, so should 98 // not be returned to the Instant page. These should be erased before returning 99 // the object. See GetMostVisitedItemsWrapper() in searchbox_api.js. 100 v8::Handle<v8::Object> GenerateMostVisitedItem( 101 v8::Isolate* isolate, 102 int render_view_id, 103 InstantRestrictedID restricted_id, 104 const InstantMostVisitedItem& mv_item) { 105 // We set the "dir" attribute of the title, so that in RTL locales, a LTR 106 // title is rendered left-to-right and truncated from the right. For 107 // example, the title of http://msdn.microsoft.com/en-us/default.aspx is 108 // "MSDN: Microsoft developer network". In RTL locales, in the New Tab 109 // page, if the "dir" of this title is not specified, it takes Chrome UI's 110 // directionality. So the title will be truncated as "soft developer 111 // network". Setting the "dir" attribute as "ltr" renders the truncated 112 // title as "MSDN: Microsoft D...". As another example, the title of 113 // http://yahoo.com is "Yahoo!". In RTL locales, in the New Tab page, the 114 // title will be rendered as "!Yahoo" if its "dir" attribute is not set to 115 // "ltr". 116 std::string direction; 117 if (base::i18n::StringContainsStrongRTLChars(mv_item.title)) 118 direction = kRTLHtmlTextDirection; 119 else 120 direction = kLTRHtmlTextDirection; 121 122 base::string16 title = mv_item.title; 123 if (title.empty()) 124 title = base::UTF8ToUTF16(mv_item.url.spec()); 125 126 v8::Handle<v8::Object> obj = v8::Object::New(isolate); 127 obj->Set(v8::String::NewFromUtf8(isolate, "renderViewId"), 128 v8::Int32::New(isolate, render_view_id)); 129 obj->Set(v8::String::NewFromUtf8(isolate, "rid"), 130 v8::Int32::New(isolate, restricted_id)); 131 obj->Set(v8::String::NewFromUtf8(isolate, "thumbnailUrl"), 132 GenerateThumbnailURL(isolate, render_view_id, restricted_id)); 133 obj->Set(v8::String::NewFromUtf8(isolate, "title"), 134 UTF16ToV8String(isolate, title)); 135 obj->Set(v8::String::NewFromUtf8(isolate, "domain"), 136 UTF8ToV8String(isolate, mv_item.url.host())); 137 obj->Set(v8::String::NewFromUtf8(isolate, "direction"), 138 UTF8ToV8String(isolate, direction)); 139 obj->Set(v8::String::NewFromUtf8(isolate, "url"), 140 UTF8ToV8String(isolate, mv_item.url.spec())); 141 return obj; 142 } 143 144 // Returns the render view for the current JS context if it matches |origin|, 145 // otherwise returns NULL. Used to restrict methods that access suggestions and 146 // most visited data to pages with origin chrome-search://most-visited and 147 // chrome-search://suggestions. 148 content::RenderView* GetRenderViewWithCheckedOrigin(const GURL& origin) { 149 blink::WebLocalFrame* webframe = 150 blink::WebLocalFrame::frameForCurrentContext(); 151 if (!webframe) 152 return NULL; 153 blink::WebView* webview = webframe->view(); 154 if (!webview) 155 return NULL; // Can happen during closing. 156 content::RenderView* render_view = content::RenderView::FromWebView(webview); 157 if (!render_view) 158 return NULL; 159 160 GURL url(webframe->document().url()); 161 if (url.GetOrigin() != origin.GetOrigin()) 162 return NULL; 163 164 return render_view; 165 } 166 167 // Returns the current URL. 168 GURL GetCurrentURL(content::RenderView* render_view) { 169 blink::WebView* webview = render_view->GetWebView(); 170 return webview ? GURL(webview->mainFrame()->document().url()) : GURL(); 171 } 172 173 } // namespace 174 175 namespace internal { // for testing. 176 177 // Returns an array with the RGBA color components. 178 v8::Handle<v8::Value> RGBAColorToArray(v8::Isolate* isolate, 179 const RGBAColor& color) { 180 v8::Handle<v8::Array> color_array = v8::Array::New(isolate, 4); 181 color_array->Set(0, v8::Int32::New(isolate, color.r)); 182 color_array->Set(1, v8::Int32::New(isolate, color.g)); 183 color_array->Set(2, v8::Int32::New(isolate, color.b)); 184 color_array->Set(3, v8::Int32::New(isolate, color.a)); 185 return color_array; 186 } 187 188 // Resolves a possibly relative URL using the current URL. 189 GURL ResolveURL(const GURL& current_url, 190 const base::string16& possibly_relative_url) { 191 if (current_url.is_valid() && !possibly_relative_url.empty()) 192 return current_url.Resolve(possibly_relative_url); 193 return GURL(possibly_relative_url); 194 } 195 196 } // namespace internal 197 198 namespace extensions_v8 { 199 200 static const char kSearchBoxExtensionName[] = "v8/EmbeddedSearch"; 201 202 // We first send this script down to determine if the page supports instant. 203 static const char kSupportsInstantScript[] = 204 "if (window.chrome &&" 205 " window.chrome.embeddedSearch &&" 206 " window.chrome.embeddedSearch.searchBox &&" 207 " window.chrome.embeddedSearch.searchBox.onsubmit &&" 208 " typeof window.chrome.embeddedSearch.searchBox.onsubmit ==" 209 " 'function') {" 210 " true;" 211 "} else {" 212 " false;" 213 "}"; 214 215 static const char kDispatchChromeIdentityCheckResult[] = 216 "if (window.chrome &&" 217 " window.chrome.embeddedSearch &&" 218 " window.chrome.embeddedSearch.newTabPage &&" 219 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone &&" 220 " typeof window.chrome.embeddedSearch.newTabPage" 221 " .onsignedincheckdone === 'function') {" 222 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone(%s, %s);" 223 " true;" 224 "}"; 225 226 227 static const char kDispatchFocusChangedScript[] = 228 "if (window.chrome &&" 229 " window.chrome.embeddedSearch &&" 230 " window.chrome.embeddedSearch.searchBox &&" 231 " window.chrome.embeddedSearch.searchBox.onfocuschange &&" 232 " typeof window.chrome.embeddedSearch.searchBox.onfocuschange ==" 233 " 'function') {" 234 " window.chrome.embeddedSearch.searchBox.onfocuschange();" 235 " true;" 236 "}"; 237 238 static const char kDispatchInputCancelScript[] = 239 "if (window.chrome &&" 240 " window.chrome.embeddedSearch &&" 241 " window.chrome.embeddedSearch.newTabPage &&" 242 " window.chrome.embeddedSearch.newTabPage.oninputcancel &&" 243 " typeof window.chrome.embeddedSearch.newTabPage.oninputcancel ==" 244 " 'function') {" 245 " window.chrome.embeddedSearch.newTabPage.oninputcancel();" 246 " true;" 247 "}"; 248 249 static const char kDispatchInputStartScript[] = 250 "if (window.chrome &&" 251 " window.chrome.embeddedSearch &&" 252 " window.chrome.embeddedSearch.newTabPage &&" 253 " window.chrome.embeddedSearch.newTabPage.oninputstart &&" 254 " typeof window.chrome.embeddedSearch.newTabPage.oninputstart ==" 255 " 'function') {" 256 " window.chrome.embeddedSearch.newTabPage.oninputstart();" 257 " true;" 258 "}"; 259 260 static const char kDispatchKeyCaptureChangeScript[] = 261 "if (window.chrome &&" 262 " window.chrome.embeddedSearch &&" 263 " window.chrome.embeddedSearch.searchBox &&" 264 " window.chrome.embeddedSearch.searchBox.onkeycapturechange &&" 265 " typeof window.chrome.embeddedSearch.searchBox.onkeycapturechange ==" 266 " 'function') {" 267 " window.chrome.embeddedSearch.searchBox.onkeycapturechange();" 268 " true;" 269 "}"; 270 271 static const char kDispatchMarginChangeEventScript[] = 272 "if (window.chrome &&" 273 " window.chrome.embeddedSearch &&" 274 " window.chrome.embeddedSearch.searchBox &&" 275 " window.chrome.embeddedSearch.searchBox.onmarginchange &&" 276 " typeof window.chrome.embeddedSearch.searchBox.onmarginchange ==" 277 " 'function') {" 278 " window.chrome.embeddedSearch.searchBox.onmarginchange();" 279 " true;" 280 "}"; 281 282 static const char kDispatchMostVisitedChangedScript[] = 283 "if (window.chrome &&" 284 " window.chrome.embeddedSearch &&" 285 " window.chrome.embeddedSearch.newTabPage &&" 286 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange &&" 287 " typeof window.chrome.embeddedSearch.newTabPage.onmostvisitedchange ==" 288 " 'function') {" 289 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange();" 290 " true;" 291 "}"; 292 293 static const char kDispatchSubmitEventScript[] = 294 "if (window.chrome &&" 295 " window.chrome.embeddedSearch &&" 296 " window.chrome.embeddedSearch.searchBox &&" 297 " window.chrome.embeddedSearch.searchBox.onsubmit &&" 298 " typeof window.chrome.embeddedSearch.searchBox.onsubmit ==" 299 " 'function') {" 300 " window.chrome.embeddedSearch.searchBox.onsubmit();" 301 " true;" 302 "}"; 303 304 static const char kDispatchSuggestionChangeEventScript[] = 305 "if (window.chrome &&" 306 " window.chrome.embeddedSearch &&" 307 " window.chrome.embeddedSearch.searchBox &&" 308 " window.chrome.embeddedSearch.searchBox.onsuggestionchange &&" 309 " typeof window.chrome.embeddedSearch.searchBox.onsuggestionchange ==" 310 " 'function') {" 311 " window.chrome.embeddedSearch.searchBox.onsuggestionchange();" 312 " true;" 313 "}"; 314 315 static const char kDispatchThemeChangeEventScript[] = 316 "if (window.chrome &&" 317 " window.chrome.embeddedSearch &&" 318 " window.chrome.embeddedSearch.newTabPage &&" 319 " window.chrome.embeddedSearch.newTabPage.onthemechange &&" 320 " typeof window.chrome.embeddedSearch.newTabPage.onthemechange ==" 321 " 'function') {" 322 " window.chrome.embeddedSearch.newTabPage.onthemechange();" 323 " true;" 324 "}"; 325 326 static const char kDispatchToggleVoiceSearchScript[] = 327 "if (window.chrome &&" 328 " window.chrome.embeddedSearch &&" 329 " window.chrome.embeddedSearch.searchBox &&" 330 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch &&" 331 " typeof window.chrome.embeddedSearch.searchBox.ontogglevoicesearch ==" 332 " 'function') {" 333 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch();" 334 " true;" 335 "}"; 336 337 // ---------------------------------------------------------------------------- 338 339 class SearchBoxExtensionWrapper : public v8::Extension { 340 public: 341 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); 342 343 // Allows v8's javascript code to call the native functions defined 344 // in this class for window.chrome. 345 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate( 346 v8::Isolate*, 347 v8::Handle<v8::String> name) OVERRIDE; 348 349 // Helper function to find the RenderView. May return NULL. 350 static content::RenderView* GetRenderView(); 351 352 // Sends a Chrome identity check to the browser. 353 static void CheckIsUserSignedInToChromeAs( 354 const v8::FunctionCallbackInfo<v8::Value>& args); 355 356 // Deletes a Most Visited item. 357 static void DeleteMostVisitedItem( 358 const v8::FunctionCallbackInfo<v8::Value>& args); 359 360 // Focuses the omnibox. 361 static void Focus(const v8::FunctionCallbackInfo<v8::Value>& args); 362 363 // Gets whether or not the app launcher is enabled. 364 static void GetAppLauncherEnabled( 365 const v8::FunctionCallbackInfo<v8::Value>& args); 366 367 // Gets the desired navigation behavior from a click event. 368 static void GetDispositionFromClick( 369 const v8::FunctionCallbackInfo<v8::Value>& args); 370 371 // Gets Most Visited Items. 372 static void GetMostVisitedItems( 373 const v8::FunctionCallbackInfo<v8::Value>& args); 374 375 // Gets the raw data for a most visited item including its raw URL. 376 // GetRenderViewWithCheckedOrigin() enforces that only code in the origin 377 // chrome-search://most-visited can call this function. 378 static void GetMostVisitedItemData( 379 const v8::FunctionCallbackInfo<v8::Value>& args); 380 381 // Gets the submitted value of the user's search query. 382 static void GetQuery(const v8::FunctionCallbackInfo<v8::Value>& args); 383 384 // Returns true if the Searchbox itself is oriented right-to-left. 385 static void GetRightToLeft(const v8::FunctionCallbackInfo<v8::Value>& args); 386 387 // Gets the start-edge margin to use with extended Instant. 388 static void GetStartMargin(const v8::FunctionCallbackInfo<v8::Value>& args); 389 390 // Gets the current top suggestion to prefetch search results. 391 static void GetSuggestionToPrefetch( 392 const v8::FunctionCallbackInfo<v8::Value>& args); 393 394 // Gets the background info of the theme currently adopted by browser. 395 // Call only when overlay is showing NTP page. 396 static void GetThemeBackgroundInfo( 397 const v8::FunctionCallbackInfo<v8::Value>& args); 398 399 // Gets whether the omnibox has focus or not. 400 static void IsFocused(const v8::FunctionCallbackInfo<v8::Value>& args); 401 402 // Gets whether user input is in progress. 403 static void IsInputInProgress( 404 const v8::FunctionCallbackInfo<v8::Value>& args); 405 406 // Gets whether the browser is capturing key strokes. 407 static void IsKeyCaptureEnabled( 408 const v8::FunctionCallbackInfo<v8::Value>& args); 409 410 // Logs information from the iframes/titles on the NTP. 411 static void LogEvent(const v8::FunctionCallbackInfo<v8::Value>& args); 412 413 // Logs an impression on one of the Most Visited tile on the NTP. 414 static void LogMostVisitedImpression( 415 const v8::FunctionCallbackInfo<v8::Value>& args); 416 417 // Logs a navigation on one of the Most Visited tile on the NTP. 418 static void LogMostVisitedNavigation( 419 const v8::FunctionCallbackInfo<v8::Value>& args); 420 421 // Navigates the window to a URL represented by either a URL string or a 422 // restricted ID. 423 static void NavigateContentWindow( 424 const v8::FunctionCallbackInfo<v8::Value>& args); 425 426 // Pastes provided value or clipboard's content into the omnibox. 427 static void Paste(const v8::FunctionCallbackInfo<v8::Value>& args); 428 429 // Indicates whether the page supports voice search. 430 static void SetVoiceSearchSupported( 431 const v8::FunctionCallbackInfo<v8::Value>& args); 432 433 // Start capturing user key strokes. 434 static void StartCapturingKeyStrokes( 435 const v8::FunctionCallbackInfo<v8::Value>& args); 436 437 // Stop capturing user key strokes. 438 static void StopCapturingKeyStrokes( 439 const v8::FunctionCallbackInfo<v8::Value>& args); 440 441 // Undoes the deletion of all Most Visited itens. 442 static void UndoAllMostVisitedDeletions( 443 const v8::FunctionCallbackInfo<v8::Value>& args); 444 445 // Undoes the deletion of a Most Visited item. 446 static void UndoMostVisitedDeletion( 447 const v8::FunctionCallbackInfo<v8::Value>& args); 448 449 // Indicates whether the page supports Instant. 450 static void GetDisplayInstantResults( 451 const v8::FunctionCallbackInfo<v8::Value>& args); 452 453 private: 454 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper); 455 }; 456 457 // static 458 v8::Extension* SearchBoxExtension::Get() { 459 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). 460 GetRawDataResource(IDR_SEARCHBOX_API)); 461 } 462 463 // static 464 bool SearchBoxExtension::PageSupportsInstant(blink::WebFrame* frame) { 465 if (!frame) return false; 466 v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); 467 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( 468 blink::WebScriptSource(kSupportsInstantScript)); 469 return !v.IsEmpty() && v->BooleanValue(); 470 } 471 472 // static 473 void SearchBoxExtension::DispatchChromeIdentityCheckResult( 474 blink::WebFrame* frame, 475 const base::string16& identity, 476 bool identity_match) { 477 std::string escaped_identity = base::GetQuotedJSONString(identity); 478 blink::WebString script(base::UTF8ToUTF16(base::StringPrintf( 479 kDispatchChromeIdentityCheckResult, 480 escaped_identity.c_str(), 481 identity_match ? "true" : "false"))); 482 Dispatch(frame, script); 483 } 484 485 // static 486 void SearchBoxExtension::DispatchFocusChange(blink::WebFrame* frame) { 487 Dispatch(frame, kDispatchFocusChangedScript); 488 } 489 490 // static 491 void SearchBoxExtension::DispatchInputCancel(blink::WebFrame* frame) { 492 Dispatch(frame, kDispatchInputCancelScript); 493 } 494 495 // static 496 void SearchBoxExtension::DispatchInputStart(blink::WebFrame* frame) { 497 Dispatch(frame, kDispatchInputStartScript); 498 } 499 500 // static 501 void SearchBoxExtension::DispatchKeyCaptureChange(blink::WebFrame* frame) { 502 Dispatch(frame, kDispatchKeyCaptureChangeScript); 503 } 504 505 // static 506 void SearchBoxExtension::DispatchMarginChange(blink::WebFrame* frame) { 507 Dispatch(frame, kDispatchMarginChangeEventScript); 508 } 509 510 // static 511 void SearchBoxExtension::DispatchMostVisitedChanged( 512 blink::WebFrame* frame) { 513 Dispatch(frame, kDispatchMostVisitedChangedScript); 514 } 515 516 // static 517 void SearchBoxExtension::DispatchSubmit(blink::WebFrame* frame) { 518 Dispatch(frame, kDispatchSubmitEventScript); 519 } 520 521 // static 522 void SearchBoxExtension::DispatchSuggestionChange(blink::WebFrame* frame) { 523 Dispatch(frame, kDispatchSuggestionChangeEventScript); 524 } 525 526 // static 527 void SearchBoxExtension::DispatchThemeChange(blink::WebFrame* frame) { 528 Dispatch(frame, kDispatchThemeChangeEventScript); 529 } 530 531 // static 532 void SearchBoxExtension::DispatchToggleVoiceSearch( 533 blink::WebFrame* frame) { 534 Dispatch(frame, kDispatchToggleVoiceSearchScript); 535 } 536 537 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper( 538 const base::StringPiece& code) 539 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) { 540 } 541 542 v8::Handle<v8::FunctionTemplate> 543 SearchBoxExtensionWrapper::GetNativeFunctionTemplate( 544 v8::Isolate* isolate, 545 v8::Handle<v8::String> name) { 546 if (name->Equals( 547 v8::String::NewFromUtf8(isolate, "CheckIsUserSignedInToChromeAs"))) 548 return v8::FunctionTemplate::New(isolate, CheckIsUserSignedInToChromeAs); 549 if (name->Equals(v8::String::NewFromUtf8(isolate, "DeleteMostVisitedItem"))) 550 return v8::FunctionTemplate::New(isolate, DeleteMostVisitedItem); 551 if (name->Equals(v8::String::NewFromUtf8(isolate, "Focus"))) 552 return v8::FunctionTemplate::New(isolate, Focus); 553 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetAppLauncherEnabled"))) 554 return v8::FunctionTemplate::New(isolate, GetAppLauncherEnabled); 555 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetDispositionFromClick"))) 556 return v8::FunctionTemplate::New(isolate, GetDispositionFromClick); 557 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetMostVisitedItems"))) 558 return v8::FunctionTemplate::New(isolate, GetMostVisitedItems); 559 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetMostVisitedItemData"))) 560 return v8::FunctionTemplate::New(isolate, GetMostVisitedItemData); 561 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetQuery"))) 562 return v8::FunctionTemplate::New(isolate, GetQuery); 563 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetRightToLeft"))) 564 return v8::FunctionTemplate::New(isolate, GetRightToLeft); 565 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetStartMargin"))) 566 return v8::FunctionTemplate::New(isolate, GetStartMargin); 567 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetSuggestionToPrefetch"))) 568 return v8::FunctionTemplate::New(isolate, GetSuggestionToPrefetch); 569 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetThemeBackgroundInfo"))) 570 return v8::FunctionTemplate::New(isolate, GetThemeBackgroundInfo); 571 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsFocused"))) 572 return v8::FunctionTemplate::New(isolate, IsFocused); 573 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsInputInProgress"))) 574 return v8::FunctionTemplate::New(isolate, IsInputInProgress); 575 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsKeyCaptureEnabled"))) 576 return v8::FunctionTemplate::New(isolate, IsKeyCaptureEnabled); 577 if (name->Equals(v8::String::NewFromUtf8(isolate, "LogEvent"))) 578 return v8::FunctionTemplate::New(isolate, LogEvent); 579 if (name->Equals( 580 v8::String::NewFromUtf8(isolate, "LogMostVisitedImpression"))) { 581 return v8::FunctionTemplate::New(isolate, LogMostVisitedImpression); 582 } 583 if (name->Equals( 584 v8::String::NewFromUtf8(isolate, "LogMostVisitedNavigation"))) { 585 return v8::FunctionTemplate::New(isolate, LogMostVisitedNavigation); 586 } 587 if (name->Equals(v8::String::NewFromUtf8(isolate, "NavigateContentWindow"))) 588 return v8::FunctionTemplate::New(isolate, NavigateContentWindow); 589 if (name->Equals(v8::String::NewFromUtf8(isolate, "Paste"))) 590 return v8::FunctionTemplate::New(isolate, Paste); 591 if (name->Equals(v8::String::NewFromUtf8(isolate, "SetVoiceSearchSupported"))) 592 return v8::FunctionTemplate::New(isolate, SetVoiceSearchSupported); 593 if (name->Equals( 594 v8::String::NewFromUtf8(isolate, "StartCapturingKeyStrokes"))) 595 return v8::FunctionTemplate::New(isolate, StartCapturingKeyStrokes); 596 if (name->Equals(v8::String::NewFromUtf8(isolate, "StopCapturingKeyStrokes"))) 597 return v8::FunctionTemplate::New(isolate, StopCapturingKeyStrokes); 598 if (name->Equals( 599 v8::String::NewFromUtf8(isolate, "UndoAllMostVisitedDeletions"))) 600 return v8::FunctionTemplate::New(isolate, UndoAllMostVisitedDeletions); 601 if (name->Equals(v8::String::NewFromUtf8(isolate, "UndoMostVisitedDeletion"))) 602 return v8::FunctionTemplate::New(isolate, UndoMostVisitedDeletion); 603 if (name->Equals( 604 v8::String::NewFromUtf8(isolate, "GetDisplayInstantResults"))) 605 return v8::FunctionTemplate::New(isolate, GetDisplayInstantResults); 606 return v8::Handle<v8::FunctionTemplate>(); 607 } 608 609 // static 610 content::RenderView* SearchBoxExtensionWrapper::GetRenderView() { 611 blink::WebLocalFrame* webframe = 612 blink::WebLocalFrame::frameForCurrentContext(); 613 if (!webframe) return NULL; 614 615 blink::WebView* webview = webframe->view(); 616 if (!webview) return NULL; // can happen during closing 617 618 return content::RenderView::FromWebView(webview); 619 } 620 621 // static 622 void SearchBoxExtensionWrapper::CheckIsUserSignedInToChromeAs( 623 const v8::FunctionCallbackInfo<v8::Value>& args) { 624 content::RenderView* render_view = GetRenderView(); 625 if (!render_view || args.Length() == 0 || args[0]->IsUndefined()) return; 626 627 DVLOG(1) << render_view << " CheckIsUserSignedInToChromeAs"; 628 629 SearchBox::Get(render_view)->CheckIsUserSignedInToChromeAs( 630 V8ValueToUTF16(args[0])); 631 } 632 633 // static 634 void SearchBoxExtensionWrapper::DeleteMostVisitedItem( 635 const v8::FunctionCallbackInfo<v8::Value>& args) { 636 content::RenderView* render_view = GetRenderView(); 637 if (!render_view || !args.Length()) return; 638 639 DVLOG(1) << render_view << " DeleteMostVisitedItem"; 640 SearchBox::Get(render_view)->DeleteMostVisitedItem(args[0]->IntegerValue()); 641 } 642 643 // static 644 void SearchBoxExtensionWrapper::Focus( 645 const v8::FunctionCallbackInfo<v8::Value>& args) { 646 content::RenderView* render_view = GetRenderView(); 647 if (!render_view) return; 648 649 DVLOG(1) << render_view << " Focus"; 650 SearchBox::Get(render_view)->Focus(); 651 } 652 653 // static 654 void SearchBoxExtensionWrapper::GetAppLauncherEnabled( 655 const v8::FunctionCallbackInfo<v8::Value>& args) { 656 content::RenderView* render_view = GetRenderView(); 657 if (!render_view) return; 658 659 args.GetReturnValue().Set( 660 SearchBox::Get(render_view)->app_launcher_enabled()); 661 } 662 663 // static 664 void SearchBoxExtensionWrapper::GetDispositionFromClick( 665 const v8::FunctionCallbackInfo<v8::Value>& args) { 666 content::RenderView* render_view = GetRenderView(); 667 if (!render_view || args.Length() != 5) return; 668 669 bool middle_button = args[0]->BooleanValue(); 670 bool alt_key = args[1]->BooleanValue(); 671 bool ctrl_key = args[2]->BooleanValue(); 672 bool meta_key = args[3]->BooleanValue(); 673 bool shift_key = args[4]->BooleanValue(); 674 675 WindowOpenDisposition disposition = ui::DispositionFromClick(middle_button, 676 alt_key, 677 ctrl_key, 678 meta_key, 679 shift_key); 680 v8::Isolate* isolate = args.GetIsolate(); 681 args.GetReturnValue().Set(v8::Int32::New(isolate, disposition)); 682 } 683 684 // static 685 void SearchBoxExtensionWrapper::GetMostVisitedItems( 686 const v8::FunctionCallbackInfo<v8::Value>& args) { 687 content::RenderView* render_view = GetRenderView(); 688 if (!render_view) 689 return; 690 DVLOG(1) << render_view << " GetMostVisitedItems"; 691 692 const SearchBox* search_box = SearchBox::Get(render_view); 693 694 std::vector<InstantMostVisitedItemIDPair> instant_mv_items; 695 search_box->GetMostVisitedItems(&instant_mv_items); 696 v8::Isolate* isolate = args.GetIsolate(); 697 v8::Handle<v8::Array> v8_mv_items = 698 v8::Array::New(isolate, instant_mv_items.size()); 699 for (size_t i = 0; i < instant_mv_items.size(); ++i) { 700 v8_mv_items->Set(i, 701 GenerateMostVisitedItem(isolate, 702 render_view->GetRoutingID(), 703 instant_mv_items[i].first, 704 instant_mv_items[i].second)); 705 } 706 args.GetReturnValue().Set(v8_mv_items); 707 } 708 709 // static 710 void SearchBoxExtensionWrapper::GetMostVisitedItemData( 711 const v8::FunctionCallbackInfo<v8::Value>& args) { 712 content::RenderView* render_view = GetRenderViewWithCheckedOrigin( 713 GURL(chrome::kChromeSearchMostVisitedUrl)); 714 if (!render_view) return; 715 716 // Need an rid argument. 717 if (args.Length() < 1 || !args[0]->IsNumber()) 718 return; 719 720 DVLOG(1) << render_view << " GetMostVisitedItem"; 721 InstantRestrictedID restricted_id = args[0]->IntegerValue(); 722 InstantMostVisitedItem mv_item; 723 if (!SearchBox::Get(render_view)->GetMostVisitedItemWithID( 724 restricted_id, &mv_item)) { 725 return; 726 } 727 v8::Isolate* isolate = args.GetIsolate(); 728 args.GetReturnValue().Set(GenerateMostVisitedItem( 729 isolate, render_view->GetRoutingID(), restricted_id, mv_item)); 730 } 731 732 // static 733 void SearchBoxExtensionWrapper::GetQuery( 734 const v8::FunctionCallbackInfo<v8::Value>& args) { 735 content::RenderView* render_view = GetRenderView(); 736 if (!render_view) return; 737 const base::string16& query = SearchBox::Get(render_view)->query(); 738 DVLOG(1) << render_view << " GetQuery: '" << query << "'"; 739 v8::Isolate* isolate = args.GetIsolate(); 740 args.GetReturnValue().Set(UTF16ToV8String(isolate, query)); 741 } 742 743 // static 744 void SearchBoxExtensionWrapper::GetRightToLeft( 745 const v8::FunctionCallbackInfo<v8::Value>& args) { 746 args.GetReturnValue().Set(base::i18n::IsRTL()); 747 } 748 749 // static 750 void SearchBoxExtensionWrapper::GetStartMargin( 751 const v8::FunctionCallbackInfo<v8::Value>& args) { 752 content::RenderView* render_view = GetRenderView(); 753 if (!render_view) return; 754 args.GetReturnValue().Set(static_cast<int32_t>( 755 SearchBox::Get(render_view)->start_margin())); 756 } 757 758 // static 759 void SearchBoxExtensionWrapper::GetSuggestionToPrefetch( 760 const v8::FunctionCallbackInfo<v8::Value>& args) { 761 content::RenderView* render_view = GetRenderView(); 762 if (!render_view) return; 763 764 const InstantSuggestion& suggestion = 765 SearchBox::Get(render_view)->suggestion(); 766 v8::Isolate* isolate = args.GetIsolate(); 767 v8::Handle<v8::Object> data = v8::Object::New(isolate); 768 data->Set(v8::String::NewFromUtf8(isolate, "text"), 769 UTF16ToV8String(isolate, suggestion.text)); 770 data->Set(v8::String::NewFromUtf8(isolate, "metadata"), 771 UTF8ToV8String(isolate, suggestion.metadata)); 772 args.GetReturnValue().Set(data); 773 } 774 775 // static 776 void SearchBoxExtensionWrapper::GetThemeBackgroundInfo( 777 const v8::FunctionCallbackInfo<v8::Value>& args) { 778 content::RenderView* render_view = GetRenderView(); 779 if (!render_view) return; 780 781 DVLOG(1) << render_view << " GetThemeBackgroundInfo"; 782 const ThemeBackgroundInfo& theme_info = 783 SearchBox::Get(render_view)->GetThemeBackgroundInfo(); 784 v8::Isolate* isolate = args.GetIsolate(); 785 v8::Handle<v8::Object> info = v8::Object::New(isolate); 786 787 info->Set(v8::String::NewFromUtf8(isolate, "usingDefaultTheme"), 788 v8::Boolean::New(isolate, theme_info.using_default_theme)); 789 790 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and 791 // B are between 0 and 255 inclusive, and A is a double between 0 and 1 792 // inclusive. 793 // This is the CSS "background-color" format. 794 // Value is always valid. 795 // TODO(jfweitz): Remove this field after GWS is modified to use the new 796 // backgroundColorRgba field. 797 info->Set( 798 v8::String::NewFromUtf8(isolate, "colorRgba"), 799 UTF8ToV8String( 800 isolate, 801 // Convert the alpha using DoubleToString because StringPrintf will 802 // use 803 // locale specific formatters (e.g., use , instead of . in German). 804 base::StringPrintf( 805 kCSSBackgroundColorFormat, 806 theme_info.background_color.r, 807 theme_info.background_color.g, 808 theme_info.background_color.b, 809 base::DoubleToString(theme_info.background_color.a / 255.0) 810 .c_str()))); 811 812 // Theme color for background as an array with the RGBA components in order. 813 // Value is always valid. 814 info->Set(v8::String::NewFromUtf8(isolate, "backgroundColorRgba"), 815 internal::RGBAColorToArray(isolate, theme_info.background_color)); 816 817 // Theme color for text as an array with the RGBA components in order. 818 // Value is always valid. 819 info->Set(v8::String::NewFromUtf8(isolate, "textColorRgba"), 820 internal::RGBAColorToArray(isolate, theme_info.text_color)); 821 822 // Theme color for links as an array with the RGBA components in order. 823 // Value is always valid. 824 info->Set(v8::String::NewFromUtf8(isolate, "linkColorRgba"), 825 internal::RGBAColorToArray(isolate, theme_info.link_color)); 826 827 // Theme color for light text as an array with the RGBA components in order. 828 // Value is always valid. 829 info->Set(v8::String::NewFromUtf8(isolate, "textColorLightRgba"), 830 internal::RGBAColorToArray(isolate, theme_info.text_color_light)); 831 832 // Theme color for header as an array with the RGBA components in order. 833 // Value is always valid. 834 info->Set(v8::String::NewFromUtf8(isolate, "headerColorRgba"), 835 internal::RGBAColorToArray(isolate, theme_info.header_color)); 836 837 // Theme color for section border as an array with the RGBA components in 838 // order. Value is always valid. 839 info->Set( 840 v8::String::NewFromUtf8(isolate, "sectionBorderColorRgba"), 841 internal::RGBAColorToArray(isolate, theme_info.section_border_color)); 842 843 // The theme alternate logo value indicates a white logo when TRUE and a 844 // colorful one when FALSE. 845 info->Set(v8::String::NewFromUtf8(isolate, "alternateLogo"), 846 v8::Boolean::New(isolate, theme_info.logo_alternate)); 847 848 // The theme background image url is of format kCSSBackgroundImageFormat 849 // where both instances of "%s" are replaced with the id that identifies the 850 // theme. 851 // This is the CSS "background-image" format. 852 // Value is only valid if there's a custom theme background image. 853 if (extensions::Extension::IdIsValid(theme_info.theme_id)) { 854 info->Set(v8::String::NewFromUtf8(isolate, "imageUrl"), 855 UTF8ToV8String(isolate, 856 base::StringPrintf(kCSSBackgroundImageFormat, 857 theme_info.theme_id.c_str(), 858 theme_info.theme_id.c_str()))); 859 860 // The theme background image horizontal alignment is one of "left", 861 // "right", "center". 862 // This is the horizontal component of the CSS "background-position" format. 863 // Value is only valid if |imageUrl| is not empty. 864 std::string alignment = kCSSBackgroundPositionCenter; 865 if (theme_info.image_horizontal_alignment == 866 THEME_BKGRND_IMAGE_ALIGN_LEFT) { 867 alignment = kCSSBackgroundPositionLeft; 868 } else if (theme_info.image_horizontal_alignment == 869 THEME_BKGRND_IMAGE_ALIGN_RIGHT) { 870 alignment = kCSSBackgroundPositionRight; 871 } 872 info->Set(v8::String::NewFromUtf8(isolate, "imageHorizontalAlignment"), 873 UTF8ToV8String(isolate, alignment)); 874 875 // The theme background image vertical alignment is one of "top", "bottom", 876 // "center". 877 // This is the vertical component of the CSS "background-position" format. 878 // Value is only valid if |image_url| is not empty. 879 if (theme_info.image_vertical_alignment == THEME_BKGRND_IMAGE_ALIGN_TOP) { 880 alignment = kCSSBackgroundPositionTop; 881 } else if (theme_info.image_vertical_alignment == 882 THEME_BKGRND_IMAGE_ALIGN_BOTTOM) { 883 alignment = kCSSBackgroundPositionBottom; 884 } else { 885 alignment = kCSSBackgroundPositionCenter; 886 } 887 info->Set(v8::String::NewFromUtf8(isolate, "imageVerticalAlignment"), 888 UTF8ToV8String(isolate, alignment)); 889 890 // The tiling of the theme background image is one of "no-repeat", 891 // "repeat-x", "repeat-y", "repeat". 892 // This is the CSS "background-repeat" format. 893 // Value is only valid if |image_url| is not empty. 894 std::string tiling = kCSSBackgroundRepeatNo; 895 switch (theme_info.image_tiling) { 896 case THEME_BKGRND_IMAGE_NO_REPEAT: 897 tiling = kCSSBackgroundRepeatNo; 898 break; 899 case THEME_BKGRND_IMAGE_REPEAT_X: 900 tiling = kCSSBackgroundRepeatX; 901 break; 902 case THEME_BKGRND_IMAGE_REPEAT_Y: 903 tiling = kCSSBackgroundRepeatY; 904 break; 905 case THEME_BKGRND_IMAGE_REPEAT: 906 tiling = kCSSBackgroundRepeat; 907 break; 908 } 909 info->Set(v8::String::NewFromUtf8(isolate, "imageTiling"), 910 UTF8ToV8String(isolate, tiling)); 911 912 // The theme background image height is only valid if |imageUrl| is valid. 913 info->Set(v8::String::NewFromUtf8(isolate, "imageHeight"), 914 v8::Int32::New(isolate, theme_info.image_height)); 915 916 // The attribution URL is only valid if the theme has attribution logo. 917 if (theme_info.has_attribution) { 918 info->Set( 919 v8::String::NewFromUtf8(isolate, "attributionUrl"), 920 UTF8ToV8String(isolate, 921 base::StringPrintf(kThemeAttributionFormat, 922 theme_info.theme_id.c_str(), 923 theme_info.theme_id.c_str()))); 924 } 925 } 926 927 args.GetReturnValue().Set(info); 928 } 929 930 // static 931 void SearchBoxExtensionWrapper::IsFocused( 932 const v8::FunctionCallbackInfo<v8::Value>& args) { 933 content::RenderView* render_view = GetRenderView(); 934 if (!render_view) return; 935 936 bool is_focused = SearchBox::Get(render_view)->is_focused(); 937 DVLOG(1) << render_view << " IsFocused: " << is_focused; 938 args.GetReturnValue().Set(is_focused); 939 } 940 941 // static 942 void SearchBoxExtensionWrapper::IsInputInProgress( 943 const v8::FunctionCallbackInfo<v8::Value>& args) { 944 content::RenderView* render_view = GetRenderView(); 945 if (!render_view) return; 946 947 bool is_input_in_progress = 948 SearchBox::Get(render_view)->is_input_in_progress(); 949 DVLOG(1) << render_view << " IsInputInProgress: " << is_input_in_progress; 950 args.GetReturnValue().Set(is_input_in_progress); 951 } 952 953 // static 954 void SearchBoxExtensionWrapper::IsKeyCaptureEnabled( 955 const v8::FunctionCallbackInfo<v8::Value>& args) { 956 content::RenderView* render_view = GetRenderView(); 957 if (!render_view) return; 958 959 args.GetReturnValue().Set(SearchBox::Get(render_view)-> 960 is_key_capture_enabled()); 961 } 962 963 // static 964 void SearchBoxExtensionWrapper::LogEvent( 965 const v8::FunctionCallbackInfo<v8::Value>& args) { 966 content::RenderView* render_view = GetRenderViewWithCheckedOrigin( 967 GURL(chrome::kChromeSearchMostVisitedUrl)); 968 if (!render_view) return; 969 970 if (args.Length() < 1 || !args[0]->IsNumber()) 971 return; 972 973 DVLOG(1) << render_view << " LogEvent"; 974 975 if (args[0]->Uint32Value() < NTP_NUM_EVENT_TYPES) { 976 NTPLoggingEventType event = 977 static_cast<NTPLoggingEventType>(args[0]->Uint32Value()); 978 SearchBox::Get(render_view)->LogEvent(event); 979 } 980 } 981 982 // static 983 void SearchBoxExtensionWrapper::LogMostVisitedImpression( 984 const v8::FunctionCallbackInfo<v8::Value>& args) { 985 content::RenderView* render_view = GetRenderViewWithCheckedOrigin( 986 GURL(chrome::kChromeSearchMostVisitedUrl)); 987 if (!render_view) return; 988 989 if (args.Length() < 2 || !args[0]->IsNumber() || args[1]->IsUndefined()) 990 return; 991 992 DVLOG(1) << render_view << " LogMostVisitedImpression"; 993 994 SearchBox::Get(render_view)->LogMostVisitedImpression( 995 args[0]->IntegerValue(), V8ValueToUTF16(args[1])); 996 } 997 998 // static 999 void SearchBoxExtensionWrapper::LogMostVisitedNavigation( 1000 const v8::FunctionCallbackInfo<v8::Value>& args) { 1001 content::RenderView* render_view = GetRenderViewWithCheckedOrigin( 1002 GURL(chrome::kChromeSearchMostVisitedUrl)); 1003 if (!render_view) return; 1004 1005 if (args.Length() < 2 || !args[0]->IsNumber() || args[1]->IsUndefined()) 1006 return; 1007 1008 DVLOG(1) << render_view << " LogMostVisitedNavigation"; 1009 1010 SearchBox::Get(render_view)->LogMostVisitedNavigation( 1011 args[0]->IntegerValue(), V8ValueToUTF16(args[1])); 1012 } 1013 1014 // static 1015 void SearchBoxExtensionWrapper::NavigateContentWindow( 1016 const v8::FunctionCallbackInfo<v8::Value>& args) { 1017 content::RenderView* render_view = GetRenderView(); 1018 if (!render_view || !args.Length()) return; 1019 1020 GURL destination_url; 1021 bool is_most_visited_item_url = false; 1022 // Check if the url is a rid 1023 if (args[0]->IsNumber()) { 1024 InstantMostVisitedItem item; 1025 if (SearchBox::Get(render_view)->GetMostVisitedItemWithID( 1026 args[0]->IntegerValue(), &item)) { 1027 destination_url = item.url; 1028 is_most_visited_item_url = true; 1029 } 1030 } else { 1031 // Resolve the URL 1032 const base::string16& possibly_relative_url = V8ValueToUTF16(args[0]); 1033 GURL current_url = GetCurrentURL(render_view); 1034 destination_url = internal::ResolveURL(current_url, possibly_relative_url); 1035 } 1036 1037 DVLOG(1) << render_view << " NavigateContentWindow: " << destination_url; 1038 1039 // Navigate the main frame. 1040 if (destination_url.is_valid() && 1041 !destination_url.SchemeIs(url::kJavaScriptScheme)) { 1042 WindowOpenDisposition disposition = CURRENT_TAB; 1043 if (args[1]->IsNumber()) { 1044 disposition = (WindowOpenDisposition) args[1]->Uint32Value(); 1045 } 1046 SearchBox::Get(render_view)->NavigateToURL(destination_url, disposition, 1047 is_most_visited_item_url); 1048 } 1049 } 1050 1051 // static 1052 void SearchBoxExtensionWrapper::Paste( 1053 const v8::FunctionCallbackInfo<v8::Value>& args) { 1054 content::RenderView* render_view = GetRenderView(); 1055 if (!render_view) return; 1056 1057 base::string16 text; 1058 if (!args[0]->IsUndefined()) 1059 text = V8ValueToUTF16(args[0]); 1060 1061 DVLOG(1) << render_view << " Paste: " << text; 1062 SearchBox::Get(render_view)->Paste(text); 1063 } 1064 1065 // static 1066 void SearchBoxExtensionWrapper::StartCapturingKeyStrokes( 1067 const v8::FunctionCallbackInfo<v8::Value>& args) { 1068 content::RenderView* render_view = GetRenderView(); 1069 if (!render_view) return; 1070 1071 DVLOG(1) << render_view << " StartCapturingKeyStrokes"; 1072 SearchBox::Get(render_view)->StartCapturingKeyStrokes(); 1073 } 1074 1075 // static 1076 void SearchBoxExtensionWrapper::StopCapturingKeyStrokes( 1077 const v8::FunctionCallbackInfo<v8::Value>& args) { 1078 content::RenderView* render_view = GetRenderView(); 1079 if (!render_view) return; 1080 1081 DVLOG(1) << render_view << " StopCapturingKeyStrokes"; 1082 SearchBox::Get(render_view)->StopCapturingKeyStrokes(); 1083 } 1084 1085 // static 1086 void SearchBoxExtensionWrapper::SetVoiceSearchSupported( 1087 const v8::FunctionCallbackInfo<v8::Value>& args) { 1088 content::RenderView* render_view = GetRenderView(); 1089 if (!render_view || args.Length() < 1) return; 1090 1091 DVLOG(1) << render_view << " SetVoiceSearchSupported"; 1092 SearchBox::Get(render_view)->SetVoiceSearchSupported(args[0]->BooleanValue()); 1093 } 1094 1095 // static 1096 void SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions( 1097 const v8::FunctionCallbackInfo<v8::Value>& args) { 1098 content::RenderView* render_view = GetRenderView(); 1099 if (!render_view) return; 1100 1101 DVLOG(1) << render_view << " UndoAllMostVisitedDeletions"; 1102 SearchBox::Get(render_view)->UndoAllMostVisitedDeletions(); 1103 } 1104 1105 // static 1106 void SearchBoxExtensionWrapper::UndoMostVisitedDeletion( 1107 const v8::FunctionCallbackInfo<v8::Value>& args) { 1108 content::RenderView* render_view = GetRenderView(); 1109 if (!render_view || !args.Length()) return; 1110 1111 DVLOG(1) << render_view << " UndoMostVisitedDeletion"; 1112 SearchBox::Get(render_view)->UndoMostVisitedDeletion(args[0]->IntegerValue()); 1113 } 1114 1115 // static 1116 void SearchBoxExtensionWrapper::GetDisplayInstantResults( 1117 const v8::FunctionCallbackInfo<v8::Value>& args) { 1118 content::RenderView* render_view = GetRenderView(); 1119 if (!render_view) return; 1120 1121 bool display_instant_results = 1122 SearchBox::Get(render_view)->display_instant_results(); 1123 DVLOG(1) << render_view << " GetDisplayInstantResults" << 1124 display_instant_results; 1125 args.GetReturnValue().Set(display_instant_results); 1126 } 1127 1128 } // namespace extensions_v8 1129