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.
5 #include "chrome/renderer/searchbox/searchbox_extension.h"
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/common/url_constants.h"
19 #include "content/public/renderer/render_view.h"
20 #include "extensions/common/extension.h"
21 #include "grit/renderer_resources.h"
22 #include "third_party/WebKit/public/platform/WebURLRequest.h"
23 #include "third_party/WebKit/public/web/WebDocument.h"
24 #include "third_party/WebKit/public/web/WebFrame.h"
25 #include "third_party/WebKit/public/web/WebScriptSource.h"
26 #include "third_party/WebKit/public/web/WebView.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/base/window_open_disposition.h"
29 #include "ui/events/keycodes/keyboard_codes.h"
31 #include "v8/include/v8.h"
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)";
39 const char kCSSBackgroundColorFormat
[] = "rgba(%d,%d,%d,%s)";
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";
47 const char kCSSBackgroundRepeatNo
[] = "no-repeat";
48 const char kCSSBackgroundRepeatX
[] = "repeat-x";
49 const char kCSSBackgroundRepeatY
[] = "repeat-y";
50 const char kCSSBackgroundRepeat
[] = "repeat";
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)";
56 const char kLTRHtmlTextDirection
[] = "ltr";
57 const char kRTLHtmlTextDirection
[] = "rtl";
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());
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
,
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());
81 void Dispatch(blink::WebFrame
* frame
, const blink::WebString
& script
) {
83 frame
->executeScript(blink::WebScriptSource(script
));
86 v8::Handle
<v8::String
> GenerateThumbnailURL(
89 InstantRestrictedID most_visited_item_id
) {
90 return UTF8ToV8String(
93 "chrome-search://thumb/%d/%d", render_view_id
, most_visited_item_id
));
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
,
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
116 std::string direction
;
117 if (base::i18n::StringContainsStrongRTLChars(mv_item
.title
))
118 direction
= kRTLHtmlTextDirection
;
120 direction
= kLTRHtmlTextDirection
;
122 base::string16 title
= mv_item
.title
;
124 title
= base::UTF8ToUTF16(mv_item
.url
.spec());
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()));
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::WebFrame
* webframe
= blink::WebFrame::frameForCurrentContext();
152 blink::WebView
* webview
= webframe
->view();
154 return NULL
; // Can happen during closing.
155 content::RenderView
* render_view
= content::RenderView::FromWebView(webview
);
159 GURL
url(webframe
->document().url());
160 if (url
.GetOrigin() != origin
.GetOrigin())
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();
174 namespace internal
{ // for testing.
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
));
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
);
195 } // namespace internal
197 namespace extensions_v8
{
199 static const char kSearchBoxExtensionName
[] = "v8/EmbeddedSearch";
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 =="
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);"
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 =="
233 " window.chrome.embeddedSearch.searchBox.onfocuschange();"
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 =="
244 " window.chrome.embeddedSearch.newTabPage.oninputcancel();"
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 =="
255 " window.chrome.embeddedSearch.newTabPage.oninputstart();"
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 =="
266 " window.chrome.embeddedSearch.searchBox.onkeycapturechange();"
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 =="
277 " window.chrome.embeddedSearch.searchBox.onmarginchange();"
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 =="
288 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange();"
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 =="
299 " window.chrome.embeddedSearch.searchBox.onsubmit();"
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 =="
310 " window.chrome.embeddedSearch.searchBox.onsuggestionchange();"
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 =="
321 " window.chrome.embeddedSearch.newTabPage.onthemechange();"
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 =="
332 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch();"
336 // ----------------------------------------------------------------------------
338 class SearchBoxExtensionWrapper
: public v8::Extension
{
340 explicit SearchBoxExtensionWrapper(const base::StringPiece
& code
);
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(
346 v8::Handle
<v8::String
> name
) OVERRIDE
;
348 // Helper function to find the RenderView. May return NULL.
349 static content::RenderView
* GetRenderView();
351 // Sends a Chrome identity check to the browser.
352 static void CheckIsUserSignedInToChromeAs(
353 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
355 // Deletes a Most Visited item.
356 static void DeleteMostVisitedItem(
357 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
359 // Focuses the omnibox.
360 static void Focus(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
362 // Gets whether or not the app launcher is enabled.
363 static void GetAppLauncherEnabled(
364 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
366 // Gets the desired navigation behavior from a click event.
367 static void GetDispositionFromClick(
368 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
370 // Gets Most Visited Items.
371 static void GetMostVisitedItems(
372 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
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
);
380 // Gets the submitted value of the user's search query.
381 static void GetQuery(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
383 // Returns true if the Searchbox itself is oriented right-to-left.
384 static void GetRightToLeft(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
386 // Gets the start-edge margin to use with extended Instant.
387 static void GetStartMargin(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
389 // Gets the current top suggestion to prefetch search results.
390 static void GetSuggestionToPrefetch(
391 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
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
);
398 // Gets whether the omnibox has focus or not.
399 static void IsFocused(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
401 // Gets whether user input is in progress.
402 static void IsInputInProgress(
403 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
405 // Gets whether the browser is capturing key strokes.
406 static void IsKeyCaptureEnabled(
407 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
409 // Logs information from the iframes/titles on the NTP.
410 static void LogEvent(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
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
);
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
);
420 // Navigates the window to a URL represented by either a URL string or a
422 static void NavigateContentWindow(
423 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
425 // Pastes provided value or clipboard's content into the omnibox.
426 static void Paste(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
428 // Indicates whether the page supports voice search.
429 static void SetVoiceSearchSupported(
430 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
432 // Start capturing user key strokes.
433 static void StartCapturingKeyStrokes(
434 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
436 // Stop capturing user key strokes.
437 static void StopCapturingKeyStrokes(
438 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
440 // Undoes the deletion of all Most Visited itens.
441 static void UndoAllMostVisitedDeletions(
442 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
444 // Undoes the deletion of a Most Visited item.
445 static void UndoMostVisitedDeletion(
446 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
448 // Indicates whether the page supports Instant.
449 static void GetDisplayInstantResults(
450 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
453 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper
);
457 v8::Extension
* SearchBoxExtension::Get() {
458 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance().
459 GetRawDataResource(IDR_SEARCHBOX_API
));
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();
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
);
485 void SearchBoxExtension::DispatchFocusChange(blink::WebFrame
* frame
) {
486 Dispatch(frame
, kDispatchFocusChangedScript
);
490 void SearchBoxExtension::DispatchInputCancel(blink::WebFrame
* frame
) {
491 Dispatch(frame
, kDispatchInputCancelScript
);
495 void SearchBoxExtension::DispatchInputStart(blink::WebFrame
* frame
) {
496 Dispatch(frame
, kDispatchInputStartScript
);
500 void SearchBoxExtension::DispatchKeyCaptureChange(blink::WebFrame
* frame
) {
501 Dispatch(frame
, kDispatchKeyCaptureChangeScript
);
505 void SearchBoxExtension::DispatchMarginChange(blink::WebFrame
* frame
) {
506 Dispatch(frame
, kDispatchMarginChangeEventScript
);
510 void SearchBoxExtension::DispatchMostVisitedChanged(
511 blink::WebFrame
* frame
) {
512 Dispatch(frame
, kDispatchMostVisitedChangedScript
);
516 void SearchBoxExtension::DispatchSubmit(blink::WebFrame
* frame
) {
517 Dispatch(frame
, kDispatchSubmitEventScript
);
521 void SearchBoxExtension::DispatchSuggestionChange(blink::WebFrame
* frame
) {
522 Dispatch(frame
, kDispatchSuggestionChangeEventScript
);
526 void SearchBoxExtension::DispatchThemeChange(blink::WebFrame
* frame
) {
527 Dispatch(frame
, kDispatchThemeChangeEventScript
);
531 void SearchBoxExtension::DispatchToggleVoiceSearch(
532 blink::WebFrame
* frame
) {
533 Dispatch(frame
, kDispatchToggleVoiceSearchScript
);
536 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper(
537 const base::StringPiece
& code
)
538 : v8::Extension(kSearchBoxExtensionName
, code
.data(), 0, 0, code
.size()) {
541 v8::Handle
<v8::FunctionTemplate
>
542 SearchBoxExtensionWrapper::GetNativeFunctionTemplate(
543 v8::Isolate
* isolate
,
544 v8::Handle
<v8::String
> name
) {
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
);
579 v8::String::NewFromUtf8(isolate
, "LogMostVisitedImpression"))) {
580 return v8::FunctionTemplate::New(isolate
, LogMostVisitedImpression
);
583 v8::String::NewFromUtf8(isolate
, "LogMostVisitedNavigation"))) {
584 return v8::FunctionTemplate::New(isolate
, LogMostVisitedNavigation
);
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
);
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
);
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
);
603 v8::String::NewFromUtf8(isolate
, "GetDisplayInstantResults")))
604 return v8::FunctionTemplate::New(isolate
, GetDisplayInstantResults
);
605 return v8::Handle
<v8::FunctionTemplate
>();
609 content::RenderView
* SearchBoxExtensionWrapper::GetRenderView() {
610 blink::WebFrame
* webframe
= blink::WebFrame::frameForCurrentContext();
611 if (!webframe
) return NULL
;
613 blink::WebView
* webview
= webframe
->view();
614 if (!webview
) return NULL
; // can happen during closing
616 return content::RenderView::FromWebView(webview
);
620 void SearchBoxExtensionWrapper::CheckIsUserSignedInToChromeAs(
621 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
622 content::RenderView
* render_view
= GetRenderView();
623 if (!render_view
|| args
.Length() == 0 || args
[0]->IsUndefined()) return;
625 DVLOG(1) << render_view
<< " CheckIsUserSignedInToChromeAs";
627 SearchBox::Get(render_view
)->CheckIsUserSignedInToChromeAs(
628 V8ValueToUTF16(args
[0]));
632 void SearchBoxExtensionWrapper::DeleteMostVisitedItem(
633 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
634 content::RenderView
* render_view
= GetRenderView();
635 if (!render_view
|| !args
.Length()) return;
637 DVLOG(1) << render_view
<< " DeleteMostVisitedItem";
638 SearchBox::Get(render_view
)->DeleteMostVisitedItem(args
[0]->IntegerValue());
642 void SearchBoxExtensionWrapper::Focus(
643 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
644 content::RenderView
* render_view
= GetRenderView();
645 if (!render_view
) return;
647 DVLOG(1) << render_view
<< " Focus";
648 SearchBox::Get(render_view
)->Focus();
652 void SearchBoxExtensionWrapper::GetAppLauncherEnabled(
653 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
654 content::RenderView
* render_view
= GetRenderView();
655 if (!render_view
) return;
657 args
.GetReturnValue().Set(
658 SearchBox::Get(render_view
)->app_launcher_enabled());
662 void SearchBoxExtensionWrapper::GetDispositionFromClick(
663 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
664 content::RenderView
* render_view
= GetRenderView();
665 if (!render_view
|| args
.Length() != 5) return;
667 bool middle_button
= args
[0]->BooleanValue();
668 bool alt_key
= args
[1]->BooleanValue();
669 bool ctrl_key
= args
[2]->BooleanValue();
670 bool meta_key
= args
[3]->BooleanValue();
671 bool shift_key
= args
[4]->BooleanValue();
673 WindowOpenDisposition disposition
= ui::DispositionFromClick(middle_button
,
678 v8::Isolate
* isolate
= args
.GetIsolate();
679 args
.GetReturnValue().Set(v8::Int32::New(isolate
, disposition
));
683 void SearchBoxExtensionWrapper::GetMostVisitedItems(
684 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
685 content::RenderView
* render_view
= GetRenderView();
688 DVLOG(1) << render_view
<< " GetMostVisitedItems";
690 const SearchBox
* search_box
= SearchBox::Get(render_view
);
692 std::vector
<InstantMostVisitedItemIDPair
> instant_mv_items
;
693 search_box
->GetMostVisitedItems(&instant_mv_items
);
694 v8::Isolate
* isolate
= args
.GetIsolate();
695 v8::Handle
<v8::Array
> v8_mv_items
=
696 v8::Array::New(isolate
, instant_mv_items
.size());
697 for (size_t i
= 0; i
< instant_mv_items
.size(); ++i
) {
699 GenerateMostVisitedItem(isolate
,
700 render_view
->GetRoutingID(),
701 instant_mv_items
[i
].first
,
702 instant_mv_items
[i
].second
));
704 args
.GetReturnValue().Set(v8_mv_items
);
708 void SearchBoxExtensionWrapper::GetMostVisitedItemData(
709 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
710 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
711 GURL(chrome::kChromeSearchMostVisitedUrl
));
712 if (!render_view
) return;
714 // Need an rid argument.
715 if (args
.Length() < 1 || !args
[0]->IsNumber())
718 DVLOG(1) << render_view
<< " GetMostVisitedItem";
719 InstantRestrictedID restricted_id
= args
[0]->IntegerValue();
720 InstantMostVisitedItem mv_item
;
721 if (!SearchBox::Get(render_view
)->GetMostVisitedItemWithID(
722 restricted_id
, &mv_item
)) {
725 v8::Isolate
* isolate
= args
.GetIsolate();
726 args
.GetReturnValue().Set(GenerateMostVisitedItem(
727 isolate
, render_view
->GetRoutingID(), restricted_id
, mv_item
));
731 void SearchBoxExtensionWrapper::GetQuery(
732 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
733 content::RenderView
* render_view
= GetRenderView();
734 if (!render_view
) return;
735 const base::string16
& query
= SearchBox::Get(render_view
)->query();
736 DVLOG(1) << render_view
<< " GetQuery: '" << query
<< "'";
737 v8::Isolate
* isolate
= args
.GetIsolate();
738 args
.GetReturnValue().Set(UTF16ToV8String(isolate
, query
));
742 void SearchBoxExtensionWrapper::GetRightToLeft(
743 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
744 args
.GetReturnValue().Set(base::i18n::IsRTL());
748 void SearchBoxExtensionWrapper::GetStartMargin(
749 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
750 content::RenderView
* render_view
= GetRenderView();
751 if (!render_view
) return;
752 args
.GetReturnValue().Set(static_cast<int32_t>(
753 SearchBox::Get(render_view
)->start_margin()));
757 void SearchBoxExtensionWrapper::GetSuggestionToPrefetch(
758 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
759 content::RenderView
* render_view
= GetRenderView();
760 if (!render_view
) return;
762 const InstantSuggestion
& suggestion
=
763 SearchBox::Get(render_view
)->suggestion();
764 v8::Isolate
* isolate
= args
.GetIsolate();
765 v8::Handle
<v8::Object
> data
= v8::Object::New(isolate
);
766 data
->Set(v8::String::NewFromUtf8(isolate
, "text"),
767 UTF16ToV8String(isolate
, suggestion
.text
));
768 data
->Set(v8::String::NewFromUtf8(isolate
, "metadata"),
769 UTF8ToV8String(isolate
, suggestion
.metadata
));
770 args
.GetReturnValue().Set(data
);
774 void SearchBoxExtensionWrapper::GetThemeBackgroundInfo(
775 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
776 content::RenderView
* render_view
= GetRenderView();
777 if (!render_view
) return;
779 DVLOG(1) << render_view
<< " GetThemeBackgroundInfo";
780 const ThemeBackgroundInfo
& theme_info
=
781 SearchBox::Get(render_view
)->GetThemeBackgroundInfo();
782 v8::Isolate
* isolate
= args
.GetIsolate();
783 v8::Handle
<v8::Object
> info
= v8::Object::New(isolate
);
785 info
->Set(v8::String::NewFromUtf8(isolate
, "usingDefaultTheme"),
786 v8::Boolean::New(isolate
, theme_info
.using_default_theme
));
788 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and
789 // B are between 0 and 255 inclusive, and A is a double between 0 and 1
791 // This is the CSS "background-color" format.
792 // Value is always valid.
793 // TODO(jfweitz): Remove this field after GWS is modified to use the new
794 // backgroundColorRgba field.
796 v8::String::NewFromUtf8(isolate
, "colorRgba"),
799 // Convert the alpha using DoubleToString because StringPrintf will
801 // locale specific formatters (e.g., use , instead of . in German).
803 kCSSBackgroundColorFormat
,
804 theme_info
.background_color
.r
,
805 theme_info
.background_color
.g
,
806 theme_info
.background_color
.b
,
807 base::DoubleToString(theme_info
.background_color
.a
/ 255.0)
810 // Theme color for background as an array with the RGBA components in order.
811 // Value is always valid.
812 info
->Set(v8::String::NewFromUtf8(isolate
, "backgroundColorRgba"),
813 internal::RGBAColorToArray(isolate
, theme_info
.background_color
));
815 // Theme color for text as an array with the RGBA components in order.
816 // Value is always valid.
817 info
->Set(v8::String::NewFromUtf8(isolate
, "textColorRgba"),
818 internal::RGBAColorToArray(isolate
, theme_info
.text_color
));
820 // Theme color for links as an array with the RGBA components in order.
821 // Value is always valid.
822 info
->Set(v8::String::NewFromUtf8(isolate
, "linkColorRgba"),
823 internal::RGBAColorToArray(isolate
, theme_info
.link_color
));
825 // Theme color for light text as an array with the RGBA components in order.
826 // Value is always valid.
827 info
->Set(v8::String::NewFromUtf8(isolate
, "textColorLightRgba"),
828 internal::RGBAColorToArray(isolate
, theme_info
.text_color_light
));
830 // Theme color for header as an array with the RGBA components in order.
831 // Value is always valid.
832 info
->Set(v8::String::NewFromUtf8(isolate
, "headerColorRgba"),
833 internal::RGBAColorToArray(isolate
, theme_info
.header_color
));
835 // Theme color for section border as an array with the RGBA components in
836 // order. Value is always valid.
838 v8::String::NewFromUtf8(isolate
, "sectionBorderColorRgba"),
839 internal::RGBAColorToArray(isolate
, theme_info
.section_border_color
));
841 // The theme alternate logo value indicates a white logo when TRUE and a
842 // colorful one when FALSE.
843 info
->Set(v8::String::NewFromUtf8(isolate
, "alternateLogo"),
844 v8::Boolean::New(isolate
, theme_info
.logo_alternate
));
846 // The theme background image url is of format kCSSBackgroundImageFormat
847 // where both instances of "%s" are replaced with the id that identifies the
849 // This is the CSS "background-image" format.
850 // Value is only valid if there's a custom theme background image.
851 if (extensions::Extension::IdIsValid(theme_info
.theme_id
)) {
852 info
->Set(v8::String::NewFromUtf8(isolate
, "imageUrl"),
853 UTF8ToV8String(isolate
,
854 base::StringPrintf(kCSSBackgroundImageFormat
,
855 theme_info
.theme_id
.c_str(),
856 theme_info
.theme_id
.c_str())));
858 // The theme background image horizontal alignment is one of "left",
859 // "right", "center".
860 // This is the horizontal component of the CSS "background-position" format.
861 // Value is only valid if |imageUrl| is not empty.
862 std::string alignment
= kCSSBackgroundPositionCenter
;
863 if (theme_info
.image_horizontal_alignment
==
864 THEME_BKGRND_IMAGE_ALIGN_LEFT
) {
865 alignment
= kCSSBackgroundPositionLeft
;
866 } else if (theme_info
.image_horizontal_alignment
==
867 THEME_BKGRND_IMAGE_ALIGN_RIGHT
) {
868 alignment
= kCSSBackgroundPositionRight
;
870 info
->Set(v8::String::NewFromUtf8(isolate
, "imageHorizontalAlignment"),
871 UTF8ToV8String(isolate
, alignment
));
873 // The theme background image vertical alignment is one of "top", "bottom",
875 // This is the vertical component of the CSS "background-position" format.
876 // Value is only valid if |image_url| is not empty.
877 if (theme_info
.image_vertical_alignment
== THEME_BKGRND_IMAGE_ALIGN_TOP
) {
878 alignment
= kCSSBackgroundPositionTop
;
879 } else if (theme_info
.image_vertical_alignment
==
880 THEME_BKGRND_IMAGE_ALIGN_BOTTOM
) {
881 alignment
= kCSSBackgroundPositionBottom
;
883 alignment
= kCSSBackgroundPositionCenter
;
885 info
->Set(v8::String::NewFromUtf8(isolate
, "imageVerticalAlignment"),
886 UTF8ToV8String(isolate
, alignment
));
888 // The tiling of the theme background image is one of "no-repeat",
889 // "repeat-x", "repeat-y", "repeat".
890 // This is the CSS "background-repeat" format.
891 // Value is only valid if |image_url| is not empty.
892 std::string tiling
= kCSSBackgroundRepeatNo
;
893 switch (theme_info
.image_tiling
) {
894 case THEME_BKGRND_IMAGE_NO_REPEAT
:
895 tiling
= kCSSBackgroundRepeatNo
;
897 case THEME_BKGRND_IMAGE_REPEAT_X
:
898 tiling
= kCSSBackgroundRepeatX
;
900 case THEME_BKGRND_IMAGE_REPEAT_Y
:
901 tiling
= kCSSBackgroundRepeatY
;
903 case THEME_BKGRND_IMAGE_REPEAT
:
904 tiling
= kCSSBackgroundRepeat
;
907 info
->Set(v8::String::NewFromUtf8(isolate
, "imageTiling"),
908 UTF8ToV8String(isolate
, tiling
));
910 // The theme background image height is only valid if |imageUrl| is valid.
911 info
->Set(v8::String::NewFromUtf8(isolate
, "imageHeight"),
912 v8::Int32::New(isolate
, theme_info
.image_height
));
914 // The attribution URL is only valid if the theme has attribution logo.
915 if (theme_info
.has_attribution
) {
917 v8::String::NewFromUtf8(isolate
, "attributionUrl"),
918 UTF8ToV8String(isolate
,
919 base::StringPrintf(kThemeAttributionFormat
,
920 theme_info
.theme_id
.c_str(),
921 theme_info
.theme_id
.c_str())));
925 args
.GetReturnValue().Set(info
);
929 void SearchBoxExtensionWrapper::IsFocused(
930 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
931 content::RenderView
* render_view
= GetRenderView();
932 if (!render_view
) return;
934 bool is_focused
= SearchBox::Get(render_view
)->is_focused();
935 DVLOG(1) << render_view
<< " IsFocused: " << is_focused
;
936 args
.GetReturnValue().Set(is_focused
);
940 void SearchBoxExtensionWrapper::IsInputInProgress(
941 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
942 content::RenderView
* render_view
= GetRenderView();
943 if (!render_view
) return;
945 bool is_input_in_progress
=
946 SearchBox::Get(render_view
)->is_input_in_progress();
947 DVLOG(1) << render_view
<< " IsInputInProgress: " << is_input_in_progress
;
948 args
.GetReturnValue().Set(is_input_in_progress
);
952 void SearchBoxExtensionWrapper::IsKeyCaptureEnabled(
953 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
954 content::RenderView
* render_view
= GetRenderView();
955 if (!render_view
) return;
957 args
.GetReturnValue().Set(SearchBox::Get(render_view
)->
958 is_key_capture_enabled());
962 void SearchBoxExtensionWrapper::LogEvent(
963 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
964 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
965 GURL(chrome::kChromeSearchMostVisitedUrl
));
966 if (!render_view
) return;
968 if (args
.Length() < 1 || !args
[0]->IsNumber())
971 DVLOG(1) << render_view
<< " LogEvent";
973 if (args
[0]->Uint32Value() < NTP_NUM_EVENT_TYPES
) {
974 NTPLoggingEventType event
=
975 static_cast<NTPLoggingEventType
>(args
[0]->Uint32Value());
976 SearchBox::Get(render_view
)->LogEvent(event
);
981 void SearchBoxExtensionWrapper::LogMostVisitedImpression(
982 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
983 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
984 GURL(chrome::kChromeSearchMostVisitedUrl
));
985 if (!render_view
) return;
987 if (args
.Length() < 2 || !args
[0]->IsNumber() || args
[1]->IsUndefined())
990 DVLOG(1) << render_view
<< " LogMostVisitedImpression";
992 SearchBox::Get(render_view
)->LogMostVisitedImpression(
993 args
[0]->IntegerValue(), V8ValueToUTF16(args
[1]));
997 void SearchBoxExtensionWrapper::LogMostVisitedNavigation(
998 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
999 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
1000 GURL(chrome::kChromeSearchMostVisitedUrl
));
1001 if (!render_view
) return;
1003 if (args
.Length() < 2 || !args
[0]->IsNumber() || args
[1]->IsUndefined())
1006 DVLOG(1) << render_view
<< " LogMostVisitedNavigation";
1008 SearchBox::Get(render_view
)->LogMostVisitedNavigation(
1009 args
[0]->IntegerValue(), V8ValueToUTF16(args
[1]));
1013 void SearchBoxExtensionWrapper::NavigateContentWindow(
1014 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1015 content::RenderView
* render_view
= GetRenderView();
1016 if (!render_view
|| !args
.Length()) return;
1018 GURL destination_url
;
1019 bool is_most_visited_item_url
= false;
1020 // Check if the url is a rid
1021 if (args
[0]->IsNumber()) {
1022 InstantMostVisitedItem item
;
1023 if (SearchBox::Get(render_view
)->GetMostVisitedItemWithID(
1024 args
[0]->IntegerValue(), &item
)) {
1025 destination_url
= item
.url
;
1026 is_most_visited_item_url
= true;
1030 const base::string16
& possibly_relative_url
= V8ValueToUTF16(args
[0]);
1031 GURL current_url
= GetCurrentURL(render_view
);
1032 destination_url
= internal::ResolveURL(current_url
, possibly_relative_url
);
1035 DVLOG(1) << render_view
<< " NavigateContentWindow: " << destination_url
;
1037 // Navigate the main frame.
1038 if (destination_url
.is_valid() &&
1039 !destination_url
.SchemeIs(content::kJavaScriptScheme
)) {
1040 WindowOpenDisposition disposition
= CURRENT_TAB
;
1041 if (args
[1]->IsNumber()) {
1042 disposition
= (WindowOpenDisposition
) args
[1]->Uint32Value();
1044 SearchBox::Get(render_view
)->NavigateToURL(destination_url
, disposition
,
1045 is_most_visited_item_url
);
1050 void SearchBoxExtensionWrapper::Paste(
1051 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1052 content::RenderView
* render_view
= GetRenderView();
1053 if (!render_view
) return;
1055 base::string16 text
;
1056 if (!args
[0]->IsUndefined())
1057 text
= V8ValueToUTF16(args
[0]);
1059 DVLOG(1) << render_view
<< " Paste: " << text
;
1060 SearchBox::Get(render_view
)->Paste(text
);
1064 void SearchBoxExtensionWrapper::StartCapturingKeyStrokes(
1065 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1066 content::RenderView
* render_view
= GetRenderView();
1067 if (!render_view
) return;
1069 DVLOG(1) << render_view
<< " StartCapturingKeyStrokes";
1070 SearchBox::Get(render_view
)->StartCapturingKeyStrokes();
1074 void SearchBoxExtensionWrapper::StopCapturingKeyStrokes(
1075 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1076 content::RenderView
* render_view
= GetRenderView();
1077 if (!render_view
) return;
1079 DVLOG(1) << render_view
<< " StopCapturingKeyStrokes";
1080 SearchBox::Get(render_view
)->StopCapturingKeyStrokes();
1084 void SearchBoxExtensionWrapper::SetVoiceSearchSupported(
1085 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1086 content::RenderView
* render_view
= GetRenderView();
1087 if (!render_view
|| args
.Length() < 1) return;
1089 DVLOG(1) << render_view
<< " SetVoiceSearchSupported";
1090 SearchBox::Get(render_view
)->SetVoiceSearchSupported(args
[0]->BooleanValue());
1094 void SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions(
1095 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1096 content::RenderView
* render_view
= GetRenderView();
1097 if (!render_view
) return;
1099 DVLOG(1) << render_view
<< " UndoAllMostVisitedDeletions";
1100 SearchBox::Get(render_view
)->UndoAllMostVisitedDeletions();
1104 void SearchBoxExtensionWrapper::UndoMostVisitedDeletion(
1105 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1106 content::RenderView
* render_view
= GetRenderView();
1107 if (!render_view
|| !args
.Length()) return;
1109 DVLOG(1) << render_view
<< " UndoMostVisitedDeletion";
1110 SearchBox::Get(render_view
)->UndoMostVisitedDeletion(args
[0]->IntegerValue());
1114 void SearchBoxExtensionWrapper::GetDisplayInstantResults(
1115 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1116 content::RenderView
* render_view
= GetRenderView();
1117 if (!render_view
) return;
1119 bool display_instant_results
=
1120 SearchBox::Get(render_view
)->display_instant_results();
1121 DVLOG(1) << render_view
<< " GetDisplayInstantResults" <<
1122 display_instant_results
;
1123 args
.GetReturnValue().Set(display_instant_results
);
1126 } // namespace extensions_v8