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