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/command_line.h"
8 #include "base/i18n/rtl.h"
9 #include "base/json/string_escape.h"
10 #include "base/metrics/field_trial.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/stringprintf.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "chrome/common/instant_types.h"
16 #include "chrome/common/ntp_logging_events.h"
17 #include "chrome/common/url_constants.h"
18 #include "chrome/grit/renderer_resources.h"
19 #include "chrome/renderer/searchbox/searchbox.h"
20 #include "components/crx_file/id_util.h"
21 #include "content/public/renderer/render_view.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/WebLocalFrame.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/ui_base_switches.h"
29 #include "ui/base/window_open_disposition.h"
30 #include "ui/events/keycodes/keyboard_codes.h"
32 #include "url/url_constants.h"
33 #include "v8/include/v8.h"
37 const char kCSSBackgroundImageFormat
[] = "-webkit-image-set("
38 "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND?%s) 1x, "
39 "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND@2x?%s) 2x)";
41 const char kCSSBackgroundColorFormat
[] = "rgba(%d,%d,%d,%s)";
43 const char kCSSBackgroundPositionCenter
[] = "center";
44 const char kCSSBackgroundPositionLeft
[] = "left";
45 const char kCSSBackgroundPositionTop
[] = "top";
46 const char kCSSBackgroundPositionRight
[] = "right";
47 const char kCSSBackgroundPositionBottom
[] = "bottom";
49 const char kCSSBackgroundRepeatNo
[] = "no-repeat";
50 const char kCSSBackgroundRepeatX
[] = "repeat-x";
51 const char kCSSBackgroundRepeatY
[] = "repeat-y";
52 const char kCSSBackgroundRepeat
[] = "repeat";
54 const char kThemeAttributionFormat
[] = "-webkit-image-set("
55 "url(chrome-search://theme/IDR_THEME_NTP_ATTRIBUTION?%s) 1x, "
56 "url(chrome-search://theme/IDR_THEME_NTP_ATTRIBUTION@2x?%s) 2x)";
58 const char kLTRHtmlTextDirection
[] = "ltr";
59 const char kRTLHtmlTextDirection
[] = "rtl";
61 // Converts a V8 value to a string16.
62 base::string16
V8ValueToUTF16(v8::Local
<v8::Value
> v
) {
63 v8::String::Value
s(v
);
64 return base::string16(reinterpret_cast<const base::char16
*>(*s
), s
.length());
67 // Returns whether icon NTP is enabled by experiment.
68 // TODO(huangs): Remove all 3 copies of this routine once Icon NTP launches.
69 bool IsIconNTPEnabled() {
70 // Note: It's important to query the field trial state first, to ensure that
71 // UMA reports the correct group.
72 const std::string group_name
= base::FieldTrialList::FindFullName("IconNTP");
73 using base::CommandLine
;
74 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableIconNtp
))
76 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp
))
79 return base::StartsWith(group_name
, "Enabled", base::CompareCase::SENSITIVE
);
82 // Converts string16 to V8 String.
83 v8::Local
<v8::String
> UTF16ToV8String(v8::Isolate
* isolate
,
84 const base::string16
& s
) {
85 return v8::String::NewFromTwoByte(isolate
,
86 reinterpret_cast<const uint16_t*>(s
.data()),
87 v8::String::kNormalString
,
91 // Converts std::string to V8 String.
92 v8::Local
<v8::String
> UTF8ToV8String(v8::Isolate
* isolate
,
93 const std::string
& s
) {
94 return v8::String::NewFromUtf8(
95 isolate
, s
.data(), v8::String::kNormalString
, s
.size());
98 // Throws a TypeError on the current V8 context if the args are invalid.
99 void ThrowInvalidParameters(const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
100 v8::Isolate
* isolate
= args
.GetIsolate();
101 isolate
->ThrowException(v8::Exception::TypeError(
102 v8::String::NewFromUtf8(isolate
, "Invalid parameters")));
105 void Dispatch(blink::WebFrame
* frame
, const blink::WebString
& script
) {
107 frame
->executeScript(blink::WebScriptSource(script
));
110 v8::Local
<v8::String
> GenerateThumbnailURL(
111 v8::Isolate
* isolate
,
113 InstantRestrictedID most_visited_item_id
) {
114 return UTF8ToV8String(
117 "chrome-search://thumb/%d/%d", render_view_id
, most_visited_item_id
));
120 v8::Local
<v8::String
> GenerateThumb2URL(v8::Isolate
* isolate
, std::string url
) {
121 return UTF8ToV8String(
122 isolate
, base::StringPrintf("chrome-search://thumb2/%s", url
.c_str()));
125 // Populates a Javascript MostVisitedItem object from |mv_item|.
126 // NOTE: Includes "url", "title" and "domain" which are private data, so should
127 // not be returned to the Instant page. These should be erased before returning
128 // the object. See GetMostVisitedItemsWrapper() in searchbox_api.js.
129 v8::Local
<v8::Object
> GenerateMostVisitedItem(
130 v8::Isolate
* isolate
,
132 InstantRestrictedID restricted_id
,
133 const InstantMostVisitedItem
& mv_item
) {
134 // We set the "dir" attribute of the title, so that in RTL locales, a LTR
135 // title is rendered left-to-right and truncated from the right. For
136 // example, the title of http://msdn.microsoft.com/en-us/default.aspx is
137 // "MSDN: Microsoft developer network". In RTL locales, in the New Tab
138 // page, if the "dir" of this title is not specified, it takes Chrome UI's
139 // directionality. So the title will be truncated as "soft developer
140 // network". Setting the "dir" attribute as "ltr" renders the truncated
141 // title as "MSDN: Microsoft D...". As another example, the title of
142 // http://yahoo.com is "Yahoo!". In RTL locales, in the New Tab page, the
143 // title will be rendered as "!Yahoo" if its "dir" attribute is not set to
145 std::string direction
;
146 if (base::i18n::StringContainsStrongRTLChars(mv_item
.title
))
147 direction
= kRTLHtmlTextDirection
;
149 direction
= kLTRHtmlTextDirection
;
151 base::string16 title
= mv_item
.title
;
153 title
= base::UTF8ToUTF16(mv_item
.url
.spec());
155 v8::Local
<v8::Object
> obj
= v8::Object::New(isolate
);
156 obj
->Set(v8::String::NewFromUtf8(isolate
, "renderViewId"),
157 v8::Int32::New(isolate
, render_view_id
));
158 obj
->Set(v8::String::NewFromUtf8(isolate
, "rid"),
159 v8::Int32::New(isolate
, restricted_id
));
161 // If the suggestion already has a suggested thumbnail, we create an thumbnail
162 // array with both the local thumbnail and the proposed one.
163 // Otherwise, we just create an array with the generated one.
164 if (!mv_item
.thumbnail
.spec().empty()) {
165 v8::Local
<v8::Array
> thumbs
= v8::Array::New(isolate
, 2);
166 thumbs
->Set(0, GenerateThumb2URL(isolate
, mv_item
.url
.spec()));
167 thumbs
->Set(1, UTF8ToV8String(isolate
, mv_item
.thumbnail
.spec()));
168 obj
->Set(v8::String::NewFromUtf8(isolate
, "thumbnailUrls"), thumbs
);
170 v8::Local
<v8::Array
> thumbs
= v8::Array::New(isolate
, 1);
172 GenerateThumbnailURL(isolate
, render_view_id
, restricted_id
));
173 obj
->Set(v8::String::NewFromUtf8(isolate
, "thumbnailUrls"), thumbs
);
176 // If the suggestion already has a favicon, we populate the element with it.
177 if (!mv_item
.favicon
.spec().empty()) {
178 obj
->Set(v8::String::NewFromUtf8(isolate
, "faviconUrl"),
179 UTF8ToV8String(isolate
, mv_item
.favicon
.spec()));
182 if (IsIconNTPEnabled()) {
183 // Update website http://www.chromium.org/embeddedsearch when we make this
185 // Large icon size is 48px * window.devicePixelRatio. This is easier to set
186 // from JS, where IsIconNTPEnabled() is not available. So we add stubs
187 // here, and let JS fill in details.
188 obj
->Set(v8::String::NewFromUtf8(isolate
, "largeIconUrl"),
189 v8::String::NewFromUtf8(isolate
, "chrome-search://large-icon/"));
190 obj
->Set(v8::String::NewFromUtf8(isolate
, "fallbackIconUrl"),
191 v8::String::NewFromUtf8(isolate
, "chrome-search://fallback-icon/"));
193 obj
->Set(v8::String::NewFromUtf8(isolate
, "title"),
194 UTF16ToV8String(isolate
, title
));
195 obj
->Set(v8::String::NewFromUtf8(isolate
, "domain"),
196 UTF8ToV8String(isolate
, mv_item
.url
.host()));
197 obj
->Set(v8::String::NewFromUtf8(isolate
, "direction"),
198 UTF8ToV8String(isolate
, direction
));
199 obj
->Set(v8::String::NewFromUtf8(isolate
, "url"),
200 UTF8ToV8String(isolate
, mv_item
.url
.spec()));
204 // Returns the render view for the current JS context if it matches |origin|,
205 // otherwise returns NULL. Used to restrict methods that access suggestions and
206 // most visited data to pages with origin chrome-search://most-visited and
207 // chrome-search://suggestions.
208 content::RenderView
* GetRenderViewWithCheckedOrigin(const GURL
& origin
) {
209 blink::WebLocalFrame
* webframe
=
210 blink::WebLocalFrame::frameForCurrentContext();
213 blink::WebView
* webview
= webframe
->view();
215 return NULL
; // Can happen during closing.
216 content::RenderView
* render_view
= content::RenderView::FromWebView(webview
);
220 GURL
url(webframe
->document().url());
221 if (url
.GetOrigin() != origin
.GetOrigin())
227 // Returns the current URL.
228 GURL
GetCurrentURL(content::RenderView
* render_view
) {
229 blink::WebView
* webview
= render_view
->GetWebView();
230 return webview
? GURL(webview
->mainFrame()->document().url()) : GURL();
235 namespace internal
{ // for testing.
237 // Returns an array with the RGBA color components.
238 v8::Local
<v8::Value
> RGBAColorToArray(v8::Isolate
* isolate
,
239 const RGBAColor
& color
) {
240 v8::Local
<v8::Array
> color_array
= v8::Array::New(isolate
, 4);
241 color_array
->Set(0, v8::Int32::New(isolate
, color
.r
));
242 color_array
->Set(1, v8::Int32::New(isolate
, color
.g
));
243 color_array
->Set(2, v8::Int32::New(isolate
, color
.b
));
244 color_array
->Set(3, v8::Int32::New(isolate
, color
.a
));
248 // Resolves a possibly relative URL using the current URL.
249 GURL
ResolveURL(const GURL
& current_url
,
250 const base::string16
& possibly_relative_url
) {
251 if (current_url
.is_valid() && !possibly_relative_url
.empty())
252 return current_url
.Resolve(possibly_relative_url
);
253 return GURL(possibly_relative_url
);
256 } // namespace internal
258 namespace extensions_v8
{
260 static const char kSearchBoxExtensionName
[] = "v8/EmbeddedSearch";
262 // We first send this script down to determine if the page supports instant.
263 static const char kSupportsInstantScript
[] =
264 "if (window.chrome &&"
265 " window.chrome.embeddedSearch &&"
266 " window.chrome.embeddedSearch.searchBox &&"
267 " window.chrome.embeddedSearch.searchBox.onsubmit &&"
268 " typeof window.chrome.embeddedSearch.searchBox.onsubmit =="
275 static const char kDispatchChromeIdentityCheckResult
[] =
276 "if (window.chrome &&"
277 " window.chrome.embeddedSearch &&"
278 " window.chrome.embeddedSearch.newTabPage &&"
279 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone &&"
280 " typeof window.chrome.embeddedSearch.newTabPage"
281 " .onsignedincheckdone === 'function') {"
282 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone(%s, %s);"
286 static const char kDispatchFocusChangedScript
[] =
287 "if (window.chrome &&"
288 " window.chrome.embeddedSearch &&"
289 " window.chrome.embeddedSearch.searchBox &&"
290 " window.chrome.embeddedSearch.searchBox.onfocuschange &&"
291 " typeof window.chrome.embeddedSearch.searchBox.onfocuschange =="
293 " window.chrome.embeddedSearch.searchBox.onfocuschange();"
297 static const char kDispatchHistorySyncCheckResult
[] =
298 "if (window.chrome &&"
299 " window.chrome.embeddedSearch &&"
300 " window.chrome.embeddedSearch.newTabPage &&"
301 " window.chrome.embeddedSearch.newTabPage.onhistorysynccheckdone &&"
302 " typeof window.chrome.embeddedSearch.newTabPage"
303 " .onhistorysynccheckdone === 'function') {"
304 " window.chrome.embeddedSearch.newTabPage.onhistorysynccheckdone(%s);"
308 static const char kDispatchInputCancelScript
[] =
309 "if (window.chrome &&"
310 " window.chrome.embeddedSearch &&"
311 " window.chrome.embeddedSearch.newTabPage &&"
312 " window.chrome.embeddedSearch.newTabPage.oninputcancel &&"
313 " typeof window.chrome.embeddedSearch.newTabPage.oninputcancel =="
315 " window.chrome.embeddedSearch.newTabPage.oninputcancel();"
319 static const char kDispatchInputStartScript
[] =
320 "if (window.chrome &&"
321 " window.chrome.embeddedSearch &&"
322 " window.chrome.embeddedSearch.newTabPage &&"
323 " window.chrome.embeddedSearch.newTabPage.oninputstart &&"
324 " typeof window.chrome.embeddedSearch.newTabPage.oninputstart =="
326 " window.chrome.embeddedSearch.newTabPage.oninputstart();"
330 static const char kDispatchKeyCaptureChangeScript
[] =
331 "if (window.chrome &&"
332 " window.chrome.embeddedSearch &&"
333 " window.chrome.embeddedSearch.searchBox &&"
334 " window.chrome.embeddedSearch.searchBox.onkeycapturechange &&"
335 " typeof window.chrome.embeddedSearch.searchBox.onkeycapturechange =="
337 " window.chrome.embeddedSearch.searchBox.onkeycapturechange();"
341 static const char kDispatchMarginChangeEventScript
[] =
342 "if (window.chrome &&"
343 " window.chrome.embeddedSearch &&"
344 " window.chrome.embeddedSearch.searchBox &&"
345 " window.chrome.embeddedSearch.searchBox.onmarginchange &&"
346 " typeof window.chrome.embeddedSearch.searchBox.onmarginchange =="
348 " window.chrome.embeddedSearch.searchBox.onmarginchange();"
352 static const char kDispatchMostVisitedChangedScript
[] =
353 "if (window.chrome &&"
354 " window.chrome.embeddedSearch &&"
355 " window.chrome.embeddedSearch.newTabPage &&"
356 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange &&"
357 " typeof window.chrome.embeddedSearch.newTabPage.onmostvisitedchange =="
359 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange();"
363 static const char kDispatchSubmitEventScript
[] =
364 "if (window.chrome &&"
365 " window.chrome.embeddedSearch &&"
366 " window.chrome.embeddedSearch.searchBox &&"
367 " window.chrome.embeddedSearch.searchBox.onsubmit &&"
368 " typeof window.chrome.embeddedSearch.searchBox.onsubmit =="
370 " window.chrome.embeddedSearch.searchBox.onsubmit();"
374 static const char kDispatchSuggestionChangeEventScript
[] =
375 "if (window.chrome &&"
376 " window.chrome.embeddedSearch &&"
377 " window.chrome.embeddedSearch.searchBox &&"
378 " window.chrome.embeddedSearch.searchBox.onsuggestionchange &&"
379 " typeof window.chrome.embeddedSearch.searchBox.onsuggestionchange =="
381 " window.chrome.embeddedSearch.searchBox.onsuggestionchange();"
385 static const char kDispatchThemeChangeEventScript
[] =
386 "if (window.chrome &&"
387 " window.chrome.embeddedSearch &&"
388 " window.chrome.embeddedSearch.newTabPage &&"
389 " window.chrome.embeddedSearch.newTabPage.onthemechange &&"
390 " typeof window.chrome.embeddedSearch.newTabPage.onthemechange =="
392 " window.chrome.embeddedSearch.newTabPage.onthemechange();"
396 static const char kDispatchToggleVoiceSearchScript
[] =
397 "if (window.chrome &&"
398 " window.chrome.embeddedSearch &&"
399 " window.chrome.embeddedSearch.searchBox &&"
400 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch &&"
401 " typeof window.chrome.embeddedSearch.searchBox.ontogglevoicesearch =="
403 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch();"
407 // ----------------------------------------------------------------------------
409 class SearchBoxExtensionWrapper
: public v8::Extension
{
411 explicit SearchBoxExtensionWrapper(const base::StringPiece
& code
);
413 // Allows v8's javascript code to call the native functions defined
414 // in this class for window.chrome.
415 v8::Local
<v8::FunctionTemplate
> GetNativeFunctionTemplate(
417 v8::Local
<v8::String
> name
) override
;
419 // Helper function to find the RenderView. May return NULL.
420 static content::RenderView
* GetRenderView();
422 // Sends a Chrome identity check to the browser.
423 static void CheckIsUserSignedInToChromeAs(
424 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
426 // Checks whether the user sync his history.
427 static void CheckIsUserSyncingHistory(
428 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
430 // Deletes a Most Visited item.
431 static void DeleteMostVisitedItem(
432 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
434 // Focuses the omnibox.
435 static void Focus(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
437 // Gets whether or not the app launcher is enabled.
438 static void GetAppLauncherEnabled(
439 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
441 // Gets the desired navigation behavior from a click event.
442 static void GetDispositionFromClick(
443 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
445 // Gets Most Visited Items.
446 static void GetMostVisitedItems(
447 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
449 // Gets the raw data for a most visited item including its raw URL.
450 // GetRenderViewWithCheckedOrigin() enforces that only code in the origin
451 // chrome-search://most-visited can call this function.
452 static void GetMostVisitedItemData(
453 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
455 // Gets the submitted value of the user's search query.
456 static void GetQuery(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
458 // Returns true if the Searchbox itself is oriented right-to-left.
459 static void GetRightToLeft(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
461 // Gets the Embedded Search request params. Used for logging purposes.
462 static void GetSearchRequestParams(
463 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
465 // Gets the start-edge margin to use with extended Instant.
466 static void GetStartMargin(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
468 // Gets the current top suggestion to prefetch search results.
469 static void GetSuggestionToPrefetch(
470 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
472 // Gets the background info of the theme currently adopted by browser.
473 // Call only when overlay is showing NTP page.
474 static void GetThemeBackgroundInfo(
475 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
477 // Gets whether the omnibox has focus or not.
478 static void IsFocused(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
480 // Gets whether user input is in progress.
481 static void IsInputInProgress(
482 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
484 // Gets whether the browser is capturing key strokes.
485 static void IsKeyCaptureEnabled(
486 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
488 // Logs information from the iframes/titles on the NTP.
489 static void LogEvent(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
491 // Logs an impression on one of the Most Visited tile on the NTP.
492 static void LogMostVisitedImpression(
493 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
495 // Logs a navigation on one of the Most Visited tile on the NTP.
496 static void LogMostVisitedNavigation(
497 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
499 // Navigates the window to a URL represented by either a URL string or a
501 static void NavigateContentWindow(
502 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
504 // Pastes provided value or clipboard's content into the omnibox.
505 static void Paste(const v8::FunctionCallbackInfo
<v8::Value
>& args
);
507 // Indicates whether the page supports voice search.
508 static void SetVoiceSearchSupported(
509 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
511 // Start capturing user key strokes.
512 static void StartCapturingKeyStrokes(
513 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
515 // Stop capturing user key strokes.
516 static void StopCapturingKeyStrokes(
517 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
519 // Undoes the deletion of all Most Visited itens.
520 static void UndoAllMostVisitedDeletions(
521 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
523 // Undoes the deletion of a Most Visited item.
524 static void UndoMostVisitedDeletion(
525 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
527 // Indicates whether the page supports Instant.
528 static void GetDisplayInstantResults(
529 const v8::FunctionCallbackInfo
<v8::Value
>& args
);
532 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper
);
536 v8::Extension
* SearchBoxExtension::Get() {
537 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance().
538 GetRawDataResource(IDR_SEARCHBOX_API
));
542 bool SearchBoxExtension::PageSupportsInstant(blink::WebFrame
* frame
) {
543 if (!frame
) return false;
544 v8::HandleScope
handle_scope(v8::Isolate::GetCurrent());
545 v8::Local
<v8::Value
> v
= frame
->executeScriptAndReturnValue(
546 blink::WebScriptSource(kSupportsInstantScript
));
547 return !v
.IsEmpty() && v
->BooleanValue();
551 void SearchBoxExtension::DispatchChromeIdentityCheckResult(
552 blink::WebFrame
* frame
,
553 const base::string16
& identity
,
554 bool identity_match
) {
555 std::string escaped_identity
= base::GetQuotedJSONString(identity
);
556 blink::WebString
script(base::UTF8ToUTF16(base::StringPrintf(
557 kDispatchChromeIdentityCheckResult
,
558 escaped_identity
.c_str(),
559 identity_match
? "true" : "false")));
560 Dispatch(frame
, script
);
564 void SearchBoxExtension::DispatchFocusChange(blink::WebFrame
* frame
) {
565 Dispatch(frame
, kDispatchFocusChangedScript
);
569 void SearchBoxExtension::DispatchHistorySyncCheckResult(
570 blink::WebFrame
* frame
,
572 blink::WebString
script(base::UTF8ToUTF16(base::StringPrintf(
573 kDispatchHistorySyncCheckResult
,
574 sync_history
? "true" : "false")));
575 Dispatch(frame
, script
);
579 void SearchBoxExtension::DispatchInputCancel(blink::WebFrame
* frame
) {
580 Dispatch(frame
, kDispatchInputCancelScript
);
584 void SearchBoxExtension::DispatchInputStart(blink::WebFrame
* frame
) {
585 Dispatch(frame
, kDispatchInputStartScript
);
589 void SearchBoxExtension::DispatchKeyCaptureChange(blink::WebFrame
* frame
) {
590 Dispatch(frame
, kDispatchKeyCaptureChangeScript
);
594 void SearchBoxExtension::DispatchMarginChange(blink::WebFrame
* frame
) {
595 Dispatch(frame
, kDispatchMarginChangeEventScript
);
599 void SearchBoxExtension::DispatchMostVisitedChanged(
600 blink::WebFrame
* frame
) {
601 Dispatch(frame
, kDispatchMostVisitedChangedScript
);
605 void SearchBoxExtension::DispatchSubmit(blink::WebFrame
* frame
) {
606 Dispatch(frame
, kDispatchSubmitEventScript
);
610 void SearchBoxExtension::DispatchSuggestionChange(blink::WebFrame
* frame
) {
611 Dispatch(frame
, kDispatchSuggestionChangeEventScript
);
615 void SearchBoxExtension::DispatchThemeChange(blink::WebFrame
* frame
) {
616 Dispatch(frame
, kDispatchThemeChangeEventScript
);
620 void SearchBoxExtension::DispatchToggleVoiceSearch(
621 blink::WebFrame
* frame
) {
622 Dispatch(frame
, kDispatchToggleVoiceSearchScript
);
625 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper(
626 const base::StringPiece
& code
)
627 : v8::Extension(kSearchBoxExtensionName
, code
.data(), 0, 0, code
.size()) {
630 v8::Local
<v8::FunctionTemplate
>
631 SearchBoxExtensionWrapper::GetNativeFunctionTemplate(
632 v8::Isolate
* isolate
,
633 v8::Local
<v8::String
> name
) {
635 v8::String::NewFromUtf8(isolate
, "CheckIsUserSignedInToChromeAs")))
636 return v8::FunctionTemplate::New(isolate
, CheckIsUserSignedInToChromeAs
);
638 v8::String::NewFromUtf8(isolate
, "CheckIsUserSyncingHistory")))
639 return v8::FunctionTemplate::New(isolate
, CheckIsUserSyncingHistory
);
640 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "DeleteMostVisitedItem")))
641 return v8::FunctionTemplate::New(isolate
, DeleteMostVisitedItem
);
642 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "Focus")))
643 return v8::FunctionTemplate::New(isolate
, Focus
);
644 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetAppLauncherEnabled")))
645 return v8::FunctionTemplate::New(isolate
, GetAppLauncherEnabled
);
646 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetDispositionFromClick")))
647 return v8::FunctionTemplate::New(isolate
, GetDispositionFromClick
);
648 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetMostVisitedItems")))
649 return v8::FunctionTemplate::New(isolate
, GetMostVisitedItems
);
650 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetMostVisitedItemData")))
651 return v8::FunctionTemplate::New(isolate
, GetMostVisitedItemData
);
652 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetQuery")))
653 return v8::FunctionTemplate::New(isolate
, GetQuery
);
654 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetRightToLeft")))
655 return v8::FunctionTemplate::New(isolate
, GetRightToLeft
);
656 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetSearchRequestParams")))
657 return v8::FunctionTemplate::New(isolate
, GetSearchRequestParams
);
658 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetStartMargin")))
659 return v8::FunctionTemplate::New(isolate
, GetStartMargin
);
660 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetSuggestionToPrefetch")))
661 return v8::FunctionTemplate::New(isolate
, GetSuggestionToPrefetch
);
662 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "GetThemeBackgroundInfo")))
663 return v8::FunctionTemplate::New(isolate
, GetThemeBackgroundInfo
);
664 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "IsFocused")))
665 return v8::FunctionTemplate::New(isolate
, IsFocused
);
666 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "IsInputInProgress")))
667 return v8::FunctionTemplate::New(isolate
, IsInputInProgress
);
668 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "IsKeyCaptureEnabled")))
669 return v8::FunctionTemplate::New(isolate
, IsKeyCaptureEnabled
);
670 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "LogEvent")))
671 return v8::FunctionTemplate::New(isolate
, LogEvent
);
673 v8::String::NewFromUtf8(isolate
, "LogMostVisitedImpression"))) {
674 return v8::FunctionTemplate::New(isolate
, LogMostVisitedImpression
);
677 v8::String::NewFromUtf8(isolate
, "LogMostVisitedNavigation"))) {
678 return v8::FunctionTemplate::New(isolate
, LogMostVisitedNavigation
);
680 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "NavigateContentWindow")))
681 return v8::FunctionTemplate::New(isolate
, NavigateContentWindow
);
682 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "Paste")))
683 return v8::FunctionTemplate::New(isolate
, Paste
);
684 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "SetVoiceSearchSupported")))
685 return v8::FunctionTemplate::New(isolate
, SetVoiceSearchSupported
);
687 v8::String::NewFromUtf8(isolate
, "StartCapturingKeyStrokes")))
688 return v8::FunctionTemplate::New(isolate
, StartCapturingKeyStrokes
);
689 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "StopCapturingKeyStrokes")))
690 return v8::FunctionTemplate::New(isolate
, StopCapturingKeyStrokes
);
692 v8::String::NewFromUtf8(isolate
, "UndoAllMostVisitedDeletions")))
693 return v8::FunctionTemplate::New(isolate
, UndoAllMostVisitedDeletions
);
694 if (name
->Equals(v8::String::NewFromUtf8(isolate
, "UndoMostVisitedDeletion")))
695 return v8::FunctionTemplate::New(isolate
, UndoMostVisitedDeletion
);
697 v8::String::NewFromUtf8(isolate
, "GetDisplayInstantResults")))
698 return v8::FunctionTemplate::New(isolate
, GetDisplayInstantResults
);
699 return v8::Local
<v8::FunctionTemplate
>();
703 content::RenderView
* SearchBoxExtensionWrapper::GetRenderView() {
704 blink::WebLocalFrame
* webframe
=
705 blink::WebLocalFrame::frameForCurrentContext();
706 if (!webframe
) return NULL
;
708 blink::WebView
* webview
= webframe
->view();
709 if (!webview
) return NULL
; // can happen during closing
711 return content::RenderView::FromWebView(webview
);
715 void SearchBoxExtensionWrapper::CheckIsUserSignedInToChromeAs(
716 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
717 content::RenderView
* render_view
= GetRenderView();
718 if (!render_view
) return;
720 if (!args
.Length() || args
[0]->IsUndefined()) {
721 ThrowInvalidParameters(args
);
725 DVLOG(1) << render_view
<< " CheckIsUserSignedInToChromeAs";
727 SearchBox::Get(render_view
)->CheckIsUserSignedInToChromeAs(
728 V8ValueToUTF16(args
[0]));
732 void SearchBoxExtensionWrapper::CheckIsUserSyncingHistory(
733 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
734 content::RenderView
* render_view
= GetRenderView();
735 if (!render_view
) return;
737 DVLOG(1) << render_view
<< " CheckIsUserSyncingHistory";
738 SearchBox::Get(render_view
)->CheckIsUserSyncingHistory();
742 void SearchBoxExtensionWrapper::DeleteMostVisitedItem(
743 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
744 content::RenderView
* render_view
= GetRenderView();
745 if (!render_view
) return;
747 if (!args
.Length()) {
748 ThrowInvalidParameters(args
);
752 DVLOG(1) << render_view
753 << " DeleteMostVisitedItem: " << args
[0]->ToInteger()->Value();
754 SearchBox::Get(render_view
)->
755 DeleteMostVisitedItem(args
[0]->ToInteger()->Value());
759 void SearchBoxExtensionWrapper::Focus(
760 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
761 content::RenderView
* render_view
= GetRenderView();
762 if (!render_view
) return;
764 DVLOG(1) << render_view
<< " Focus";
765 SearchBox::Get(render_view
)->Focus();
769 void SearchBoxExtensionWrapper::GetAppLauncherEnabled(
770 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
771 content::RenderView
* render_view
= GetRenderView();
772 if (!render_view
) return;
774 args
.GetReturnValue().Set(
775 SearchBox::Get(render_view
)->app_launcher_enabled());
779 void SearchBoxExtensionWrapper::GetDispositionFromClick(
780 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
781 content::RenderView
* render_view
= GetRenderView();
782 if (!render_view
) return;
784 if (args
.Length() != 5) {
785 ThrowInvalidParameters(args
);
789 bool middle_button
= args
[0]->BooleanValue();
790 bool alt_key
= args
[1]->BooleanValue();
791 bool ctrl_key
= args
[2]->BooleanValue();
792 bool meta_key
= args
[3]->BooleanValue();
793 bool shift_key
= args
[4]->BooleanValue();
795 WindowOpenDisposition disposition
= ui::DispositionFromClick(middle_button
,
800 v8::Isolate
* isolate
= args
.GetIsolate();
801 args
.GetReturnValue().Set(v8::Int32::New(isolate
, disposition
));
805 void SearchBoxExtensionWrapper::GetMostVisitedItems(
806 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
807 content::RenderView
* render_view
= GetRenderView();
810 DVLOG(1) << render_view
<< " GetMostVisitedItems";
812 const SearchBox
* search_box
= SearchBox::Get(render_view
);
814 std::vector
<InstantMostVisitedItemIDPair
> instant_mv_items
;
815 search_box
->GetMostVisitedItems(&instant_mv_items
);
816 v8::Isolate
* isolate
= args
.GetIsolate();
817 v8::Local
<v8::Array
> v8_mv_items
=
818 v8::Array::New(isolate
, instant_mv_items
.size());
819 for (size_t i
= 0; i
< instant_mv_items
.size(); ++i
) {
821 GenerateMostVisitedItem(isolate
,
822 render_view
->GetRoutingID(),
823 instant_mv_items
[i
].first
,
824 instant_mv_items
[i
].second
));
826 args
.GetReturnValue().Set(v8_mv_items
);
830 void SearchBoxExtensionWrapper::GetMostVisitedItemData(
831 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
832 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
833 GURL(chrome::kChromeSearchMostVisitedUrl
));
834 if (!render_view
) return;
836 // Need an rid argument.
837 if (!args
.Length() || !args
[0]->IsNumber()) {
838 ThrowInvalidParameters(args
);
842 DVLOG(1) << render_view
<< " GetMostVisitedItem";
843 InstantRestrictedID restricted_id
= args
[0]->IntegerValue();
844 InstantMostVisitedItem mv_item
;
845 if (!SearchBox::Get(render_view
)->GetMostVisitedItemWithID(
846 restricted_id
, &mv_item
)) {
849 v8::Isolate
* isolate
= args
.GetIsolate();
850 args
.GetReturnValue().Set(GenerateMostVisitedItem(
851 isolate
, render_view
->GetRoutingID(), restricted_id
, mv_item
));
855 void SearchBoxExtensionWrapper::GetQuery(
856 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
857 content::RenderView
* render_view
= GetRenderView();
858 if (!render_view
) return;
859 const base::string16
& query
= SearchBox::Get(render_view
)->query();
860 DVLOG(1) << render_view
<< " GetQuery: '" << query
<< "'";
861 v8::Isolate
* isolate
= args
.GetIsolate();
862 args
.GetReturnValue().Set(UTF16ToV8String(isolate
, query
));
866 void SearchBoxExtensionWrapper::GetRightToLeft(
867 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
868 args
.GetReturnValue().Set(base::i18n::IsRTL());
872 void SearchBoxExtensionWrapper::GetSearchRequestParams(
873 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
874 content::RenderView
* render_view
= GetRenderView();
875 if (!render_view
) return;
877 const EmbeddedSearchRequestParams
& params
=
878 SearchBox::Get(render_view
)->GetEmbeddedSearchRequestParams();
879 v8::Isolate
* isolate
= args
.GetIsolate();
880 v8::Local
<v8::Object
> data
= v8::Object::New(isolate
);
881 if (!params
.search_query
.empty()) {
882 data
->Set(v8::String::NewFromUtf8(isolate
, kSearchQueryKey
),
883 UTF16ToV8String(isolate
, params
.search_query
));
885 if (!params
.original_query
.empty()) {
886 data
->Set(v8::String::NewFromUtf8(isolate
, kOriginalQueryKey
),
887 UTF16ToV8String(isolate
, params
.original_query
));
889 if (!params
.rlz_parameter_value
.empty()) {
890 data
->Set(v8::String::NewFromUtf8(isolate
, kRLZParameterKey
),
891 UTF16ToV8String(isolate
, params
.rlz_parameter_value
));
893 if (!params
.input_encoding
.empty()) {
894 data
->Set(v8::String::NewFromUtf8(isolate
, kInputEncodingKey
),
895 UTF16ToV8String(isolate
, params
.input_encoding
));
897 if (!params
.assisted_query_stats
.empty()) {
898 data
->Set(v8::String::NewFromUtf8(isolate
, kAssistedQueryStatsKey
),
899 UTF16ToV8String(isolate
, params
.assisted_query_stats
));
901 args
.GetReturnValue().Set(data
);
905 void SearchBoxExtensionWrapper::GetStartMargin(
906 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
907 content::RenderView
* render_view
= GetRenderView();
908 if (!render_view
) return;
909 args
.GetReturnValue().Set(static_cast<int32_t>(
910 SearchBox::Get(render_view
)->start_margin()));
914 void SearchBoxExtensionWrapper::GetSuggestionToPrefetch(
915 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
916 content::RenderView
* render_view
= GetRenderView();
917 if (!render_view
) return;
919 const InstantSuggestion
& suggestion
=
920 SearchBox::Get(render_view
)->suggestion();
921 v8::Isolate
* isolate
= args
.GetIsolate();
922 v8::Local
<v8::Object
> data
= v8::Object::New(isolate
);
923 data
->Set(v8::String::NewFromUtf8(isolate
, "text"),
924 UTF16ToV8String(isolate
, suggestion
.text
));
925 data
->Set(v8::String::NewFromUtf8(isolate
, "metadata"),
926 UTF8ToV8String(isolate
, suggestion
.metadata
));
927 args
.GetReturnValue().Set(data
);
931 void SearchBoxExtensionWrapper::GetThemeBackgroundInfo(
932 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
933 content::RenderView
* render_view
= GetRenderView();
934 if (!render_view
) return;
936 DVLOG(1) << render_view
<< " GetThemeBackgroundInfo";
937 const ThemeBackgroundInfo
& theme_info
=
938 SearchBox::Get(render_view
)->GetThemeBackgroundInfo();
939 v8::Isolate
* isolate
= args
.GetIsolate();
940 v8::Local
<v8::Object
> info
= v8::Object::New(isolate
);
942 info
->Set(v8::String::NewFromUtf8(isolate
, "usingDefaultTheme"),
943 v8::Boolean::New(isolate
, theme_info
.using_default_theme
));
945 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and
946 // B are between 0 and 255 inclusive, and A is a double between 0 and 1
948 // This is the CSS "background-color" format.
949 // Value is always valid.
950 // TODO(jfweitz): Remove this field after GWS is modified to use the new
951 // backgroundColorRgba field.
953 v8::String::NewFromUtf8(isolate
, "colorRgba"),
956 // Convert the alpha using DoubleToString because StringPrintf will
958 // locale specific formatters (e.g., use , instead of . in German).
960 kCSSBackgroundColorFormat
,
961 theme_info
.background_color
.r
,
962 theme_info
.background_color
.g
,
963 theme_info
.background_color
.b
,
964 base::DoubleToString(theme_info
.background_color
.a
/ 255.0)
967 // Theme color for background as an array with the RGBA components in order.
968 // Value is always valid.
969 info
->Set(v8::String::NewFromUtf8(isolate
, "backgroundColorRgba"),
970 internal::RGBAColorToArray(isolate
, theme_info
.background_color
));
972 // Theme color for text as an array with the RGBA components in order.
973 // Value is always valid.
974 info
->Set(v8::String::NewFromUtf8(isolate
, "textColorRgba"),
975 internal::RGBAColorToArray(isolate
, theme_info
.text_color
));
977 // Theme color for links as an array with the RGBA components in order.
978 // Value is always valid.
979 info
->Set(v8::String::NewFromUtf8(isolate
, "linkColorRgba"),
980 internal::RGBAColorToArray(isolate
, theme_info
.link_color
));
982 // Theme color for light text as an array with the RGBA components in order.
983 // Value is always valid.
984 info
->Set(v8::String::NewFromUtf8(isolate
, "textColorLightRgba"),
985 internal::RGBAColorToArray(isolate
, theme_info
.text_color_light
));
987 // Theme color for header as an array with the RGBA components in order.
988 // Value is always valid.
989 info
->Set(v8::String::NewFromUtf8(isolate
, "headerColorRgba"),
990 internal::RGBAColorToArray(isolate
, theme_info
.header_color
));
992 // Theme color for section border as an array with the RGBA components in
993 // order. Value is always valid.
995 v8::String::NewFromUtf8(isolate
, "sectionBorderColorRgba"),
996 internal::RGBAColorToArray(isolate
, theme_info
.section_border_color
));
998 // The theme alternate logo value indicates a white logo when TRUE and a
999 // colorful one when FALSE.
1000 info
->Set(v8::String::NewFromUtf8(isolate
, "alternateLogo"),
1001 v8::Boolean::New(isolate
, theme_info
.logo_alternate
));
1003 // The theme background image url is of format kCSSBackgroundImageFormat
1004 // where both instances of "%s" are replaced with the id that identifies the
1006 // This is the CSS "background-image" format.
1007 // Value is only valid if there's a custom theme background image.
1008 if (crx_file::id_util::IdIsValid(theme_info
.theme_id
)) {
1009 info
->Set(v8::String::NewFromUtf8(isolate
, "imageUrl"),
1010 UTF8ToV8String(isolate
,
1011 base::StringPrintf(kCSSBackgroundImageFormat
,
1012 theme_info
.theme_id
.c_str(),
1013 theme_info
.theme_id
.c_str())));
1015 // The theme background image horizontal alignment is one of "left",
1016 // "right", "center".
1017 // This is the horizontal component of the CSS "background-position" format.
1018 // Value is only valid if |imageUrl| is not empty.
1019 std::string alignment
= kCSSBackgroundPositionCenter
;
1020 if (theme_info
.image_horizontal_alignment
==
1021 THEME_BKGRND_IMAGE_ALIGN_LEFT
) {
1022 alignment
= kCSSBackgroundPositionLeft
;
1023 } else if (theme_info
.image_horizontal_alignment
==
1024 THEME_BKGRND_IMAGE_ALIGN_RIGHT
) {
1025 alignment
= kCSSBackgroundPositionRight
;
1027 info
->Set(v8::String::NewFromUtf8(isolate
, "imageHorizontalAlignment"),
1028 UTF8ToV8String(isolate
, alignment
));
1030 // The theme background image vertical alignment is one of "top", "bottom",
1032 // This is the vertical component of the CSS "background-position" format.
1033 // Value is only valid if |image_url| is not empty.
1034 if (theme_info
.image_vertical_alignment
== THEME_BKGRND_IMAGE_ALIGN_TOP
) {
1035 alignment
= kCSSBackgroundPositionTop
;
1036 } else if (theme_info
.image_vertical_alignment
==
1037 THEME_BKGRND_IMAGE_ALIGN_BOTTOM
) {
1038 alignment
= kCSSBackgroundPositionBottom
;
1040 alignment
= kCSSBackgroundPositionCenter
;
1042 info
->Set(v8::String::NewFromUtf8(isolate
, "imageVerticalAlignment"),
1043 UTF8ToV8String(isolate
, alignment
));
1045 // The tiling of the theme background image is one of "no-repeat",
1046 // "repeat-x", "repeat-y", "repeat".
1047 // This is the CSS "background-repeat" format.
1048 // Value is only valid if |image_url| is not empty.
1049 std::string tiling
= kCSSBackgroundRepeatNo
;
1050 switch (theme_info
.image_tiling
) {
1051 case THEME_BKGRND_IMAGE_NO_REPEAT
:
1052 tiling
= kCSSBackgroundRepeatNo
;
1054 case THEME_BKGRND_IMAGE_REPEAT_X
:
1055 tiling
= kCSSBackgroundRepeatX
;
1057 case THEME_BKGRND_IMAGE_REPEAT_Y
:
1058 tiling
= kCSSBackgroundRepeatY
;
1060 case THEME_BKGRND_IMAGE_REPEAT
:
1061 tiling
= kCSSBackgroundRepeat
;
1064 info
->Set(v8::String::NewFromUtf8(isolate
, "imageTiling"),
1065 UTF8ToV8String(isolate
, tiling
));
1067 // The theme background image height is only valid if |imageUrl| is valid.
1068 info
->Set(v8::String::NewFromUtf8(isolate
, "imageHeight"),
1069 v8::Int32::New(isolate
, theme_info
.image_height
));
1071 // The attribution URL is only valid if the theme has attribution logo.
1072 if (theme_info
.has_attribution
) {
1074 v8::String::NewFromUtf8(isolate
, "attributionUrl"),
1075 UTF8ToV8String(isolate
,
1076 base::StringPrintf(kThemeAttributionFormat
,
1077 theme_info
.theme_id
.c_str(),
1078 theme_info
.theme_id
.c_str())));
1082 args
.GetReturnValue().Set(info
);
1086 void SearchBoxExtensionWrapper::IsFocused(
1087 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1088 content::RenderView
* render_view
= GetRenderView();
1089 if (!render_view
) return;
1091 bool is_focused
= SearchBox::Get(render_view
)->is_focused();
1092 DVLOG(1) << render_view
<< " IsFocused: " << is_focused
;
1093 args
.GetReturnValue().Set(is_focused
);
1097 void SearchBoxExtensionWrapper::IsInputInProgress(
1098 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1099 content::RenderView
* render_view
= GetRenderView();
1100 if (!render_view
) return;
1102 bool is_input_in_progress
=
1103 SearchBox::Get(render_view
)->is_input_in_progress();
1104 DVLOG(1) << render_view
<< " IsInputInProgress: " << is_input_in_progress
;
1105 args
.GetReturnValue().Set(is_input_in_progress
);
1109 void SearchBoxExtensionWrapper::IsKeyCaptureEnabled(
1110 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1111 content::RenderView
* render_view
= GetRenderView();
1112 if (!render_view
) return;
1114 args
.GetReturnValue().Set(SearchBox::Get(render_view
)->
1115 is_key_capture_enabled());
1119 void SearchBoxExtensionWrapper::LogEvent(
1120 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1121 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
1122 GURL(chrome::kChromeSearchMostVisitedUrl
));
1123 if (!render_view
) return;
1125 if (!args
.Length() || !args
[0]->IsNumber()) {
1126 ThrowInvalidParameters(args
);
1130 DVLOG(1) << render_view
<< " LogEvent";
1132 if (args
[0]->Uint32Value() <= NTP_EVENT_TYPE_LAST
) {
1133 NTPLoggingEventType event
=
1134 static_cast<NTPLoggingEventType
>(args
[0]->Uint32Value());
1135 SearchBox::Get(render_view
)->LogEvent(event
);
1140 void SearchBoxExtensionWrapper::LogMostVisitedImpression(
1141 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1142 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
1143 GURL(chrome::kChromeSearchMostVisitedUrl
));
1144 if (!render_view
) return;
1146 if (args
.Length() < 2 || !args
[0]->IsNumber() || args
[1]->IsUndefined()) {
1147 ThrowInvalidParameters(args
);
1151 DVLOG(1) << render_view
<< " LogMostVisitedImpression";
1153 SearchBox::Get(render_view
)->LogMostVisitedImpression(
1154 args
[0]->IntegerValue(), V8ValueToUTF16(args
[1]));
1158 void SearchBoxExtensionWrapper::LogMostVisitedNavigation(
1159 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1160 content::RenderView
* render_view
= GetRenderViewWithCheckedOrigin(
1161 GURL(chrome::kChromeSearchMostVisitedUrl
));
1162 if (!render_view
) return;
1164 if (args
.Length() < 2 || !args
[0]->IsNumber() || args
[1]->IsUndefined()) {
1165 ThrowInvalidParameters(args
);
1169 DVLOG(1) << render_view
<< " LogMostVisitedNavigation";
1171 SearchBox::Get(render_view
)->LogMostVisitedNavigation(
1172 args
[0]->IntegerValue(), V8ValueToUTF16(args
[1]));
1176 void SearchBoxExtensionWrapper::NavigateContentWindow(
1177 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1178 content::RenderView
* render_view
= GetRenderView();
1179 if (!render_view
) return;
1181 if (!args
.Length()) {
1182 ThrowInvalidParameters(args
);
1186 GURL destination_url
;
1187 bool is_most_visited_item_url
= false;
1188 // Check if the url is a rid
1189 if (args
[0]->IsNumber()) {
1190 InstantMostVisitedItem item
;
1191 if (SearchBox::Get(render_view
)->GetMostVisitedItemWithID(
1192 args
[0]->IntegerValue(), &item
)) {
1193 destination_url
= item
.url
;
1194 is_most_visited_item_url
= true;
1198 const base::string16
& possibly_relative_url
= V8ValueToUTF16(args
[0]);
1199 GURL current_url
= GetCurrentURL(render_view
);
1200 destination_url
= internal::ResolveURL(current_url
, possibly_relative_url
);
1203 DVLOG(1) << render_view
<< " NavigateContentWindow: " << destination_url
;
1205 // Navigate the main frame.
1206 if (destination_url
.is_valid() &&
1207 !destination_url
.SchemeIs(url::kJavaScriptScheme
)) {
1208 WindowOpenDisposition disposition
= CURRENT_TAB
;
1209 if (args
[1]->IsNumber()) {
1210 disposition
= (WindowOpenDisposition
) args
[1]->Uint32Value();
1212 SearchBox::Get(render_view
)->NavigateToURL(destination_url
, disposition
,
1213 is_most_visited_item_url
);
1218 void SearchBoxExtensionWrapper::Paste(
1219 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1220 content::RenderView
* render_view
= GetRenderView();
1221 if (!render_view
) return;
1223 base::string16 text
;
1224 if (!args
[0]->IsUndefined())
1225 text
= V8ValueToUTF16(args
[0]);
1227 DVLOG(1) << render_view
<< " Paste: " << text
;
1228 SearchBox::Get(render_view
)->Paste(text
);
1232 void SearchBoxExtensionWrapper::StartCapturingKeyStrokes(
1233 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1234 content::RenderView
* render_view
= GetRenderView();
1235 if (!render_view
) return;
1237 DVLOG(1) << render_view
<< " StartCapturingKeyStrokes";
1238 SearchBox::Get(render_view
)->StartCapturingKeyStrokes();
1242 void SearchBoxExtensionWrapper::StopCapturingKeyStrokes(
1243 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1244 content::RenderView
* render_view
= GetRenderView();
1245 if (!render_view
) return;
1247 DVLOG(1) << render_view
<< " StopCapturingKeyStrokes";
1248 SearchBox::Get(render_view
)->StopCapturingKeyStrokes();
1252 void SearchBoxExtensionWrapper::SetVoiceSearchSupported(
1253 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1254 content::RenderView
* render_view
= GetRenderView();
1258 if (!args
.Length()) {
1259 ThrowInvalidParameters(args
);
1263 DVLOG(1) << render_view
<< " SetVoiceSearchSupported";
1264 SearchBox::Get(render_view
)->SetVoiceSearchSupported(args
[0]->BooleanValue());
1268 void SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions(
1269 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1270 content::RenderView
* render_view
= GetRenderView();
1271 if (!render_view
) return;
1273 DVLOG(1) << render_view
<< " UndoAllMostVisitedDeletions";
1274 SearchBox::Get(render_view
)->UndoAllMostVisitedDeletions();
1278 void SearchBoxExtensionWrapper::UndoMostVisitedDeletion(
1279 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1280 content::RenderView
* render_view
= GetRenderView();
1284 if (!args
.Length()) {
1285 ThrowInvalidParameters(args
);
1289 DVLOG(1) << render_view
<< " UndoMostVisitedDeletion";
1290 SearchBox::Get(render_view
)
1291 ->UndoMostVisitedDeletion(args
[0]->ToInteger()->Value());
1295 void SearchBoxExtensionWrapper::GetDisplayInstantResults(
1296 const v8::FunctionCallbackInfo
<v8::Value
>& args
) {
1297 content::RenderView
* render_view
= GetRenderView();
1298 if (!render_view
) return;
1300 bool display_instant_results
=
1301 SearchBox::Get(render_view
)->display_instant_results();
1302 DVLOG(1) << render_view
<< " GetDisplayInstantResults" <<
1303 display_instant_results
;
1304 args
.GetReturnValue().Set(display_instant_results
);
1307 } // namespace extensions_v8