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