Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / renderer / searchbox / searchbox_extension.cc
blob7cb5d7d49786efc17484c3733ecfadd5f07e13f1
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/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 "components/variations/variations_associated_data.h"
20 #include "content/public/renderer/render_view.h"
21 #include "third_party/WebKit/public/platform/WebURLRequest.h"
22 #include "third_party/WebKit/public/web/WebDocument.h"
23 #include "third_party/WebKit/public/web/WebLocalFrame.h"
24 #include "third_party/WebKit/public/web/WebScriptSource.h"
25 #include "third_party/WebKit/public/web/WebView.h"
26 #include "ui/base/resource/resource_bundle.h"
27 #include "ui/base/window_open_disposition.h"
28 #include "ui/events/keycodes/keyboard_codes.h"
29 #include "url/gurl.h"
30 #include "url/url_constants.h"
31 #include "v8/include/v8.h"
33 namespace {
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 // Returns whether we should use large icons on NTP.
66 bool IsIconNTPEnabled() {
67 return variations::GetVariationParamValue("IconNTP", "state") == "enabled";
70 // Converts string16 to V8 String.
71 v8::Handle<v8::String> UTF16ToV8String(v8::Isolate* isolate,
72 const base::string16& s) {
73 return v8::String::NewFromTwoByte(isolate,
74 reinterpret_cast<const uint16_t*>(s.data()),
75 v8::String::kNormalString,
76 s.size());
79 // Converts std::string to V8 String.
80 v8::Handle<v8::String> UTF8ToV8String(v8::Isolate* isolate,
81 const std::string& s) {
82 return v8::String::NewFromUtf8(
83 isolate, s.data(), v8::String::kNormalString, s.size());
86 // Throws a TypeError on the current V8 context if the args are invalid.
87 void ThrowInvalidParameters(const v8::FunctionCallbackInfo<v8::Value>& args) {
88 v8::Isolate* isolate = args.GetIsolate();
89 isolate->ThrowException(v8::Exception::TypeError(
90 v8::String::NewFromUtf8(isolate, "Invalid parameters")));
93 void Dispatch(blink::WebFrame* frame, const blink::WebString& script) {
94 if (!frame) return;
95 frame->executeScript(blink::WebScriptSource(script));
98 v8::Handle<v8::String> GenerateThumbnailURL(
99 v8::Isolate* isolate,
100 int render_view_id,
101 InstantRestrictedID most_visited_item_id) {
102 return UTF8ToV8String(
103 isolate,
104 base::StringPrintf(
105 "chrome-search://thumb/%d/%d", render_view_id, most_visited_item_id));
108 v8::Handle<v8::String> GenerateLargeIconURL(
109 v8::Isolate* isolate,
110 int render_view_id,
111 InstantRestrictedID most_visited_item_id) {
112 const int kIconSize = 96; // To support high DPI; on screen it's 48 dp.
113 return UTF8ToV8String(
114 isolate,
115 base::StringPrintf("chrome-search://large-icon/%d/%d/%d",
116 kIconSize, render_view_id, most_visited_item_id));
119 v8::Handle<v8::String> GenerateFallbackIconURL(
120 v8::Isolate* isolate,
121 int render_view_id,
122 InstantRestrictedID most_visited_item_id) {
123 return UTF8ToV8String(
124 isolate,
125 base::StringPrintf("chrome-search://fallback-icon/,,,,1/%d/%d",
126 render_view_id, most_visited_item_id));
129 // Populates a Javascript MostVisitedItem object from |mv_item|.
130 // NOTE: Includes "url", "title" and "domain" which are private data, so should
131 // not be returned to the Instant page. These should be erased before returning
132 // the object. See GetMostVisitedItemsWrapper() in searchbox_api.js.
133 v8::Handle<v8::Object> GenerateMostVisitedItem(
134 v8::Isolate* isolate,
135 int render_view_id,
136 InstantRestrictedID restricted_id,
137 const InstantMostVisitedItem& mv_item) {
138 // We set the "dir" attribute of the title, so that in RTL locales, a LTR
139 // title is rendered left-to-right and truncated from the right. For
140 // example, the title of http://msdn.microsoft.com/en-us/default.aspx is
141 // "MSDN: Microsoft developer network". In RTL locales, in the New Tab
142 // page, if the "dir" of this title is not specified, it takes Chrome UI's
143 // directionality. So the title will be truncated as "soft developer
144 // network". Setting the "dir" attribute as "ltr" renders the truncated
145 // title as "MSDN: Microsoft D...". As another example, the title of
146 // http://yahoo.com is "Yahoo!". In RTL locales, in the New Tab page, the
147 // title will be rendered as "!Yahoo" if its "dir" attribute is not set to
148 // "ltr".
149 std::string direction;
150 if (base::i18n::StringContainsStrongRTLChars(mv_item.title))
151 direction = kRTLHtmlTextDirection;
152 else
153 direction = kLTRHtmlTextDirection;
155 base::string16 title = mv_item.title;
156 if (title.empty())
157 title = base::UTF8ToUTF16(mv_item.url.spec());
159 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
160 obj->Set(v8::String::NewFromUtf8(isolate, "renderViewId"),
161 v8::Int32::New(isolate, render_view_id));
162 obj->Set(v8::String::NewFromUtf8(isolate, "rid"),
163 v8::Int32::New(isolate, restricted_id));
164 obj->Set(v8::String::NewFromUtf8(isolate, "thumbnailUrl"),
165 GenerateThumbnailURL(isolate, render_view_id, restricted_id));
166 if (IsIconNTPEnabled()) {
167 // Update website http://www.chromium.org/embeddedsearch when we make this
168 // permanent.
169 obj->Set(v8::String::NewFromUtf8(isolate, "largeIconUrl"),
170 GenerateLargeIconURL(isolate, render_view_id, restricted_id));
171 obj->Set(v8::String::NewFromUtf8(isolate, "fallbackIconUrl"),
172 GenerateFallbackIconURL(isolate, render_view_id, restricted_id));
174 obj->Set(v8::String::NewFromUtf8(isolate, "title"),
175 UTF16ToV8String(isolate, title));
176 obj->Set(v8::String::NewFromUtf8(isolate, "domain"),
177 UTF8ToV8String(isolate, mv_item.url.host()));
178 obj->Set(v8::String::NewFromUtf8(isolate, "direction"),
179 UTF8ToV8String(isolate, direction));
180 obj->Set(v8::String::NewFromUtf8(isolate, "url"),
181 UTF8ToV8String(isolate, mv_item.url.spec()));
182 return obj;
185 // Returns the render view for the current JS context if it matches |origin|,
186 // otherwise returns NULL. Used to restrict methods that access suggestions and
187 // most visited data to pages with origin chrome-search://most-visited and
188 // chrome-search://suggestions.
189 content::RenderView* GetRenderViewWithCheckedOrigin(const GURL& origin) {
190 blink::WebLocalFrame* webframe =
191 blink::WebLocalFrame::frameForCurrentContext();
192 if (!webframe)
193 return NULL;
194 blink::WebView* webview = webframe->view();
195 if (!webview)
196 return NULL; // Can happen during closing.
197 content::RenderView* render_view = content::RenderView::FromWebView(webview);
198 if (!render_view)
199 return NULL;
201 GURL url(webframe->document().url());
202 if (url.GetOrigin() != origin.GetOrigin())
203 return NULL;
205 return render_view;
208 // Returns the current URL.
209 GURL GetCurrentURL(content::RenderView* render_view) {
210 blink::WebView* webview = render_view->GetWebView();
211 return webview ? GURL(webview->mainFrame()->document().url()) : GURL();
214 } // namespace
216 namespace internal { // for testing.
218 // Returns an array with the RGBA color components.
219 v8::Handle<v8::Value> RGBAColorToArray(v8::Isolate* isolate,
220 const RGBAColor& color) {
221 v8::Handle<v8::Array> color_array = v8::Array::New(isolate, 4);
222 color_array->Set(0, v8::Int32::New(isolate, color.r));
223 color_array->Set(1, v8::Int32::New(isolate, color.g));
224 color_array->Set(2, v8::Int32::New(isolate, color.b));
225 color_array->Set(3, v8::Int32::New(isolate, color.a));
226 return color_array;
229 // Resolves a possibly relative URL using the current URL.
230 GURL ResolveURL(const GURL& current_url,
231 const base::string16& possibly_relative_url) {
232 if (current_url.is_valid() && !possibly_relative_url.empty())
233 return current_url.Resolve(possibly_relative_url);
234 return GURL(possibly_relative_url);
237 } // namespace internal
239 namespace extensions_v8 {
241 static const char kSearchBoxExtensionName[] = "v8/EmbeddedSearch";
243 // We first send this script down to determine if the page supports instant.
244 static const char kSupportsInstantScript[] =
245 "if (window.chrome &&"
246 " window.chrome.embeddedSearch &&"
247 " window.chrome.embeddedSearch.searchBox &&"
248 " window.chrome.embeddedSearch.searchBox.onsubmit &&"
249 " typeof window.chrome.embeddedSearch.searchBox.onsubmit =="
250 " 'function') {"
251 " true;"
252 "} else {"
253 " false;"
254 "}";
256 static const char kDispatchChromeIdentityCheckResult[] =
257 "if (window.chrome &&"
258 " window.chrome.embeddedSearch &&"
259 " window.chrome.embeddedSearch.newTabPage &&"
260 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone &&"
261 " typeof window.chrome.embeddedSearch.newTabPage"
262 " .onsignedincheckdone === 'function') {"
263 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone(%s, %s);"
264 " true;"
265 "}";
267 static const char kDispatchFocusChangedScript[] =
268 "if (window.chrome &&"
269 " window.chrome.embeddedSearch &&"
270 " window.chrome.embeddedSearch.searchBox &&"
271 " window.chrome.embeddedSearch.searchBox.onfocuschange &&"
272 " typeof window.chrome.embeddedSearch.searchBox.onfocuschange =="
273 " 'function') {"
274 " window.chrome.embeddedSearch.searchBox.onfocuschange();"
275 " true;"
276 "}";
278 static const char kDispatchHistorySyncCheckResult[] =
279 "if (window.chrome &&"
280 " window.chrome.embeddedSearch &&"
281 " window.chrome.embeddedSearch.newTabPage &&"
282 " window.chrome.embeddedSearch.newTabPage.onhistorysynccheckdone &&"
283 " typeof window.chrome.embeddedSearch.newTabPage"
284 " .onhistorysynccheckdone === 'function') {"
285 " window.chrome.embeddedSearch.newTabPage.onhistorysynccheckdone(%s);"
286 " true;"
287 "}";
289 static const char kDispatchInputCancelScript[] =
290 "if (window.chrome &&"
291 " window.chrome.embeddedSearch &&"
292 " window.chrome.embeddedSearch.newTabPage &&"
293 " window.chrome.embeddedSearch.newTabPage.oninputcancel &&"
294 " typeof window.chrome.embeddedSearch.newTabPage.oninputcancel =="
295 " 'function') {"
296 " window.chrome.embeddedSearch.newTabPage.oninputcancel();"
297 " true;"
298 "}";
300 static const char kDispatchInputStartScript[] =
301 "if (window.chrome &&"
302 " window.chrome.embeddedSearch &&"
303 " window.chrome.embeddedSearch.newTabPage &&"
304 " window.chrome.embeddedSearch.newTabPage.oninputstart &&"
305 " typeof window.chrome.embeddedSearch.newTabPage.oninputstart =="
306 " 'function') {"
307 " window.chrome.embeddedSearch.newTabPage.oninputstart();"
308 " true;"
309 "}";
311 static const char kDispatchKeyCaptureChangeScript[] =
312 "if (window.chrome &&"
313 " window.chrome.embeddedSearch &&"
314 " window.chrome.embeddedSearch.searchBox &&"
315 " window.chrome.embeddedSearch.searchBox.onkeycapturechange &&"
316 " typeof window.chrome.embeddedSearch.searchBox.onkeycapturechange =="
317 " 'function') {"
318 " window.chrome.embeddedSearch.searchBox.onkeycapturechange();"
319 " true;"
320 "}";
322 static const char kDispatchMarginChangeEventScript[] =
323 "if (window.chrome &&"
324 " window.chrome.embeddedSearch &&"
325 " window.chrome.embeddedSearch.searchBox &&"
326 " window.chrome.embeddedSearch.searchBox.onmarginchange &&"
327 " typeof window.chrome.embeddedSearch.searchBox.onmarginchange =="
328 " 'function') {"
329 " window.chrome.embeddedSearch.searchBox.onmarginchange();"
330 " true;"
331 "}";
333 static const char kDispatchMostVisitedChangedScript[] =
334 "if (window.chrome &&"
335 " window.chrome.embeddedSearch &&"
336 " window.chrome.embeddedSearch.newTabPage &&"
337 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange &&"
338 " typeof window.chrome.embeddedSearch.newTabPage.onmostvisitedchange =="
339 " 'function') {"
340 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange();"
341 " true;"
342 "}";
344 static const char kDispatchSubmitEventScript[] =
345 "if (window.chrome &&"
346 " window.chrome.embeddedSearch &&"
347 " window.chrome.embeddedSearch.searchBox &&"
348 " window.chrome.embeddedSearch.searchBox.onsubmit &&"
349 " typeof window.chrome.embeddedSearch.searchBox.onsubmit =="
350 " 'function') {"
351 " window.chrome.embeddedSearch.searchBox.onsubmit();"
352 " true;"
353 "}";
355 static const char kDispatchSuggestionChangeEventScript[] =
356 "if (window.chrome &&"
357 " window.chrome.embeddedSearch &&"
358 " window.chrome.embeddedSearch.searchBox &&"
359 " window.chrome.embeddedSearch.searchBox.onsuggestionchange &&"
360 " typeof window.chrome.embeddedSearch.searchBox.onsuggestionchange =="
361 " 'function') {"
362 " window.chrome.embeddedSearch.searchBox.onsuggestionchange();"
363 " true;"
364 "}";
366 static const char kDispatchThemeChangeEventScript[] =
367 "if (window.chrome &&"
368 " window.chrome.embeddedSearch &&"
369 " window.chrome.embeddedSearch.newTabPage &&"
370 " window.chrome.embeddedSearch.newTabPage.onthemechange &&"
371 " typeof window.chrome.embeddedSearch.newTabPage.onthemechange =="
372 " 'function') {"
373 " window.chrome.embeddedSearch.newTabPage.onthemechange();"
374 " true;"
375 "}";
377 static const char kDispatchToggleVoiceSearchScript[] =
378 "if (window.chrome &&"
379 " window.chrome.embeddedSearch &&"
380 " window.chrome.embeddedSearch.searchBox &&"
381 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch &&"
382 " typeof window.chrome.embeddedSearch.searchBox.ontogglevoicesearch =="
383 " 'function') {"
384 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch();"
385 " true;"
386 "}";
388 // ----------------------------------------------------------------------------
390 class SearchBoxExtensionWrapper : public v8::Extension {
391 public:
392 explicit SearchBoxExtensionWrapper(const base::StringPiece& code);
394 // Allows v8's javascript code to call the native functions defined
395 // in this class for window.chrome.
396 v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
397 v8::Isolate*,
398 v8::Handle<v8::String> name) override;
400 // Helper function to find the RenderView. May return NULL.
401 static content::RenderView* GetRenderView();
403 // Sends a Chrome identity check to the browser.
404 static void CheckIsUserSignedInToChromeAs(
405 const v8::FunctionCallbackInfo<v8::Value>& args);
407 // Checks whether the user sync his history.
408 static void CheckIsUserSyncingHistory(
409 const v8::FunctionCallbackInfo<v8::Value>& args);
411 // Deletes a Most Visited item.
412 static void DeleteMostVisitedItem(
413 const v8::FunctionCallbackInfo<v8::Value>& args);
415 // Focuses the omnibox.
416 static void Focus(const v8::FunctionCallbackInfo<v8::Value>& args);
418 // Gets whether or not the app launcher is enabled.
419 static void GetAppLauncherEnabled(
420 const v8::FunctionCallbackInfo<v8::Value>& args);
422 // Gets the desired navigation behavior from a click event.
423 static void GetDispositionFromClick(
424 const v8::FunctionCallbackInfo<v8::Value>& args);
426 // Gets Most Visited Items.
427 static void GetMostVisitedItems(
428 const v8::FunctionCallbackInfo<v8::Value>& args);
430 // Gets the raw data for a most visited item including its raw URL.
431 // GetRenderViewWithCheckedOrigin() enforces that only code in the origin
432 // chrome-search://most-visited can call this function.
433 static void GetMostVisitedItemData(
434 const v8::FunctionCallbackInfo<v8::Value>& args);
436 // Gets the submitted value of the user's search query.
437 static void GetQuery(const v8::FunctionCallbackInfo<v8::Value>& args);
439 // Returns true if the Searchbox itself is oriented right-to-left.
440 static void GetRightToLeft(const v8::FunctionCallbackInfo<v8::Value>& args);
442 // Gets the Embedded Search request params. Used for logging purposes.
443 static void GetSearchRequestParams(
444 const v8::FunctionCallbackInfo<v8::Value>& args);
446 // Gets the start-edge margin to use with extended Instant.
447 static void GetStartMargin(const v8::FunctionCallbackInfo<v8::Value>& args);
449 // Gets the current top suggestion to prefetch search results.
450 static void GetSuggestionToPrefetch(
451 const v8::FunctionCallbackInfo<v8::Value>& args);
453 // Gets the background info of the theme currently adopted by browser.
454 // Call only when overlay is showing NTP page.
455 static void GetThemeBackgroundInfo(
456 const v8::FunctionCallbackInfo<v8::Value>& args);
458 // Gets whether the omnibox has focus or not.
459 static void IsFocused(const v8::FunctionCallbackInfo<v8::Value>& args);
461 // Gets whether user input is in progress.
462 static void IsInputInProgress(
463 const v8::FunctionCallbackInfo<v8::Value>& args);
465 // Gets whether the browser is capturing key strokes.
466 static void IsKeyCaptureEnabled(
467 const v8::FunctionCallbackInfo<v8::Value>& args);
469 // Logs information from the iframes/titles on the NTP.
470 static void LogEvent(const v8::FunctionCallbackInfo<v8::Value>& args);
472 // Logs an impression on one of the Most Visited tile on the NTP.
473 static void LogMostVisitedImpression(
474 const v8::FunctionCallbackInfo<v8::Value>& args);
476 // Logs a navigation on one of the Most Visited tile on the NTP.
477 static void LogMostVisitedNavigation(
478 const v8::FunctionCallbackInfo<v8::Value>& args);
480 // Navigates the window to a URL represented by either a URL string or a
481 // restricted ID.
482 static void NavigateContentWindow(
483 const v8::FunctionCallbackInfo<v8::Value>& args);
485 // Pastes provided value or clipboard's content into the omnibox.
486 static void Paste(const v8::FunctionCallbackInfo<v8::Value>& args);
488 // Indicates whether the page supports voice search.
489 static void SetVoiceSearchSupported(
490 const v8::FunctionCallbackInfo<v8::Value>& args);
492 // Start capturing user key strokes.
493 static void StartCapturingKeyStrokes(
494 const v8::FunctionCallbackInfo<v8::Value>& args);
496 // Stop capturing user key strokes.
497 static void StopCapturingKeyStrokes(
498 const v8::FunctionCallbackInfo<v8::Value>& args);
500 // Undoes the deletion of all Most Visited itens.
501 static void UndoAllMostVisitedDeletions(
502 const v8::FunctionCallbackInfo<v8::Value>& args);
504 // Undoes the deletion of a Most Visited item.
505 static void UndoMostVisitedDeletion(
506 const v8::FunctionCallbackInfo<v8::Value>& args);
508 // Indicates whether the page supports Instant.
509 static void GetDisplayInstantResults(
510 const v8::FunctionCallbackInfo<v8::Value>& args);
512 private:
513 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper);
516 // static
517 v8::Extension* SearchBoxExtension::Get() {
518 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance().
519 GetRawDataResource(IDR_SEARCHBOX_API));
522 // static
523 bool SearchBoxExtension::PageSupportsInstant(blink::WebFrame* frame) {
524 if (!frame) return false;
525 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
526 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue(
527 blink::WebScriptSource(kSupportsInstantScript));
528 return !v.IsEmpty() && v->BooleanValue();
531 // static
532 void SearchBoxExtension::DispatchChromeIdentityCheckResult(
533 blink::WebFrame* frame,
534 const base::string16& identity,
535 bool identity_match) {
536 std::string escaped_identity = base::GetQuotedJSONString(identity);
537 blink::WebString script(base::UTF8ToUTF16(base::StringPrintf(
538 kDispatchChromeIdentityCheckResult,
539 escaped_identity.c_str(),
540 identity_match ? "true" : "false")));
541 Dispatch(frame, script);
544 // static
545 void SearchBoxExtension::DispatchFocusChange(blink::WebFrame* frame) {
546 Dispatch(frame, kDispatchFocusChangedScript);
549 // static
550 void SearchBoxExtension::DispatchHistorySyncCheckResult(
551 blink::WebFrame* frame,
552 bool sync_history) {
553 blink::WebString script(base::UTF8ToUTF16(base::StringPrintf(
554 kDispatchHistorySyncCheckResult,
555 sync_history ? "true" : "false")));
556 Dispatch(frame, script);
559 // static
560 void SearchBoxExtension::DispatchInputCancel(blink::WebFrame* frame) {
561 Dispatch(frame, kDispatchInputCancelScript);
564 // static
565 void SearchBoxExtension::DispatchInputStart(blink::WebFrame* frame) {
566 Dispatch(frame, kDispatchInputStartScript);
569 // static
570 void SearchBoxExtension::DispatchKeyCaptureChange(blink::WebFrame* frame) {
571 Dispatch(frame, kDispatchKeyCaptureChangeScript);
574 // static
575 void SearchBoxExtension::DispatchMarginChange(blink::WebFrame* frame) {
576 Dispatch(frame, kDispatchMarginChangeEventScript);
579 // static
580 void SearchBoxExtension::DispatchMostVisitedChanged(
581 blink::WebFrame* frame) {
582 Dispatch(frame, kDispatchMostVisitedChangedScript);
585 // static
586 void SearchBoxExtension::DispatchSubmit(blink::WebFrame* frame) {
587 Dispatch(frame, kDispatchSubmitEventScript);
590 // static
591 void SearchBoxExtension::DispatchSuggestionChange(blink::WebFrame* frame) {
592 Dispatch(frame, kDispatchSuggestionChangeEventScript);
595 // static
596 void SearchBoxExtension::DispatchThemeChange(blink::WebFrame* frame) {
597 Dispatch(frame, kDispatchThemeChangeEventScript);
600 // static
601 void SearchBoxExtension::DispatchToggleVoiceSearch(
602 blink::WebFrame* frame) {
603 Dispatch(frame, kDispatchToggleVoiceSearchScript);
606 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper(
607 const base::StringPiece& code)
608 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) {
611 v8::Handle<v8::FunctionTemplate>
612 SearchBoxExtensionWrapper::GetNativeFunctionTemplate(
613 v8::Isolate* isolate,
614 v8::Handle<v8::String> name) {
615 if (name->Equals(
616 v8::String::NewFromUtf8(isolate, "CheckIsUserSignedInToChromeAs")))
617 return v8::FunctionTemplate::New(isolate, CheckIsUserSignedInToChromeAs);
618 if (name->Equals(
619 v8::String::NewFromUtf8(isolate, "CheckIsUserSyncingHistory")))
620 return v8::FunctionTemplate::New(isolate, CheckIsUserSyncingHistory);
621 if (name->Equals(v8::String::NewFromUtf8(isolate, "DeleteMostVisitedItem")))
622 return v8::FunctionTemplate::New(isolate, DeleteMostVisitedItem);
623 if (name->Equals(v8::String::NewFromUtf8(isolate, "Focus")))
624 return v8::FunctionTemplate::New(isolate, Focus);
625 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetAppLauncherEnabled")))
626 return v8::FunctionTemplate::New(isolate, GetAppLauncherEnabled);
627 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetDispositionFromClick")))
628 return v8::FunctionTemplate::New(isolate, GetDispositionFromClick);
629 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetMostVisitedItems")))
630 return v8::FunctionTemplate::New(isolate, GetMostVisitedItems);
631 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetMostVisitedItemData")))
632 return v8::FunctionTemplate::New(isolate, GetMostVisitedItemData);
633 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetQuery")))
634 return v8::FunctionTemplate::New(isolate, GetQuery);
635 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetRightToLeft")))
636 return v8::FunctionTemplate::New(isolate, GetRightToLeft);
637 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetSearchRequestParams")))
638 return v8::FunctionTemplate::New(isolate, GetSearchRequestParams);
639 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetStartMargin")))
640 return v8::FunctionTemplate::New(isolate, GetStartMargin);
641 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetSuggestionToPrefetch")))
642 return v8::FunctionTemplate::New(isolate, GetSuggestionToPrefetch);
643 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetThemeBackgroundInfo")))
644 return v8::FunctionTemplate::New(isolate, GetThemeBackgroundInfo);
645 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsFocused")))
646 return v8::FunctionTemplate::New(isolate, IsFocused);
647 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsInputInProgress")))
648 return v8::FunctionTemplate::New(isolate, IsInputInProgress);
649 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsKeyCaptureEnabled")))
650 return v8::FunctionTemplate::New(isolate, IsKeyCaptureEnabled);
651 if (name->Equals(v8::String::NewFromUtf8(isolate, "LogEvent")))
652 return v8::FunctionTemplate::New(isolate, LogEvent);
653 if (name->Equals(
654 v8::String::NewFromUtf8(isolate, "LogMostVisitedImpression"))) {
655 return v8::FunctionTemplate::New(isolate, LogMostVisitedImpression);
657 if (name->Equals(
658 v8::String::NewFromUtf8(isolate, "LogMostVisitedNavigation"))) {
659 return v8::FunctionTemplate::New(isolate, LogMostVisitedNavigation);
661 if (name->Equals(v8::String::NewFromUtf8(isolate, "NavigateContentWindow")))
662 return v8::FunctionTemplate::New(isolate, NavigateContentWindow);
663 if (name->Equals(v8::String::NewFromUtf8(isolate, "Paste")))
664 return v8::FunctionTemplate::New(isolate, Paste);
665 if (name->Equals(v8::String::NewFromUtf8(isolate, "SetVoiceSearchSupported")))
666 return v8::FunctionTemplate::New(isolate, SetVoiceSearchSupported);
667 if (name->Equals(
668 v8::String::NewFromUtf8(isolate, "StartCapturingKeyStrokes")))
669 return v8::FunctionTemplate::New(isolate, StartCapturingKeyStrokes);
670 if (name->Equals(v8::String::NewFromUtf8(isolate, "StopCapturingKeyStrokes")))
671 return v8::FunctionTemplate::New(isolate, StopCapturingKeyStrokes);
672 if (name->Equals(
673 v8::String::NewFromUtf8(isolate, "UndoAllMostVisitedDeletions")))
674 return v8::FunctionTemplate::New(isolate, UndoAllMostVisitedDeletions);
675 if (name->Equals(v8::String::NewFromUtf8(isolate, "UndoMostVisitedDeletion")))
676 return v8::FunctionTemplate::New(isolate, UndoMostVisitedDeletion);
677 if (name->Equals(
678 v8::String::NewFromUtf8(isolate, "GetDisplayInstantResults")))
679 return v8::FunctionTemplate::New(isolate, GetDisplayInstantResults);
680 return v8::Handle<v8::FunctionTemplate>();
683 // static
684 content::RenderView* SearchBoxExtensionWrapper::GetRenderView() {
685 blink::WebLocalFrame* webframe =
686 blink::WebLocalFrame::frameForCurrentContext();
687 if (!webframe) return NULL;
689 blink::WebView* webview = webframe->view();
690 if (!webview) return NULL; // can happen during closing
692 return content::RenderView::FromWebView(webview);
695 // static
696 void SearchBoxExtensionWrapper::CheckIsUserSignedInToChromeAs(
697 const v8::FunctionCallbackInfo<v8::Value>& args) {
698 content::RenderView* render_view = GetRenderView();
699 if (!render_view) return;
701 if (!args.Length() || args[0]->IsUndefined()) {
702 ThrowInvalidParameters(args);
703 return;
706 DVLOG(1) << render_view << " CheckIsUserSignedInToChromeAs";
708 SearchBox::Get(render_view)->CheckIsUserSignedInToChromeAs(
709 V8ValueToUTF16(args[0]));
712 // static
713 void SearchBoxExtensionWrapper::CheckIsUserSyncingHistory(
714 const v8::FunctionCallbackInfo<v8::Value>& args) {
715 content::RenderView* render_view = GetRenderView();
716 if (!render_view) return;
718 DVLOG(1) << render_view << " CheckIsUserSyncingHistory";
719 SearchBox::Get(render_view)->CheckIsUserSyncingHistory();
722 // static
723 void SearchBoxExtensionWrapper::DeleteMostVisitedItem(
724 const v8::FunctionCallbackInfo<v8::Value>& args) {
725 content::RenderView* render_view = GetRenderView();
726 if (!render_view) return;
728 if (!args.Length()) {
729 ThrowInvalidParameters(args);
730 return;
733 DVLOG(1) << render_view
734 << " DeleteMostVisitedItem: " << args[0]->ToInteger()->Value();
735 SearchBox::Get(render_view)->
736 DeleteMostVisitedItem(args[0]->ToInteger()->Value());
739 // static
740 void SearchBoxExtensionWrapper::Focus(
741 const v8::FunctionCallbackInfo<v8::Value>& args) {
742 content::RenderView* render_view = GetRenderView();
743 if (!render_view) return;
745 DVLOG(1) << render_view << " Focus";
746 SearchBox::Get(render_view)->Focus();
749 // static
750 void SearchBoxExtensionWrapper::GetAppLauncherEnabled(
751 const v8::FunctionCallbackInfo<v8::Value>& args) {
752 content::RenderView* render_view = GetRenderView();
753 if (!render_view) return;
755 args.GetReturnValue().Set(
756 SearchBox::Get(render_view)->app_launcher_enabled());
759 // static
760 void SearchBoxExtensionWrapper::GetDispositionFromClick(
761 const v8::FunctionCallbackInfo<v8::Value>& args) {
762 content::RenderView* render_view = GetRenderView();
763 if (!render_view) return;
765 if (args.Length() != 5) {
766 ThrowInvalidParameters(args);
767 return;
770 bool middle_button = args[0]->BooleanValue();
771 bool alt_key = args[1]->BooleanValue();
772 bool ctrl_key = args[2]->BooleanValue();
773 bool meta_key = args[3]->BooleanValue();
774 bool shift_key = args[4]->BooleanValue();
776 WindowOpenDisposition disposition = ui::DispositionFromClick(middle_button,
777 alt_key,
778 ctrl_key,
779 meta_key,
780 shift_key);
781 v8::Isolate* isolate = args.GetIsolate();
782 args.GetReturnValue().Set(v8::Int32::New(isolate, disposition));
785 // static
786 void SearchBoxExtensionWrapper::GetMostVisitedItems(
787 const v8::FunctionCallbackInfo<v8::Value>& args) {
788 content::RenderView* render_view = GetRenderView();
789 if (!render_view)
790 return;
791 DVLOG(1) << render_view << " GetMostVisitedItems";
793 const SearchBox* search_box = SearchBox::Get(render_view);
795 std::vector<InstantMostVisitedItemIDPair> instant_mv_items;
796 search_box->GetMostVisitedItems(&instant_mv_items);
797 v8::Isolate* isolate = args.GetIsolate();
798 v8::Handle<v8::Array> v8_mv_items =
799 v8::Array::New(isolate, instant_mv_items.size());
800 for (size_t i = 0; i < instant_mv_items.size(); ++i) {
801 v8_mv_items->Set(i,
802 GenerateMostVisitedItem(isolate,
803 render_view->GetRoutingID(),
804 instant_mv_items[i].first,
805 instant_mv_items[i].second));
807 args.GetReturnValue().Set(v8_mv_items);
810 // static
811 void SearchBoxExtensionWrapper::GetMostVisitedItemData(
812 const v8::FunctionCallbackInfo<v8::Value>& args) {
813 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
814 GURL(chrome::kChromeSearchMostVisitedUrl));
815 if (!render_view) return;
817 // Need an rid argument.
818 if (!args.Length() || !args[0]->IsNumber()) {
819 ThrowInvalidParameters(args);
820 return;
823 DVLOG(1) << render_view << " GetMostVisitedItem";
824 InstantRestrictedID restricted_id = args[0]->IntegerValue();
825 InstantMostVisitedItem mv_item;
826 if (!SearchBox::Get(render_view)->GetMostVisitedItemWithID(
827 restricted_id, &mv_item)) {
828 return;
830 v8::Isolate* isolate = args.GetIsolate();
831 args.GetReturnValue().Set(GenerateMostVisitedItem(
832 isolate, render_view->GetRoutingID(), restricted_id, mv_item));
835 // static
836 void SearchBoxExtensionWrapper::GetQuery(
837 const v8::FunctionCallbackInfo<v8::Value>& args) {
838 content::RenderView* render_view = GetRenderView();
839 if (!render_view) return;
840 const base::string16& query = SearchBox::Get(render_view)->query();
841 DVLOG(1) << render_view << " GetQuery: '" << query << "'";
842 v8::Isolate* isolate = args.GetIsolate();
843 args.GetReturnValue().Set(UTF16ToV8String(isolate, query));
846 // static
847 void SearchBoxExtensionWrapper::GetRightToLeft(
848 const v8::FunctionCallbackInfo<v8::Value>& args) {
849 args.GetReturnValue().Set(base::i18n::IsRTL());
852 // static
853 void SearchBoxExtensionWrapper::GetSearchRequestParams(
854 const v8::FunctionCallbackInfo<v8::Value>& args) {
855 content::RenderView* render_view = GetRenderView();
856 if (!render_view) return;
858 const EmbeddedSearchRequestParams& params =
859 SearchBox::Get(render_view)->GetEmbeddedSearchRequestParams();
860 v8::Isolate* isolate = args.GetIsolate();
861 v8::Handle<v8::Object> data = v8::Object::New(isolate);
862 if (!params.search_query.empty()) {
863 data->Set(v8::String::NewFromUtf8(isolate, kSearchQueryKey),
864 UTF16ToV8String(isolate, params.search_query));
866 if (!params.original_query.empty()) {
867 data->Set(v8::String::NewFromUtf8(isolate, kOriginalQueryKey),
868 UTF16ToV8String(isolate, params.original_query));
870 if (!params.rlz_parameter_value.empty()) {
871 data->Set(v8::String::NewFromUtf8(isolate, kRLZParameterKey),
872 UTF16ToV8String(isolate, params.rlz_parameter_value));
874 if (!params.input_encoding.empty()) {
875 data->Set(v8::String::NewFromUtf8(isolate, kInputEncodingKey),
876 UTF16ToV8String(isolate, params.input_encoding));
878 if (!params.assisted_query_stats.empty()) {
879 data->Set(v8::String::NewFromUtf8(isolate, kAssistedQueryStatsKey),
880 UTF16ToV8String(isolate, params.assisted_query_stats));
882 args.GetReturnValue().Set(data);
885 // static
886 void SearchBoxExtensionWrapper::GetStartMargin(
887 const v8::FunctionCallbackInfo<v8::Value>& args) {
888 content::RenderView* render_view = GetRenderView();
889 if (!render_view) return;
890 args.GetReturnValue().Set(static_cast<int32_t>(
891 SearchBox::Get(render_view)->start_margin()));
894 // static
895 void SearchBoxExtensionWrapper::GetSuggestionToPrefetch(
896 const v8::FunctionCallbackInfo<v8::Value>& args) {
897 content::RenderView* render_view = GetRenderView();
898 if (!render_view) return;
900 const InstantSuggestion& suggestion =
901 SearchBox::Get(render_view)->suggestion();
902 v8::Isolate* isolate = args.GetIsolate();
903 v8::Handle<v8::Object> data = v8::Object::New(isolate);
904 data->Set(v8::String::NewFromUtf8(isolate, "text"),
905 UTF16ToV8String(isolate, suggestion.text));
906 data->Set(v8::String::NewFromUtf8(isolate, "metadata"),
907 UTF8ToV8String(isolate, suggestion.metadata));
908 args.GetReturnValue().Set(data);
911 // static
912 void SearchBoxExtensionWrapper::GetThemeBackgroundInfo(
913 const v8::FunctionCallbackInfo<v8::Value>& args) {
914 content::RenderView* render_view = GetRenderView();
915 if (!render_view) return;
917 DVLOG(1) << render_view << " GetThemeBackgroundInfo";
918 const ThemeBackgroundInfo& theme_info =
919 SearchBox::Get(render_view)->GetThemeBackgroundInfo();
920 v8::Isolate* isolate = args.GetIsolate();
921 v8::Handle<v8::Object> info = v8::Object::New(isolate);
923 info->Set(v8::String::NewFromUtf8(isolate, "usingDefaultTheme"),
924 v8::Boolean::New(isolate, theme_info.using_default_theme));
926 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and
927 // B are between 0 and 255 inclusive, and A is a double between 0 and 1
928 // inclusive.
929 // This is the CSS "background-color" format.
930 // Value is always valid.
931 // TODO(jfweitz): Remove this field after GWS is modified to use the new
932 // backgroundColorRgba field.
933 info->Set(
934 v8::String::NewFromUtf8(isolate, "colorRgba"),
935 UTF8ToV8String(
936 isolate,
937 // Convert the alpha using DoubleToString because StringPrintf will
938 // use
939 // locale specific formatters (e.g., use , instead of . in German).
940 base::StringPrintf(
941 kCSSBackgroundColorFormat,
942 theme_info.background_color.r,
943 theme_info.background_color.g,
944 theme_info.background_color.b,
945 base::DoubleToString(theme_info.background_color.a / 255.0)
946 .c_str())));
948 // Theme color for background as an array with the RGBA components in order.
949 // Value is always valid.
950 info->Set(v8::String::NewFromUtf8(isolate, "backgroundColorRgba"),
951 internal::RGBAColorToArray(isolate, theme_info.background_color));
953 // Theme color for text as an array with the RGBA components in order.
954 // Value is always valid.
955 info->Set(v8::String::NewFromUtf8(isolate, "textColorRgba"),
956 internal::RGBAColorToArray(isolate, theme_info.text_color));
958 // Theme color for links as an array with the RGBA components in order.
959 // Value is always valid.
960 info->Set(v8::String::NewFromUtf8(isolate, "linkColorRgba"),
961 internal::RGBAColorToArray(isolate, theme_info.link_color));
963 // Theme color for light text as an array with the RGBA components in order.
964 // Value is always valid.
965 info->Set(v8::String::NewFromUtf8(isolate, "textColorLightRgba"),
966 internal::RGBAColorToArray(isolate, theme_info.text_color_light));
968 // Theme color for header as an array with the RGBA components in order.
969 // Value is always valid.
970 info->Set(v8::String::NewFromUtf8(isolate, "headerColorRgba"),
971 internal::RGBAColorToArray(isolate, theme_info.header_color));
973 // Theme color for section border as an array with the RGBA components in
974 // order. Value is always valid.
975 info->Set(
976 v8::String::NewFromUtf8(isolate, "sectionBorderColorRgba"),
977 internal::RGBAColorToArray(isolate, theme_info.section_border_color));
979 // The theme alternate logo value indicates a white logo when TRUE and a
980 // colorful one when FALSE.
981 info->Set(v8::String::NewFromUtf8(isolate, "alternateLogo"),
982 v8::Boolean::New(isolate, theme_info.logo_alternate));
984 // The theme background image url is of format kCSSBackgroundImageFormat
985 // where both instances of "%s" are replaced with the id that identifies the
986 // theme.
987 // This is the CSS "background-image" format.
988 // Value is only valid if there's a custom theme background image.
989 if (crx_file::id_util::IdIsValid(theme_info.theme_id)) {
990 info->Set(v8::String::NewFromUtf8(isolate, "imageUrl"),
991 UTF8ToV8String(isolate,
992 base::StringPrintf(kCSSBackgroundImageFormat,
993 theme_info.theme_id.c_str(),
994 theme_info.theme_id.c_str())));
996 // The theme background image horizontal alignment is one of "left",
997 // "right", "center".
998 // This is the horizontal component of the CSS "background-position" format.
999 // Value is only valid if |imageUrl| is not empty.
1000 std::string alignment = kCSSBackgroundPositionCenter;
1001 if (theme_info.image_horizontal_alignment ==
1002 THEME_BKGRND_IMAGE_ALIGN_LEFT) {
1003 alignment = kCSSBackgroundPositionLeft;
1004 } else if (theme_info.image_horizontal_alignment ==
1005 THEME_BKGRND_IMAGE_ALIGN_RIGHT) {
1006 alignment = kCSSBackgroundPositionRight;
1008 info->Set(v8::String::NewFromUtf8(isolate, "imageHorizontalAlignment"),
1009 UTF8ToV8String(isolate, alignment));
1011 // The theme background image vertical alignment is one of "top", "bottom",
1012 // "center".
1013 // This is the vertical component of the CSS "background-position" format.
1014 // Value is only valid if |image_url| is not empty.
1015 if (theme_info.image_vertical_alignment == THEME_BKGRND_IMAGE_ALIGN_TOP) {
1016 alignment = kCSSBackgroundPositionTop;
1017 } else if (theme_info.image_vertical_alignment ==
1018 THEME_BKGRND_IMAGE_ALIGN_BOTTOM) {
1019 alignment = kCSSBackgroundPositionBottom;
1020 } else {
1021 alignment = kCSSBackgroundPositionCenter;
1023 info->Set(v8::String::NewFromUtf8(isolate, "imageVerticalAlignment"),
1024 UTF8ToV8String(isolate, alignment));
1026 // The tiling of the theme background image is one of "no-repeat",
1027 // "repeat-x", "repeat-y", "repeat".
1028 // This is the CSS "background-repeat" format.
1029 // Value is only valid if |image_url| is not empty.
1030 std::string tiling = kCSSBackgroundRepeatNo;
1031 switch (theme_info.image_tiling) {
1032 case THEME_BKGRND_IMAGE_NO_REPEAT:
1033 tiling = kCSSBackgroundRepeatNo;
1034 break;
1035 case THEME_BKGRND_IMAGE_REPEAT_X:
1036 tiling = kCSSBackgroundRepeatX;
1037 break;
1038 case THEME_BKGRND_IMAGE_REPEAT_Y:
1039 tiling = kCSSBackgroundRepeatY;
1040 break;
1041 case THEME_BKGRND_IMAGE_REPEAT:
1042 tiling = kCSSBackgroundRepeat;
1043 break;
1045 info->Set(v8::String::NewFromUtf8(isolate, "imageTiling"),
1046 UTF8ToV8String(isolate, tiling));
1048 // The theme background image height is only valid if |imageUrl| is valid.
1049 info->Set(v8::String::NewFromUtf8(isolate, "imageHeight"),
1050 v8::Int32::New(isolate, theme_info.image_height));
1052 // The attribution URL is only valid if the theme has attribution logo.
1053 if (theme_info.has_attribution) {
1054 info->Set(
1055 v8::String::NewFromUtf8(isolate, "attributionUrl"),
1056 UTF8ToV8String(isolate,
1057 base::StringPrintf(kThemeAttributionFormat,
1058 theme_info.theme_id.c_str(),
1059 theme_info.theme_id.c_str())));
1063 args.GetReturnValue().Set(info);
1066 // static
1067 void SearchBoxExtensionWrapper::IsFocused(
1068 const v8::FunctionCallbackInfo<v8::Value>& args) {
1069 content::RenderView* render_view = GetRenderView();
1070 if (!render_view) return;
1072 bool is_focused = SearchBox::Get(render_view)->is_focused();
1073 DVLOG(1) << render_view << " IsFocused: " << is_focused;
1074 args.GetReturnValue().Set(is_focused);
1077 // static
1078 void SearchBoxExtensionWrapper::IsInputInProgress(
1079 const v8::FunctionCallbackInfo<v8::Value>& args) {
1080 content::RenderView* render_view = GetRenderView();
1081 if (!render_view) return;
1083 bool is_input_in_progress =
1084 SearchBox::Get(render_view)->is_input_in_progress();
1085 DVLOG(1) << render_view << " IsInputInProgress: " << is_input_in_progress;
1086 args.GetReturnValue().Set(is_input_in_progress);
1089 // static
1090 void SearchBoxExtensionWrapper::IsKeyCaptureEnabled(
1091 const v8::FunctionCallbackInfo<v8::Value>& args) {
1092 content::RenderView* render_view = GetRenderView();
1093 if (!render_view) return;
1095 args.GetReturnValue().Set(SearchBox::Get(render_view)->
1096 is_key_capture_enabled());
1099 // static
1100 void SearchBoxExtensionWrapper::LogEvent(
1101 const v8::FunctionCallbackInfo<v8::Value>& args) {
1102 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
1103 GURL(chrome::kChromeSearchMostVisitedUrl));
1104 if (!render_view) return;
1106 if (!args.Length() || !args[0]->IsNumber()) {
1107 ThrowInvalidParameters(args);
1108 return;
1111 DVLOG(1) << render_view << " LogEvent";
1113 if (args[0]->Uint32Value() <= NTP_EVENT_TYPE_LAST) {
1114 NTPLoggingEventType event =
1115 static_cast<NTPLoggingEventType>(args[0]->Uint32Value());
1116 SearchBox::Get(render_view)->LogEvent(event);
1120 // static
1121 void SearchBoxExtensionWrapper::LogMostVisitedImpression(
1122 const v8::FunctionCallbackInfo<v8::Value>& args) {
1123 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
1124 GURL(chrome::kChromeSearchMostVisitedUrl));
1125 if (!render_view) return;
1127 if (args.Length() < 2 || !args[0]->IsNumber() || args[1]->IsUndefined()) {
1128 ThrowInvalidParameters(args);
1129 return;
1132 DVLOG(1) << render_view << " LogMostVisitedImpression";
1134 SearchBox::Get(render_view)->LogMostVisitedImpression(
1135 args[0]->IntegerValue(), V8ValueToUTF16(args[1]));
1138 // static
1139 void SearchBoxExtensionWrapper::LogMostVisitedNavigation(
1140 const v8::FunctionCallbackInfo<v8::Value>& args) {
1141 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
1142 GURL(chrome::kChromeSearchMostVisitedUrl));
1143 if (!render_view) return;
1145 if (args.Length() < 2 || !args[0]->IsNumber() || args[1]->IsUndefined()) {
1146 ThrowInvalidParameters(args);
1147 return;
1150 DVLOG(1) << render_view << " LogMostVisitedNavigation";
1152 SearchBox::Get(render_view)->LogMostVisitedNavigation(
1153 args[0]->IntegerValue(), V8ValueToUTF16(args[1]));
1156 // static
1157 void SearchBoxExtensionWrapper::NavigateContentWindow(
1158 const v8::FunctionCallbackInfo<v8::Value>& args) {
1159 content::RenderView* render_view = GetRenderView();
1160 if (!render_view) return;
1162 if (!args.Length()) {
1163 ThrowInvalidParameters(args);
1164 return;
1167 GURL destination_url;
1168 bool is_most_visited_item_url = false;
1169 // Check if the url is a rid
1170 if (args[0]->IsNumber()) {
1171 InstantMostVisitedItem item;
1172 if (SearchBox::Get(render_view)->GetMostVisitedItemWithID(
1173 args[0]->IntegerValue(), &item)) {
1174 destination_url = item.url;
1175 is_most_visited_item_url = true;
1177 } else {
1178 // Resolve the URL
1179 const base::string16& possibly_relative_url = V8ValueToUTF16(args[0]);
1180 GURL current_url = GetCurrentURL(render_view);
1181 destination_url = internal::ResolveURL(current_url, possibly_relative_url);
1184 DVLOG(1) << render_view << " NavigateContentWindow: " << destination_url;
1186 // Navigate the main frame.
1187 if (destination_url.is_valid() &&
1188 !destination_url.SchemeIs(url::kJavaScriptScheme)) {
1189 WindowOpenDisposition disposition = CURRENT_TAB;
1190 if (args[1]->IsNumber()) {
1191 disposition = (WindowOpenDisposition) args[1]->Uint32Value();
1193 SearchBox::Get(render_view)->NavigateToURL(destination_url, disposition,
1194 is_most_visited_item_url);
1198 // static
1199 void SearchBoxExtensionWrapper::Paste(
1200 const v8::FunctionCallbackInfo<v8::Value>& args) {
1201 content::RenderView* render_view = GetRenderView();
1202 if (!render_view) return;
1204 base::string16 text;
1205 if (!args[0]->IsUndefined())
1206 text = V8ValueToUTF16(args[0]);
1208 DVLOG(1) << render_view << " Paste: " << text;
1209 SearchBox::Get(render_view)->Paste(text);
1212 // static
1213 void SearchBoxExtensionWrapper::StartCapturingKeyStrokes(
1214 const v8::FunctionCallbackInfo<v8::Value>& args) {
1215 content::RenderView* render_view = GetRenderView();
1216 if (!render_view) return;
1218 DVLOG(1) << render_view << " StartCapturingKeyStrokes";
1219 SearchBox::Get(render_view)->StartCapturingKeyStrokes();
1222 // static
1223 void SearchBoxExtensionWrapper::StopCapturingKeyStrokes(
1224 const v8::FunctionCallbackInfo<v8::Value>& args) {
1225 content::RenderView* render_view = GetRenderView();
1226 if (!render_view) return;
1228 DVLOG(1) << render_view << " StopCapturingKeyStrokes";
1229 SearchBox::Get(render_view)->StopCapturingKeyStrokes();
1232 // static
1233 void SearchBoxExtensionWrapper::SetVoiceSearchSupported(
1234 const v8::FunctionCallbackInfo<v8::Value>& args) {
1235 content::RenderView* render_view = GetRenderView();
1236 if (!render_view) {
1237 return;
1239 if (!args.Length()) {
1240 ThrowInvalidParameters(args);
1241 return;
1244 DVLOG(1) << render_view << " SetVoiceSearchSupported";
1245 SearchBox::Get(render_view)->SetVoiceSearchSupported(args[0]->BooleanValue());
1248 // static
1249 void SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions(
1250 const v8::FunctionCallbackInfo<v8::Value>& args) {
1251 content::RenderView* render_view = GetRenderView();
1252 if (!render_view) return;
1254 DVLOG(1) << render_view << " UndoAllMostVisitedDeletions";
1255 SearchBox::Get(render_view)->UndoAllMostVisitedDeletions();
1258 // static
1259 void SearchBoxExtensionWrapper::UndoMostVisitedDeletion(
1260 const v8::FunctionCallbackInfo<v8::Value>& args) {
1261 content::RenderView* render_view = GetRenderView();
1262 if (!render_view) {
1263 return;
1265 if (!args.Length()) {
1266 ThrowInvalidParameters(args);
1267 return;
1270 DVLOG(1) << render_view << " UndoMostVisitedDeletion";
1271 SearchBox::Get(render_view)
1272 ->UndoMostVisitedDeletion(args[0]->ToInteger()->Value());
1275 // static
1276 void SearchBoxExtensionWrapper::GetDisplayInstantResults(
1277 const v8::FunctionCallbackInfo<v8::Value>& args) {
1278 content::RenderView* render_view = GetRenderView();
1279 if (!render_view) return;
1281 bool display_instant_results =
1282 SearchBox::Get(render_view)->display_instant_results();
1283 DVLOG(1) << render_view << " GetDisplayInstantResults" <<
1284 display_instant_results;
1285 args.GetReturnValue().Set(display_instant_results);
1288 } // namespace extensions_v8