Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / chrome / renderer / searchbox / searchbox_extension.cc
blobc9e69b30b74a957147b5914147328ab05ef2d006
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"
31 #include "url/gurl.h"
32 #include "url/url_constants.h"
33 #include "v8/include/v8.h"
35 namespace {
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::Handle<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))
75 return false;
76 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp))
77 return true;
79 return StartsWithASCII(group_name, "Enabled", true);
82 // Converts string16 to V8 String.
83 v8::Handle<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,
88 s.size());
91 // Converts std::string to V8 String.
92 v8::Handle<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) {
106 if (!frame) return;
107 frame->executeScript(blink::WebScriptSource(script));
110 v8::Handle<v8::String> GenerateThumbnailURL(
111 v8::Isolate* isolate,
112 int render_view_id,
113 InstantRestrictedID most_visited_item_id) {
114 return UTF8ToV8String(
115 isolate,
116 base::StringPrintf(
117 "chrome-search://thumb/%d/%d", render_view_id, most_visited_item_id));
120 v8::Handle<v8::String> GenerateLargeIconURL(
121 v8::Isolate* isolate,
122 int render_view_id,
123 InstantRestrictedID most_visited_item_id) {
124 const int kIconSize = 96; // To support high DPI; on screen it's 48 dp.
125 return UTF8ToV8String(
126 isolate,
127 base::StringPrintf("chrome-search://large-icon/%d/%d/%d",
128 kIconSize, render_view_id, most_visited_item_id));
131 v8::Handle<v8::String> GenerateFallbackIconURL(
132 v8::Isolate* isolate,
133 int render_view_id,
134 InstantRestrictedID most_visited_item_id) {
135 return UTF8ToV8String(
136 isolate,
137 base::StringPrintf("chrome-search://fallback-icon/,,,,1/%d/%d",
138 render_view_id, most_visited_item_id));
141 // Populates a Javascript MostVisitedItem object from |mv_item|.
142 // NOTE: Includes "url", "title" and "domain" which are private data, so should
143 // not be returned to the Instant page. These should be erased before returning
144 // the object. See GetMostVisitedItemsWrapper() in searchbox_api.js.
145 v8::Handle<v8::Object> GenerateMostVisitedItem(
146 v8::Isolate* isolate,
147 int render_view_id,
148 InstantRestrictedID restricted_id,
149 const InstantMostVisitedItem& mv_item) {
150 // We set the "dir" attribute of the title, so that in RTL locales, a LTR
151 // title is rendered left-to-right and truncated from the right. For
152 // example, the title of http://msdn.microsoft.com/en-us/default.aspx is
153 // "MSDN: Microsoft developer network". In RTL locales, in the New Tab
154 // page, if the "dir" of this title is not specified, it takes Chrome UI's
155 // directionality. So the title will be truncated as "soft developer
156 // network". Setting the "dir" attribute as "ltr" renders the truncated
157 // title as "MSDN: Microsoft D...". As another example, the title of
158 // http://yahoo.com is "Yahoo!". In RTL locales, in the New Tab page, the
159 // title will be rendered as "!Yahoo" if its "dir" attribute is not set to
160 // "ltr".
161 std::string direction;
162 if (base::i18n::StringContainsStrongRTLChars(mv_item.title))
163 direction = kRTLHtmlTextDirection;
164 else
165 direction = kLTRHtmlTextDirection;
167 base::string16 title = mv_item.title;
168 if (title.empty())
169 title = base::UTF8ToUTF16(mv_item.url.spec());
171 v8::Handle<v8::Object> obj = v8::Object::New(isolate);
172 obj->Set(v8::String::NewFromUtf8(isolate, "renderViewId"),
173 v8::Int32::New(isolate, render_view_id));
174 obj->Set(v8::String::NewFromUtf8(isolate, "rid"),
175 v8::Int32::New(isolate, restricted_id));
176 obj->Set(v8::String::NewFromUtf8(isolate, "thumbnailUrl"),
177 GenerateThumbnailURL(isolate, render_view_id, restricted_id));
178 if (IsIconNTPEnabled()) {
179 // Update website http://www.chromium.org/embeddedsearch when we make this
180 // permanent.
181 obj->Set(v8::String::NewFromUtf8(isolate, "largeIconUrl"),
182 GenerateLargeIconURL(isolate, render_view_id, restricted_id));
183 obj->Set(v8::String::NewFromUtf8(isolate, "fallbackIconUrl"),
184 GenerateFallbackIconURL(isolate, render_view_id, restricted_id));
186 obj->Set(v8::String::NewFromUtf8(isolate, "title"),
187 UTF16ToV8String(isolate, title));
188 obj->Set(v8::String::NewFromUtf8(isolate, "domain"),
189 UTF8ToV8String(isolate, mv_item.url.host()));
190 obj->Set(v8::String::NewFromUtf8(isolate, "direction"),
191 UTF8ToV8String(isolate, direction));
192 obj->Set(v8::String::NewFromUtf8(isolate, "url"),
193 UTF8ToV8String(isolate, mv_item.url.spec()));
194 return obj;
197 // Returns the render view for the current JS context if it matches |origin|,
198 // otherwise returns NULL. Used to restrict methods that access suggestions and
199 // most visited data to pages with origin chrome-search://most-visited and
200 // chrome-search://suggestions.
201 content::RenderView* GetRenderViewWithCheckedOrigin(const GURL& origin) {
202 blink::WebLocalFrame* webframe =
203 blink::WebLocalFrame::frameForCurrentContext();
204 if (!webframe)
205 return NULL;
206 blink::WebView* webview = webframe->view();
207 if (!webview)
208 return NULL; // Can happen during closing.
209 content::RenderView* render_view = content::RenderView::FromWebView(webview);
210 if (!render_view)
211 return NULL;
213 GURL url(webframe->document().url());
214 if (url.GetOrigin() != origin.GetOrigin())
215 return NULL;
217 return render_view;
220 // Returns the current URL.
221 GURL GetCurrentURL(content::RenderView* render_view) {
222 blink::WebView* webview = render_view->GetWebView();
223 return webview ? GURL(webview->mainFrame()->document().url()) : GURL();
226 } // namespace
228 namespace internal { // for testing.
230 // Returns an array with the RGBA color components.
231 v8::Handle<v8::Value> RGBAColorToArray(v8::Isolate* isolate,
232 const RGBAColor& color) {
233 v8::Handle<v8::Array> color_array = v8::Array::New(isolate, 4);
234 color_array->Set(0, v8::Int32::New(isolate, color.r));
235 color_array->Set(1, v8::Int32::New(isolate, color.g));
236 color_array->Set(2, v8::Int32::New(isolate, color.b));
237 color_array->Set(3, v8::Int32::New(isolate, color.a));
238 return color_array;
241 // Resolves a possibly relative URL using the current URL.
242 GURL ResolveURL(const GURL& current_url,
243 const base::string16& possibly_relative_url) {
244 if (current_url.is_valid() && !possibly_relative_url.empty())
245 return current_url.Resolve(possibly_relative_url);
246 return GURL(possibly_relative_url);
249 } // namespace internal
251 namespace extensions_v8 {
253 static const char kSearchBoxExtensionName[] = "v8/EmbeddedSearch";
255 // We first send this script down to determine if the page supports instant.
256 static const char kSupportsInstantScript[] =
257 "if (window.chrome &&"
258 " window.chrome.embeddedSearch &&"
259 " window.chrome.embeddedSearch.searchBox &&"
260 " window.chrome.embeddedSearch.searchBox.onsubmit &&"
261 " typeof window.chrome.embeddedSearch.searchBox.onsubmit =="
262 " 'function') {"
263 " true;"
264 "} else {"
265 " false;"
266 "}";
268 static const char kDispatchChromeIdentityCheckResult[] =
269 "if (window.chrome &&"
270 " window.chrome.embeddedSearch &&"
271 " window.chrome.embeddedSearch.newTabPage &&"
272 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone &&"
273 " typeof window.chrome.embeddedSearch.newTabPage"
274 " .onsignedincheckdone === 'function') {"
275 " window.chrome.embeddedSearch.newTabPage.onsignedincheckdone(%s, %s);"
276 " true;"
277 "}";
279 static const char kDispatchFocusChangedScript[] =
280 "if (window.chrome &&"
281 " window.chrome.embeddedSearch &&"
282 " window.chrome.embeddedSearch.searchBox &&"
283 " window.chrome.embeddedSearch.searchBox.onfocuschange &&"
284 " typeof window.chrome.embeddedSearch.searchBox.onfocuschange =="
285 " 'function') {"
286 " window.chrome.embeddedSearch.searchBox.onfocuschange();"
287 " true;"
288 "}";
290 static const char kDispatchHistorySyncCheckResult[] =
291 "if (window.chrome &&"
292 " window.chrome.embeddedSearch &&"
293 " window.chrome.embeddedSearch.newTabPage &&"
294 " window.chrome.embeddedSearch.newTabPage.onhistorysynccheckdone &&"
295 " typeof window.chrome.embeddedSearch.newTabPage"
296 " .onhistorysynccheckdone === 'function') {"
297 " window.chrome.embeddedSearch.newTabPage.onhistorysynccheckdone(%s);"
298 " true;"
299 "}";
301 static const char kDispatchInputCancelScript[] =
302 "if (window.chrome &&"
303 " window.chrome.embeddedSearch &&"
304 " window.chrome.embeddedSearch.newTabPage &&"
305 " window.chrome.embeddedSearch.newTabPage.oninputcancel &&"
306 " typeof window.chrome.embeddedSearch.newTabPage.oninputcancel =="
307 " 'function') {"
308 " window.chrome.embeddedSearch.newTabPage.oninputcancel();"
309 " true;"
310 "}";
312 static const char kDispatchInputStartScript[] =
313 "if (window.chrome &&"
314 " window.chrome.embeddedSearch &&"
315 " window.chrome.embeddedSearch.newTabPage &&"
316 " window.chrome.embeddedSearch.newTabPage.oninputstart &&"
317 " typeof window.chrome.embeddedSearch.newTabPage.oninputstart =="
318 " 'function') {"
319 " window.chrome.embeddedSearch.newTabPage.oninputstart();"
320 " true;"
321 "}";
323 static const char kDispatchKeyCaptureChangeScript[] =
324 "if (window.chrome &&"
325 " window.chrome.embeddedSearch &&"
326 " window.chrome.embeddedSearch.searchBox &&"
327 " window.chrome.embeddedSearch.searchBox.onkeycapturechange &&"
328 " typeof window.chrome.embeddedSearch.searchBox.onkeycapturechange =="
329 " 'function') {"
330 " window.chrome.embeddedSearch.searchBox.onkeycapturechange();"
331 " true;"
332 "}";
334 static const char kDispatchMarginChangeEventScript[] =
335 "if (window.chrome &&"
336 " window.chrome.embeddedSearch &&"
337 " window.chrome.embeddedSearch.searchBox &&"
338 " window.chrome.embeddedSearch.searchBox.onmarginchange &&"
339 " typeof window.chrome.embeddedSearch.searchBox.onmarginchange =="
340 " 'function') {"
341 " window.chrome.embeddedSearch.searchBox.onmarginchange();"
342 " true;"
343 "}";
345 static const char kDispatchMostVisitedChangedScript[] =
346 "if (window.chrome &&"
347 " window.chrome.embeddedSearch &&"
348 " window.chrome.embeddedSearch.newTabPage &&"
349 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange &&"
350 " typeof window.chrome.embeddedSearch.newTabPage.onmostvisitedchange =="
351 " 'function') {"
352 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange();"
353 " true;"
354 "}";
356 static const char kDispatchSubmitEventScript[] =
357 "if (window.chrome &&"
358 " window.chrome.embeddedSearch &&"
359 " window.chrome.embeddedSearch.searchBox &&"
360 " window.chrome.embeddedSearch.searchBox.onsubmit &&"
361 " typeof window.chrome.embeddedSearch.searchBox.onsubmit =="
362 " 'function') {"
363 " window.chrome.embeddedSearch.searchBox.onsubmit();"
364 " true;"
365 "}";
367 static const char kDispatchSuggestionChangeEventScript[] =
368 "if (window.chrome &&"
369 " window.chrome.embeddedSearch &&"
370 " window.chrome.embeddedSearch.searchBox &&"
371 " window.chrome.embeddedSearch.searchBox.onsuggestionchange &&"
372 " typeof window.chrome.embeddedSearch.searchBox.onsuggestionchange =="
373 " 'function') {"
374 " window.chrome.embeddedSearch.searchBox.onsuggestionchange();"
375 " true;"
376 "}";
378 static const char kDispatchThemeChangeEventScript[] =
379 "if (window.chrome &&"
380 " window.chrome.embeddedSearch &&"
381 " window.chrome.embeddedSearch.newTabPage &&"
382 " window.chrome.embeddedSearch.newTabPage.onthemechange &&"
383 " typeof window.chrome.embeddedSearch.newTabPage.onthemechange =="
384 " 'function') {"
385 " window.chrome.embeddedSearch.newTabPage.onthemechange();"
386 " true;"
387 "}";
389 static const char kDispatchToggleVoiceSearchScript[] =
390 "if (window.chrome &&"
391 " window.chrome.embeddedSearch &&"
392 " window.chrome.embeddedSearch.searchBox &&"
393 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch &&"
394 " typeof window.chrome.embeddedSearch.searchBox.ontogglevoicesearch =="
395 " 'function') {"
396 " window.chrome.embeddedSearch.searchBox.ontogglevoicesearch();"
397 " true;"
398 "}";
400 // ----------------------------------------------------------------------------
402 class SearchBoxExtensionWrapper : public v8::Extension {
403 public:
404 explicit SearchBoxExtensionWrapper(const base::StringPiece& code);
406 // Allows v8's javascript code to call the native functions defined
407 // in this class for window.chrome.
408 v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(
409 v8::Isolate*,
410 v8::Handle<v8::String> name) override;
412 // Helper function to find the RenderView. May return NULL.
413 static content::RenderView* GetRenderView();
415 // Sends a Chrome identity check to the browser.
416 static void CheckIsUserSignedInToChromeAs(
417 const v8::FunctionCallbackInfo<v8::Value>& args);
419 // Checks whether the user sync his history.
420 static void CheckIsUserSyncingHistory(
421 const v8::FunctionCallbackInfo<v8::Value>& args);
423 // Deletes a Most Visited item.
424 static void DeleteMostVisitedItem(
425 const v8::FunctionCallbackInfo<v8::Value>& args);
427 // Focuses the omnibox.
428 static void Focus(const v8::FunctionCallbackInfo<v8::Value>& args);
430 // Gets whether or not the app launcher is enabled.
431 static void GetAppLauncherEnabled(
432 const v8::FunctionCallbackInfo<v8::Value>& args);
434 // Gets the desired navigation behavior from a click event.
435 static void GetDispositionFromClick(
436 const v8::FunctionCallbackInfo<v8::Value>& args);
438 // Gets Most Visited Items.
439 static void GetMostVisitedItems(
440 const v8::FunctionCallbackInfo<v8::Value>& args);
442 // Gets the raw data for a most visited item including its raw URL.
443 // GetRenderViewWithCheckedOrigin() enforces that only code in the origin
444 // chrome-search://most-visited can call this function.
445 static void GetMostVisitedItemData(
446 const v8::FunctionCallbackInfo<v8::Value>& args);
448 // Gets the submitted value of the user's search query.
449 static void GetQuery(const v8::FunctionCallbackInfo<v8::Value>& args);
451 // Returns true if the Searchbox itself is oriented right-to-left.
452 static void GetRightToLeft(const v8::FunctionCallbackInfo<v8::Value>& args);
454 // Gets the Embedded Search request params. Used for logging purposes.
455 static void GetSearchRequestParams(
456 const v8::FunctionCallbackInfo<v8::Value>& args);
458 // Gets the start-edge margin to use with extended Instant.
459 static void GetStartMargin(const v8::FunctionCallbackInfo<v8::Value>& args);
461 // Gets the current top suggestion to prefetch search results.
462 static void GetSuggestionToPrefetch(
463 const v8::FunctionCallbackInfo<v8::Value>& args);
465 // Gets the background info of the theme currently adopted by browser.
466 // Call only when overlay is showing NTP page.
467 static void GetThemeBackgroundInfo(
468 const v8::FunctionCallbackInfo<v8::Value>& args);
470 // Gets whether the omnibox has focus or not.
471 static void IsFocused(const v8::FunctionCallbackInfo<v8::Value>& args);
473 // Gets whether user input is in progress.
474 static void IsInputInProgress(
475 const v8::FunctionCallbackInfo<v8::Value>& args);
477 // Gets whether the browser is capturing key strokes.
478 static void IsKeyCaptureEnabled(
479 const v8::FunctionCallbackInfo<v8::Value>& args);
481 // Logs information from the iframes/titles on the NTP.
482 static void LogEvent(const v8::FunctionCallbackInfo<v8::Value>& args);
484 // Logs an impression on one of the Most Visited tile on the NTP.
485 static void LogMostVisitedImpression(
486 const v8::FunctionCallbackInfo<v8::Value>& args);
488 // Logs a navigation on one of the Most Visited tile on the NTP.
489 static void LogMostVisitedNavigation(
490 const v8::FunctionCallbackInfo<v8::Value>& args);
492 // Navigates the window to a URL represented by either a URL string or a
493 // restricted ID.
494 static void NavigateContentWindow(
495 const v8::FunctionCallbackInfo<v8::Value>& args);
497 // Pastes provided value or clipboard's content into the omnibox.
498 static void Paste(const v8::FunctionCallbackInfo<v8::Value>& args);
500 // Indicates whether the page supports voice search.
501 static void SetVoiceSearchSupported(
502 const v8::FunctionCallbackInfo<v8::Value>& args);
504 // Start capturing user key strokes.
505 static void StartCapturingKeyStrokes(
506 const v8::FunctionCallbackInfo<v8::Value>& args);
508 // Stop capturing user key strokes.
509 static void StopCapturingKeyStrokes(
510 const v8::FunctionCallbackInfo<v8::Value>& args);
512 // Undoes the deletion of all Most Visited itens.
513 static void UndoAllMostVisitedDeletions(
514 const v8::FunctionCallbackInfo<v8::Value>& args);
516 // Undoes the deletion of a Most Visited item.
517 static void UndoMostVisitedDeletion(
518 const v8::FunctionCallbackInfo<v8::Value>& args);
520 // Indicates whether the page supports Instant.
521 static void GetDisplayInstantResults(
522 const v8::FunctionCallbackInfo<v8::Value>& args);
524 private:
525 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper);
528 // static
529 v8::Extension* SearchBoxExtension::Get() {
530 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance().
531 GetRawDataResource(IDR_SEARCHBOX_API));
534 // static
535 bool SearchBoxExtension::PageSupportsInstant(blink::WebFrame* frame) {
536 if (!frame) return false;
537 v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
538 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue(
539 blink::WebScriptSource(kSupportsInstantScript));
540 return !v.IsEmpty() && v->BooleanValue();
543 // static
544 void SearchBoxExtension::DispatchChromeIdentityCheckResult(
545 blink::WebFrame* frame,
546 const base::string16& identity,
547 bool identity_match) {
548 std::string escaped_identity = base::GetQuotedJSONString(identity);
549 blink::WebString script(base::UTF8ToUTF16(base::StringPrintf(
550 kDispatchChromeIdentityCheckResult,
551 escaped_identity.c_str(),
552 identity_match ? "true" : "false")));
553 Dispatch(frame, script);
556 // static
557 void SearchBoxExtension::DispatchFocusChange(blink::WebFrame* frame) {
558 Dispatch(frame, kDispatchFocusChangedScript);
561 // static
562 void SearchBoxExtension::DispatchHistorySyncCheckResult(
563 blink::WebFrame* frame,
564 bool sync_history) {
565 blink::WebString script(base::UTF8ToUTF16(base::StringPrintf(
566 kDispatchHistorySyncCheckResult,
567 sync_history ? "true" : "false")));
568 Dispatch(frame, script);
571 // static
572 void SearchBoxExtension::DispatchInputCancel(blink::WebFrame* frame) {
573 Dispatch(frame, kDispatchInputCancelScript);
576 // static
577 void SearchBoxExtension::DispatchInputStart(blink::WebFrame* frame) {
578 Dispatch(frame, kDispatchInputStartScript);
581 // static
582 void SearchBoxExtension::DispatchKeyCaptureChange(blink::WebFrame* frame) {
583 Dispatch(frame, kDispatchKeyCaptureChangeScript);
586 // static
587 void SearchBoxExtension::DispatchMarginChange(blink::WebFrame* frame) {
588 Dispatch(frame, kDispatchMarginChangeEventScript);
591 // static
592 void SearchBoxExtension::DispatchMostVisitedChanged(
593 blink::WebFrame* frame) {
594 Dispatch(frame, kDispatchMostVisitedChangedScript);
597 // static
598 void SearchBoxExtension::DispatchSubmit(blink::WebFrame* frame) {
599 Dispatch(frame, kDispatchSubmitEventScript);
602 // static
603 void SearchBoxExtension::DispatchSuggestionChange(blink::WebFrame* frame) {
604 Dispatch(frame, kDispatchSuggestionChangeEventScript);
607 // static
608 void SearchBoxExtension::DispatchThemeChange(blink::WebFrame* frame) {
609 Dispatch(frame, kDispatchThemeChangeEventScript);
612 // static
613 void SearchBoxExtension::DispatchToggleVoiceSearch(
614 blink::WebFrame* frame) {
615 Dispatch(frame, kDispatchToggleVoiceSearchScript);
618 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper(
619 const base::StringPiece& code)
620 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) {
623 v8::Handle<v8::FunctionTemplate>
624 SearchBoxExtensionWrapper::GetNativeFunctionTemplate(
625 v8::Isolate* isolate,
626 v8::Handle<v8::String> name) {
627 if (name->Equals(
628 v8::String::NewFromUtf8(isolate, "CheckIsUserSignedInToChromeAs")))
629 return v8::FunctionTemplate::New(isolate, CheckIsUserSignedInToChromeAs);
630 if (name->Equals(
631 v8::String::NewFromUtf8(isolate, "CheckIsUserSyncingHistory")))
632 return v8::FunctionTemplate::New(isolate, CheckIsUserSyncingHistory);
633 if (name->Equals(v8::String::NewFromUtf8(isolate, "DeleteMostVisitedItem")))
634 return v8::FunctionTemplate::New(isolate, DeleteMostVisitedItem);
635 if (name->Equals(v8::String::NewFromUtf8(isolate, "Focus")))
636 return v8::FunctionTemplate::New(isolate, Focus);
637 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetAppLauncherEnabled")))
638 return v8::FunctionTemplate::New(isolate, GetAppLauncherEnabled);
639 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetDispositionFromClick")))
640 return v8::FunctionTemplate::New(isolate, GetDispositionFromClick);
641 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetMostVisitedItems")))
642 return v8::FunctionTemplate::New(isolate, GetMostVisitedItems);
643 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetMostVisitedItemData")))
644 return v8::FunctionTemplate::New(isolate, GetMostVisitedItemData);
645 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetQuery")))
646 return v8::FunctionTemplate::New(isolate, GetQuery);
647 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetRightToLeft")))
648 return v8::FunctionTemplate::New(isolate, GetRightToLeft);
649 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetSearchRequestParams")))
650 return v8::FunctionTemplate::New(isolate, GetSearchRequestParams);
651 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetStartMargin")))
652 return v8::FunctionTemplate::New(isolate, GetStartMargin);
653 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetSuggestionToPrefetch")))
654 return v8::FunctionTemplate::New(isolate, GetSuggestionToPrefetch);
655 if (name->Equals(v8::String::NewFromUtf8(isolate, "GetThemeBackgroundInfo")))
656 return v8::FunctionTemplate::New(isolate, GetThemeBackgroundInfo);
657 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsFocused")))
658 return v8::FunctionTemplate::New(isolate, IsFocused);
659 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsInputInProgress")))
660 return v8::FunctionTemplate::New(isolate, IsInputInProgress);
661 if (name->Equals(v8::String::NewFromUtf8(isolate, "IsKeyCaptureEnabled")))
662 return v8::FunctionTemplate::New(isolate, IsKeyCaptureEnabled);
663 if (name->Equals(v8::String::NewFromUtf8(isolate, "LogEvent")))
664 return v8::FunctionTemplate::New(isolate, LogEvent);
665 if (name->Equals(
666 v8::String::NewFromUtf8(isolate, "LogMostVisitedImpression"))) {
667 return v8::FunctionTemplate::New(isolate, LogMostVisitedImpression);
669 if (name->Equals(
670 v8::String::NewFromUtf8(isolate, "LogMostVisitedNavigation"))) {
671 return v8::FunctionTemplate::New(isolate, LogMostVisitedNavigation);
673 if (name->Equals(v8::String::NewFromUtf8(isolate, "NavigateContentWindow")))
674 return v8::FunctionTemplate::New(isolate, NavigateContentWindow);
675 if (name->Equals(v8::String::NewFromUtf8(isolate, "Paste")))
676 return v8::FunctionTemplate::New(isolate, Paste);
677 if (name->Equals(v8::String::NewFromUtf8(isolate, "SetVoiceSearchSupported")))
678 return v8::FunctionTemplate::New(isolate, SetVoiceSearchSupported);
679 if (name->Equals(
680 v8::String::NewFromUtf8(isolate, "StartCapturingKeyStrokes")))
681 return v8::FunctionTemplate::New(isolate, StartCapturingKeyStrokes);
682 if (name->Equals(v8::String::NewFromUtf8(isolate, "StopCapturingKeyStrokes")))
683 return v8::FunctionTemplate::New(isolate, StopCapturingKeyStrokes);
684 if (name->Equals(
685 v8::String::NewFromUtf8(isolate, "UndoAllMostVisitedDeletions")))
686 return v8::FunctionTemplate::New(isolate, UndoAllMostVisitedDeletions);
687 if (name->Equals(v8::String::NewFromUtf8(isolate, "UndoMostVisitedDeletion")))
688 return v8::FunctionTemplate::New(isolate, UndoMostVisitedDeletion);
689 if (name->Equals(
690 v8::String::NewFromUtf8(isolate, "GetDisplayInstantResults")))
691 return v8::FunctionTemplate::New(isolate, GetDisplayInstantResults);
692 return v8::Handle<v8::FunctionTemplate>();
695 // static
696 content::RenderView* SearchBoxExtensionWrapper::GetRenderView() {
697 blink::WebLocalFrame* webframe =
698 blink::WebLocalFrame::frameForCurrentContext();
699 if (!webframe) return NULL;
701 blink::WebView* webview = webframe->view();
702 if (!webview) return NULL; // can happen during closing
704 return content::RenderView::FromWebView(webview);
707 // static
708 void SearchBoxExtensionWrapper::CheckIsUserSignedInToChromeAs(
709 const v8::FunctionCallbackInfo<v8::Value>& args) {
710 content::RenderView* render_view = GetRenderView();
711 if (!render_view) return;
713 if (!args.Length() || args[0]->IsUndefined()) {
714 ThrowInvalidParameters(args);
715 return;
718 DVLOG(1) << render_view << " CheckIsUserSignedInToChromeAs";
720 SearchBox::Get(render_view)->CheckIsUserSignedInToChromeAs(
721 V8ValueToUTF16(args[0]));
724 // static
725 void SearchBoxExtensionWrapper::CheckIsUserSyncingHistory(
726 const v8::FunctionCallbackInfo<v8::Value>& args) {
727 content::RenderView* render_view = GetRenderView();
728 if (!render_view) return;
730 DVLOG(1) << render_view << " CheckIsUserSyncingHistory";
731 SearchBox::Get(render_view)->CheckIsUserSyncingHistory();
734 // static
735 void SearchBoxExtensionWrapper::DeleteMostVisitedItem(
736 const v8::FunctionCallbackInfo<v8::Value>& args) {
737 content::RenderView* render_view = GetRenderView();
738 if (!render_view) return;
740 if (!args.Length()) {
741 ThrowInvalidParameters(args);
742 return;
745 DVLOG(1) << render_view
746 << " DeleteMostVisitedItem: " << args[0]->ToInteger()->Value();
747 SearchBox::Get(render_view)->
748 DeleteMostVisitedItem(args[0]->ToInteger()->Value());
751 // static
752 void SearchBoxExtensionWrapper::Focus(
753 const v8::FunctionCallbackInfo<v8::Value>& args) {
754 content::RenderView* render_view = GetRenderView();
755 if (!render_view) return;
757 DVLOG(1) << render_view << " Focus";
758 SearchBox::Get(render_view)->Focus();
761 // static
762 void SearchBoxExtensionWrapper::GetAppLauncherEnabled(
763 const v8::FunctionCallbackInfo<v8::Value>& args) {
764 content::RenderView* render_view = GetRenderView();
765 if (!render_view) return;
767 args.GetReturnValue().Set(
768 SearchBox::Get(render_view)->app_launcher_enabled());
771 // static
772 void SearchBoxExtensionWrapper::GetDispositionFromClick(
773 const v8::FunctionCallbackInfo<v8::Value>& args) {
774 content::RenderView* render_view = GetRenderView();
775 if (!render_view) return;
777 if (args.Length() != 5) {
778 ThrowInvalidParameters(args);
779 return;
782 bool middle_button = args[0]->BooleanValue();
783 bool alt_key = args[1]->BooleanValue();
784 bool ctrl_key = args[2]->BooleanValue();
785 bool meta_key = args[3]->BooleanValue();
786 bool shift_key = args[4]->BooleanValue();
788 WindowOpenDisposition disposition = ui::DispositionFromClick(middle_button,
789 alt_key,
790 ctrl_key,
791 meta_key,
792 shift_key);
793 v8::Isolate* isolate = args.GetIsolate();
794 args.GetReturnValue().Set(v8::Int32::New(isolate, disposition));
797 // static
798 void SearchBoxExtensionWrapper::GetMostVisitedItems(
799 const v8::FunctionCallbackInfo<v8::Value>& args) {
800 content::RenderView* render_view = GetRenderView();
801 if (!render_view)
802 return;
803 DVLOG(1) << render_view << " GetMostVisitedItems";
805 const SearchBox* search_box = SearchBox::Get(render_view);
807 std::vector<InstantMostVisitedItemIDPair> instant_mv_items;
808 search_box->GetMostVisitedItems(&instant_mv_items);
809 v8::Isolate* isolate = args.GetIsolate();
810 v8::Handle<v8::Array> v8_mv_items =
811 v8::Array::New(isolate, instant_mv_items.size());
812 for (size_t i = 0; i < instant_mv_items.size(); ++i) {
813 v8_mv_items->Set(i,
814 GenerateMostVisitedItem(isolate,
815 render_view->GetRoutingID(),
816 instant_mv_items[i].first,
817 instant_mv_items[i].second));
819 args.GetReturnValue().Set(v8_mv_items);
822 // static
823 void SearchBoxExtensionWrapper::GetMostVisitedItemData(
824 const v8::FunctionCallbackInfo<v8::Value>& args) {
825 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
826 GURL(chrome::kChromeSearchMostVisitedUrl));
827 if (!render_view) return;
829 // Need an rid argument.
830 if (!args.Length() || !args[0]->IsNumber()) {
831 ThrowInvalidParameters(args);
832 return;
835 DVLOG(1) << render_view << " GetMostVisitedItem";
836 InstantRestrictedID restricted_id = args[0]->IntegerValue();
837 InstantMostVisitedItem mv_item;
838 if (!SearchBox::Get(render_view)->GetMostVisitedItemWithID(
839 restricted_id, &mv_item)) {
840 return;
842 v8::Isolate* isolate = args.GetIsolate();
843 args.GetReturnValue().Set(GenerateMostVisitedItem(
844 isolate, render_view->GetRoutingID(), restricted_id, mv_item));
847 // static
848 void SearchBoxExtensionWrapper::GetQuery(
849 const v8::FunctionCallbackInfo<v8::Value>& args) {
850 content::RenderView* render_view = GetRenderView();
851 if (!render_view) return;
852 const base::string16& query = SearchBox::Get(render_view)->query();
853 DVLOG(1) << render_view << " GetQuery: '" << query << "'";
854 v8::Isolate* isolate = args.GetIsolate();
855 args.GetReturnValue().Set(UTF16ToV8String(isolate, query));
858 // static
859 void SearchBoxExtensionWrapper::GetRightToLeft(
860 const v8::FunctionCallbackInfo<v8::Value>& args) {
861 args.GetReturnValue().Set(base::i18n::IsRTL());
864 // static
865 void SearchBoxExtensionWrapper::GetSearchRequestParams(
866 const v8::FunctionCallbackInfo<v8::Value>& args) {
867 content::RenderView* render_view = GetRenderView();
868 if (!render_view) return;
870 const EmbeddedSearchRequestParams& params =
871 SearchBox::Get(render_view)->GetEmbeddedSearchRequestParams();
872 v8::Isolate* isolate = args.GetIsolate();
873 v8::Handle<v8::Object> data = v8::Object::New(isolate);
874 if (!params.search_query.empty()) {
875 data->Set(v8::String::NewFromUtf8(isolate, kSearchQueryKey),
876 UTF16ToV8String(isolate, params.search_query));
878 if (!params.original_query.empty()) {
879 data->Set(v8::String::NewFromUtf8(isolate, kOriginalQueryKey),
880 UTF16ToV8String(isolate, params.original_query));
882 if (!params.rlz_parameter_value.empty()) {
883 data->Set(v8::String::NewFromUtf8(isolate, kRLZParameterKey),
884 UTF16ToV8String(isolate, params.rlz_parameter_value));
886 if (!params.input_encoding.empty()) {
887 data->Set(v8::String::NewFromUtf8(isolate, kInputEncodingKey),
888 UTF16ToV8String(isolate, params.input_encoding));
890 if (!params.assisted_query_stats.empty()) {
891 data->Set(v8::String::NewFromUtf8(isolate, kAssistedQueryStatsKey),
892 UTF16ToV8String(isolate, params.assisted_query_stats));
894 args.GetReturnValue().Set(data);
897 // static
898 void SearchBoxExtensionWrapper::GetStartMargin(
899 const v8::FunctionCallbackInfo<v8::Value>& args) {
900 content::RenderView* render_view = GetRenderView();
901 if (!render_view) return;
902 args.GetReturnValue().Set(static_cast<int32_t>(
903 SearchBox::Get(render_view)->start_margin()));
906 // static
907 void SearchBoxExtensionWrapper::GetSuggestionToPrefetch(
908 const v8::FunctionCallbackInfo<v8::Value>& args) {
909 content::RenderView* render_view = GetRenderView();
910 if (!render_view) return;
912 const InstantSuggestion& suggestion =
913 SearchBox::Get(render_view)->suggestion();
914 v8::Isolate* isolate = args.GetIsolate();
915 v8::Handle<v8::Object> data = v8::Object::New(isolate);
916 data->Set(v8::String::NewFromUtf8(isolate, "text"),
917 UTF16ToV8String(isolate, suggestion.text));
918 data->Set(v8::String::NewFromUtf8(isolate, "metadata"),
919 UTF8ToV8String(isolate, suggestion.metadata));
920 args.GetReturnValue().Set(data);
923 // static
924 void SearchBoxExtensionWrapper::GetThemeBackgroundInfo(
925 const v8::FunctionCallbackInfo<v8::Value>& args) {
926 content::RenderView* render_view = GetRenderView();
927 if (!render_view) return;
929 DVLOG(1) << render_view << " GetThemeBackgroundInfo";
930 const ThemeBackgroundInfo& theme_info =
931 SearchBox::Get(render_view)->GetThemeBackgroundInfo();
932 v8::Isolate* isolate = args.GetIsolate();
933 v8::Handle<v8::Object> info = v8::Object::New(isolate);
935 info->Set(v8::String::NewFromUtf8(isolate, "usingDefaultTheme"),
936 v8::Boolean::New(isolate, theme_info.using_default_theme));
938 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and
939 // B are between 0 and 255 inclusive, and A is a double between 0 and 1
940 // inclusive.
941 // This is the CSS "background-color" format.
942 // Value is always valid.
943 // TODO(jfweitz): Remove this field after GWS is modified to use the new
944 // backgroundColorRgba field.
945 info->Set(
946 v8::String::NewFromUtf8(isolate, "colorRgba"),
947 UTF8ToV8String(
948 isolate,
949 // Convert the alpha using DoubleToString because StringPrintf will
950 // use
951 // locale specific formatters (e.g., use , instead of . in German).
952 base::StringPrintf(
953 kCSSBackgroundColorFormat,
954 theme_info.background_color.r,
955 theme_info.background_color.g,
956 theme_info.background_color.b,
957 base::DoubleToString(theme_info.background_color.a / 255.0)
958 .c_str())));
960 // Theme color for background as an array with the RGBA components in order.
961 // Value is always valid.
962 info->Set(v8::String::NewFromUtf8(isolate, "backgroundColorRgba"),
963 internal::RGBAColorToArray(isolate, theme_info.background_color));
965 // Theme color for text as an array with the RGBA components in order.
966 // Value is always valid.
967 info->Set(v8::String::NewFromUtf8(isolate, "textColorRgba"),
968 internal::RGBAColorToArray(isolate, theme_info.text_color));
970 // Theme color for links as an array with the RGBA components in order.
971 // Value is always valid.
972 info->Set(v8::String::NewFromUtf8(isolate, "linkColorRgba"),
973 internal::RGBAColorToArray(isolate, theme_info.link_color));
975 // Theme color for light text as an array with the RGBA components in order.
976 // Value is always valid.
977 info->Set(v8::String::NewFromUtf8(isolate, "textColorLightRgba"),
978 internal::RGBAColorToArray(isolate, theme_info.text_color_light));
980 // Theme color for header as an array with the RGBA components in order.
981 // Value is always valid.
982 info->Set(v8::String::NewFromUtf8(isolate, "headerColorRgba"),
983 internal::RGBAColorToArray(isolate, theme_info.header_color));
985 // Theme color for section border as an array with the RGBA components in
986 // order. Value is always valid.
987 info->Set(
988 v8::String::NewFromUtf8(isolate, "sectionBorderColorRgba"),
989 internal::RGBAColorToArray(isolate, theme_info.section_border_color));
991 // The theme alternate logo value indicates a white logo when TRUE and a
992 // colorful one when FALSE.
993 info->Set(v8::String::NewFromUtf8(isolate, "alternateLogo"),
994 v8::Boolean::New(isolate, theme_info.logo_alternate));
996 // The theme background image url is of format kCSSBackgroundImageFormat
997 // where both instances of "%s" are replaced with the id that identifies the
998 // theme.
999 // This is the CSS "background-image" format.
1000 // Value is only valid if there's a custom theme background image.
1001 if (crx_file::id_util::IdIsValid(theme_info.theme_id)) {
1002 info->Set(v8::String::NewFromUtf8(isolate, "imageUrl"),
1003 UTF8ToV8String(isolate,
1004 base::StringPrintf(kCSSBackgroundImageFormat,
1005 theme_info.theme_id.c_str(),
1006 theme_info.theme_id.c_str())));
1008 // The theme background image horizontal alignment is one of "left",
1009 // "right", "center".
1010 // This is the horizontal component of the CSS "background-position" format.
1011 // Value is only valid if |imageUrl| is not empty.
1012 std::string alignment = kCSSBackgroundPositionCenter;
1013 if (theme_info.image_horizontal_alignment ==
1014 THEME_BKGRND_IMAGE_ALIGN_LEFT) {
1015 alignment = kCSSBackgroundPositionLeft;
1016 } else if (theme_info.image_horizontal_alignment ==
1017 THEME_BKGRND_IMAGE_ALIGN_RIGHT) {
1018 alignment = kCSSBackgroundPositionRight;
1020 info->Set(v8::String::NewFromUtf8(isolate, "imageHorizontalAlignment"),
1021 UTF8ToV8String(isolate, alignment));
1023 // The theme background image vertical alignment is one of "top", "bottom",
1024 // "center".
1025 // This is the vertical component of the CSS "background-position" format.
1026 // Value is only valid if |image_url| is not empty.
1027 if (theme_info.image_vertical_alignment == THEME_BKGRND_IMAGE_ALIGN_TOP) {
1028 alignment = kCSSBackgroundPositionTop;
1029 } else if (theme_info.image_vertical_alignment ==
1030 THEME_BKGRND_IMAGE_ALIGN_BOTTOM) {
1031 alignment = kCSSBackgroundPositionBottom;
1032 } else {
1033 alignment = kCSSBackgroundPositionCenter;
1035 info->Set(v8::String::NewFromUtf8(isolate, "imageVerticalAlignment"),
1036 UTF8ToV8String(isolate, alignment));
1038 // The tiling of the theme background image is one of "no-repeat",
1039 // "repeat-x", "repeat-y", "repeat".
1040 // This is the CSS "background-repeat" format.
1041 // Value is only valid if |image_url| is not empty.
1042 std::string tiling = kCSSBackgroundRepeatNo;
1043 switch (theme_info.image_tiling) {
1044 case THEME_BKGRND_IMAGE_NO_REPEAT:
1045 tiling = kCSSBackgroundRepeatNo;
1046 break;
1047 case THEME_BKGRND_IMAGE_REPEAT_X:
1048 tiling = kCSSBackgroundRepeatX;
1049 break;
1050 case THEME_BKGRND_IMAGE_REPEAT_Y:
1051 tiling = kCSSBackgroundRepeatY;
1052 break;
1053 case THEME_BKGRND_IMAGE_REPEAT:
1054 tiling = kCSSBackgroundRepeat;
1055 break;
1057 info->Set(v8::String::NewFromUtf8(isolate, "imageTiling"),
1058 UTF8ToV8String(isolate, tiling));
1060 // The theme background image height is only valid if |imageUrl| is valid.
1061 info->Set(v8::String::NewFromUtf8(isolate, "imageHeight"),
1062 v8::Int32::New(isolate, theme_info.image_height));
1064 // The attribution URL is only valid if the theme has attribution logo.
1065 if (theme_info.has_attribution) {
1066 info->Set(
1067 v8::String::NewFromUtf8(isolate, "attributionUrl"),
1068 UTF8ToV8String(isolate,
1069 base::StringPrintf(kThemeAttributionFormat,
1070 theme_info.theme_id.c_str(),
1071 theme_info.theme_id.c_str())));
1075 args.GetReturnValue().Set(info);
1078 // static
1079 void SearchBoxExtensionWrapper::IsFocused(
1080 const v8::FunctionCallbackInfo<v8::Value>& args) {
1081 content::RenderView* render_view = GetRenderView();
1082 if (!render_view) return;
1084 bool is_focused = SearchBox::Get(render_view)->is_focused();
1085 DVLOG(1) << render_view << " IsFocused: " << is_focused;
1086 args.GetReturnValue().Set(is_focused);
1089 // static
1090 void SearchBoxExtensionWrapper::IsInputInProgress(
1091 const v8::FunctionCallbackInfo<v8::Value>& args) {
1092 content::RenderView* render_view = GetRenderView();
1093 if (!render_view) return;
1095 bool is_input_in_progress =
1096 SearchBox::Get(render_view)->is_input_in_progress();
1097 DVLOG(1) << render_view << " IsInputInProgress: " << is_input_in_progress;
1098 args.GetReturnValue().Set(is_input_in_progress);
1101 // static
1102 void SearchBoxExtensionWrapper::IsKeyCaptureEnabled(
1103 const v8::FunctionCallbackInfo<v8::Value>& args) {
1104 content::RenderView* render_view = GetRenderView();
1105 if (!render_view) return;
1107 args.GetReturnValue().Set(SearchBox::Get(render_view)->
1108 is_key_capture_enabled());
1111 // static
1112 void SearchBoxExtensionWrapper::LogEvent(
1113 const v8::FunctionCallbackInfo<v8::Value>& args) {
1114 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
1115 GURL(chrome::kChromeSearchMostVisitedUrl));
1116 if (!render_view) return;
1118 if (!args.Length() || !args[0]->IsNumber()) {
1119 ThrowInvalidParameters(args);
1120 return;
1123 DVLOG(1) << render_view << " LogEvent";
1125 if (args[0]->Uint32Value() <= NTP_EVENT_TYPE_LAST) {
1126 NTPLoggingEventType event =
1127 static_cast<NTPLoggingEventType>(args[0]->Uint32Value());
1128 SearchBox::Get(render_view)->LogEvent(event);
1132 // static
1133 void SearchBoxExtensionWrapper::LogMostVisitedImpression(
1134 const v8::FunctionCallbackInfo<v8::Value>& args) {
1135 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
1136 GURL(chrome::kChromeSearchMostVisitedUrl));
1137 if (!render_view) return;
1139 if (args.Length() < 2 || !args[0]->IsNumber() || args[1]->IsUndefined()) {
1140 ThrowInvalidParameters(args);
1141 return;
1144 DVLOG(1) << render_view << " LogMostVisitedImpression";
1146 SearchBox::Get(render_view)->LogMostVisitedImpression(
1147 args[0]->IntegerValue(), V8ValueToUTF16(args[1]));
1150 // static
1151 void SearchBoxExtensionWrapper::LogMostVisitedNavigation(
1152 const v8::FunctionCallbackInfo<v8::Value>& args) {
1153 content::RenderView* render_view = GetRenderViewWithCheckedOrigin(
1154 GURL(chrome::kChromeSearchMostVisitedUrl));
1155 if (!render_view) return;
1157 if (args.Length() < 2 || !args[0]->IsNumber() || args[1]->IsUndefined()) {
1158 ThrowInvalidParameters(args);
1159 return;
1162 DVLOG(1) << render_view << " LogMostVisitedNavigation";
1164 SearchBox::Get(render_view)->LogMostVisitedNavigation(
1165 args[0]->IntegerValue(), V8ValueToUTF16(args[1]));
1168 // static
1169 void SearchBoxExtensionWrapper::NavigateContentWindow(
1170 const v8::FunctionCallbackInfo<v8::Value>& args) {
1171 content::RenderView* render_view = GetRenderView();
1172 if (!render_view) return;
1174 if (!args.Length()) {
1175 ThrowInvalidParameters(args);
1176 return;
1179 GURL destination_url;
1180 bool is_most_visited_item_url = false;
1181 // Check if the url is a rid
1182 if (args[0]->IsNumber()) {
1183 InstantMostVisitedItem item;
1184 if (SearchBox::Get(render_view)->GetMostVisitedItemWithID(
1185 args[0]->IntegerValue(), &item)) {
1186 destination_url = item.url;
1187 is_most_visited_item_url = true;
1189 } else {
1190 // Resolve the URL
1191 const base::string16& possibly_relative_url = V8ValueToUTF16(args[0]);
1192 GURL current_url = GetCurrentURL(render_view);
1193 destination_url = internal::ResolveURL(current_url, possibly_relative_url);
1196 DVLOG(1) << render_view << " NavigateContentWindow: " << destination_url;
1198 // Navigate the main frame.
1199 if (destination_url.is_valid() &&
1200 !destination_url.SchemeIs(url::kJavaScriptScheme)) {
1201 WindowOpenDisposition disposition = CURRENT_TAB;
1202 if (args[1]->IsNumber()) {
1203 disposition = (WindowOpenDisposition) args[1]->Uint32Value();
1205 SearchBox::Get(render_view)->NavigateToURL(destination_url, disposition,
1206 is_most_visited_item_url);
1210 // static
1211 void SearchBoxExtensionWrapper::Paste(
1212 const v8::FunctionCallbackInfo<v8::Value>& args) {
1213 content::RenderView* render_view = GetRenderView();
1214 if (!render_view) return;
1216 base::string16 text;
1217 if (!args[0]->IsUndefined())
1218 text = V8ValueToUTF16(args[0]);
1220 DVLOG(1) << render_view << " Paste: " << text;
1221 SearchBox::Get(render_view)->Paste(text);
1224 // static
1225 void SearchBoxExtensionWrapper::StartCapturingKeyStrokes(
1226 const v8::FunctionCallbackInfo<v8::Value>& args) {
1227 content::RenderView* render_view = GetRenderView();
1228 if (!render_view) return;
1230 DVLOG(1) << render_view << " StartCapturingKeyStrokes";
1231 SearchBox::Get(render_view)->StartCapturingKeyStrokes();
1234 // static
1235 void SearchBoxExtensionWrapper::StopCapturingKeyStrokes(
1236 const v8::FunctionCallbackInfo<v8::Value>& args) {
1237 content::RenderView* render_view = GetRenderView();
1238 if (!render_view) return;
1240 DVLOG(1) << render_view << " StopCapturingKeyStrokes";
1241 SearchBox::Get(render_view)->StopCapturingKeyStrokes();
1244 // static
1245 void SearchBoxExtensionWrapper::SetVoiceSearchSupported(
1246 const v8::FunctionCallbackInfo<v8::Value>& args) {
1247 content::RenderView* render_view = GetRenderView();
1248 if (!render_view) {
1249 return;
1251 if (!args.Length()) {
1252 ThrowInvalidParameters(args);
1253 return;
1256 DVLOG(1) << render_view << " SetVoiceSearchSupported";
1257 SearchBox::Get(render_view)->SetVoiceSearchSupported(args[0]->BooleanValue());
1260 // static
1261 void SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions(
1262 const v8::FunctionCallbackInfo<v8::Value>& args) {
1263 content::RenderView* render_view = GetRenderView();
1264 if (!render_view) return;
1266 DVLOG(1) << render_view << " UndoAllMostVisitedDeletions";
1267 SearchBox::Get(render_view)->UndoAllMostVisitedDeletions();
1270 // static
1271 void SearchBoxExtensionWrapper::UndoMostVisitedDeletion(
1272 const v8::FunctionCallbackInfo<v8::Value>& args) {
1273 content::RenderView* render_view = GetRenderView();
1274 if (!render_view) {
1275 return;
1277 if (!args.Length()) {
1278 ThrowInvalidParameters(args);
1279 return;
1282 DVLOG(1) << render_view << " UndoMostVisitedDeletion";
1283 SearchBox::Get(render_view)
1284 ->UndoMostVisitedDeletion(args[0]->ToInteger()->Value());
1287 // static
1288 void SearchBoxExtensionWrapper::GetDisplayInstantResults(
1289 const v8::FunctionCallbackInfo<v8::Value>& args) {
1290 content::RenderView* render_view = GetRenderView();
1291 if (!render_view) return;
1293 bool display_instant_results =
1294 SearchBox::Get(render_view)->display_instant_results();
1295 DVLOG(1) << render_view << " GetDisplayInstantResults" <<
1296 display_instant_results;
1297 args.GetReturnValue().Set(display_instant_results);
1300 } // namespace extensions_v8