summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authortonyg@chromium.org <tonyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-04 15:48:39 +0000
committertonyg@chromium.org <tonyg@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-04 15:48:39 +0000
commitce833284bfd1b0a5db62e0f3c25f48af70ae8784 (patch)
tree641d0e058901b544626b3503ff5ce06da08ba926 /chrome/renderer
parent26cce058ecd57c1da05a9a95a277da91e9be8f43 (diff)
downloadchromium_src-ce833284bfd1b0a5db62e0f3c25f48af70ae8784.zip
chromium_src-ce833284bfd1b0a5db62e0f3c25f48af70ae8784.tar.gz
chromium_src-ce833284bfd1b0a5db62e0f3c25f48af70ae8784.tar.bz2
Implement new SearchBox API along side existing API.
Add some tests. BUG=none TEST=interactive_ui_tests --gtest_filter=InstantTest.* git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65061 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/render_thread.cc2
-rw-r--r--chrome/renderer/render_view.cc56
-rw-r--r--chrome/renderer/render_view.h18
-rw-r--r--chrome/renderer/search_extension.cc4
-rw-r--r--chrome/renderer/searchbox.cc18
-rw-r--r--chrome/renderer/searchbox.h25
-rw-r--r--chrome/renderer/searchbox_extension.cc381
-rw-r--r--chrome/renderer/searchbox_extension.h42
8 files changed, 540 insertions, 6 deletions
diff --git a/chrome/renderer/render_thread.cc b/chrome/renderer/render_thread.cc
index cde829c..a43a6ec 100644
--- a/chrome/renderer/render_thread.cc
+++ b/chrome/renderer/render_thread.cc
@@ -66,6 +66,7 @@
#include "chrome/renderer/renderer_webidbfactory_impl.h"
#include "chrome/renderer/renderer_webkitclient_impl.h"
#include "chrome/renderer/search_extension.h"
+#include "chrome/renderer/searchbox_extension.h"
#include "chrome/renderer/spellchecker/spellcheck.h"
#include "chrome/renderer/user_script_slave.h"
#include "ipc/ipc_channel_handle.h"
@@ -853,6 +854,7 @@ void RenderThread::EnsureWebKitInitialized() {
RegisterExtension(extensions_v8::LoadTimesExtension::Get(), false);
RegisterExtension(extensions_v8::ChromeAppExtension::Get(), false);
RegisterExtension(extensions_v8::ExternalExtension::Get(), false);
+ RegisterExtension(extensions_v8::SearchBoxExtension::Get(), false);
v8::Extension* search_extension = extensions_v8::SearchExtension::Get();
// search_extension is null if not enabled.
if (search_extension)
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 9e3bc83..0b300a1 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -80,6 +80,7 @@
#include "chrome/renderer/render_widget_fullscreen_pepper.h"
#include "chrome/renderer/renderer_webapplicationcachehost_impl.h"
#include "chrome/renderer/renderer_webstoragenamespace_impl.h"
+#include "chrome/renderer/searchbox_extension.h"
#include "chrome/renderer/speech_input_dispatcher.h"
#include "chrome/renderer/spellchecker/spellcheck.h"
#include "chrome/renderer/user_script_idle_scheduler.h"
@@ -837,6 +838,12 @@ void RenderView::OnMessageReceived(const IPC::Message& message) {
IPC_MESSAGE_HANDLER(ViewMsg_SetBackground, OnSetBackground)
IPC_MESSAGE_HANDLER(ViewMsg_EnablePreferredSizeChangedMode,
OnEnablePreferredSizeChangedMode)
+ IPC_MESSAGE_HANDLER(ViewMsg_SearchBoxChange, OnSearchBoxChange)
+ IPC_MESSAGE_HANDLER(ViewMsg_SearchBoxSubmit, OnSearchBoxSubmit)
+ IPC_MESSAGE_HANDLER(ViewMsg_SearchBoxCancel, OnSearchBoxCancel)
+ IPC_MESSAGE_HANDLER(ViewMsg_SearchBoxResize, OnSearchBoxResize)
+ IPC_MESSAGE_HANDLER(ViewMsg_DetermineIfPageSupportsInstant,
+ OnDetermineIfPageSupportsInstant)
IPC_MESSAGE_HANDLER(ViewMsg_DisableScrollbarsForSmallWindows,
OnDisableScrollbarsForSmallWindows)
IPC_MESSAGE_HANDLER(ViewMsg_SetRendererPrefs, OnSetRendererPrefs)
@@ -4330,9 +4337,9 @@ WebFrame* RenderView::GetChildFrame(const std::wstring& xpath) const {
return frame;
}
-void RenderView::SetSuggestResult(const std::string& suggest) {
- // Explicitly allow empty strings to be sent to the browser.
- Send(new ViewHostMsg_SetSuggestResult(routing_id_, page_id_, suggest));
+void RenderView::SetSuggestions(const std::vector<std::string>& suggestions) {
+ // Explicitly allow empty vector to be sent to the browser.
+ Send(new ViewHostMsg_SetSuggestions(routing_id_, page_id_, suggestions));
}
void RenderView::EvaluateScript(const string16& frame_xpath,
@@ -4570,6 +4577,49 @@ void RenderView::OnEnablePreferredSizeChangedMode(int flags) {
}
}
+void RenderView::OnSearchBoxChange(const string16& value,
+ int selection_start,
+ int selection_end) {
+ search_box_.value = value;
+ search_box_.selection_start = selection_start;
+ search_box_.selection_end = selection_end;
+ if (!webview() || !webview()->mainFrame())
+ return;
+ extensions_v8::SearchBoxExtension::DispatchChange(webview()->mainFrame());
+}
+
+void RenderView::OnSearchBoxSubmit(const string16& value, bool verbatim) {
+ search_box_.value = value;
+ search_box_.verbatim = verbatim;
+ if (!webview() || !webview()->mainFrame())
+ return;
+ extensions_v8::SearchBoxExtension::DispatchSubmit(webview()->mainFrame());
+}
+
+void RenderView::OnSearchBoxCancel() {
+ search_box_.verbatim = false;
+ if (!webview() || !webview()->mainFrame())
+ return;
+ extensions_v8::SearchBoxExtension::DispatchCancel(webview()->mainFrame());
+}
+
+void RenderView::OnSearchBoxResize(const gfx::Rect& bounds) {
+ search_box_.x = bounds.x();
+ search_box_.y = bounds.y();
+ search_box_.width = bounds.width();
+ search_box_.height = bounds.height();
+ if (!webview() || !webview()->mainFrame())
+ return;
+ extensions_v8::SearchBoxExtension::DispatchResize(webview()->mainFrame());
+}
+
+void RenderView::OnDetermineIfPageSupportsInstant(const string16& value) {
+ search_box_.value = value;
+ bool result = extensions_v8::SearchBoxExtension::PageSupportsInstant(
+ webview()->mainFrame());
+ Send(new ViewHostMsg_InstantSupportDetermined(routing_id_, page_id_, result));
+}
+
void RenderView::OnDisableScrollbarsForSmallWindows(
const gfx::Size& disable_scrollbar_size_limit) {
disable_scrollbars_size_limit_ = disable_scrollbar_size_limit;
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index b835293..54a995f 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -32,6 +32,7 @@
#include "chrome/renderer/pepper_plugin_delegate_impl.h"
#include "chrome/renderer/render_widget.h"
#include "chrome/renderer/renderer_webcookiejar_impl.h"
+#include "chrome/renderer/searchbox.h"
#include "chrome/renderer/translate_helper.h"
#include "third_party/WebKit/WebKit/chromium/public/WebConsoleMessage.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFileSystem.h"
@@ -229,6 +230,10 @@ class RenderView : public RenderWidget,
disable_scrollbars_size_limit_.height() <= height));
}
+ const SearchBox& searchbox() const {
+ return search_box_;
+ }
+
// Called from JavaScript window.external.AddSearchProvider() to add a
// keyword for a provider described in the given OpenSearch document.
void AddSearchProvider(const std::string& url,
@@ -239,8 +244,8 @@ class RenderView : public RenderWidget,
GetSearchProviderInstallState(WebKit::WebFrame* frame,
const std::string& url);
- // Sends ViewHostMsg_SetSuggestResult to the browser.
- void SetSuggestResult(const std::string& suggest);
+ // Sends ViewHostMsg_SetSuggestions to the browser.
+ void SetSuggestions(const std::vector<std::string>& suggestions);
// Evaluates a string of JavaScript in a particular frame.
void EvaluateScript(const string16& frame_xpath,
@@ -823,6 +828,13 @@ class RenderView : public RenderWidget,
const gfx::Point& screen_pt,
WebKit::WebDragOperationsMask operations_allowed);
void OnEnablePreferredSizeChangedMode(int flags);
+ void OnSearchBoxChange(const string16& value,
+ int selection_start,
+ int selection_end);
+ void OnSearchBoxSubmit(const string16& value, bool verbatim);
+ void OnSearchBoxCancel();
+ void OnSearchBoxResize(const gfx::Rect& bounds);
+ void OnDetermineIfPageSupportsInstant(const string16& value);
void OnEnableViewSourceMode();
void OnExecuteCode(const ViewMsg_ExecuteCode_Params& params);
void OnExecuteEditCommand(const std::string& name, const std::string& value);
@@ -1235,6 +1247,8 @@ class RenderView : public RenderWidget,
// The text selection the last time DidChangeSelection got called.
std::string last_selection_;
+ SearchBox search_box_;
+
// View ----------------------------------------------------------------------
// Type of view attached with RenderView. See view_types.h
diff --git a/chrome/renderer/search_extension.cc b/chrome/renderer/search_extension.cc
index 1ce6296..f14cda7 100644
--- a/chrome/renderer/search_extension.cc
+++ b/chrome/renderer/search_extension.cc
@@ -78,7 +78,9 @@ v8::Handle<v8::Value> SearchExtensionWrapper::SetSuggestResult(
RenderView* render_view = GetRenderView();
if (!render_view) return v8::Undefined();
- render_view->SetSuggestResult(std::string(*v8::String::Utf8Value(args[0])));
+ std::vector<std::string> suggestions;
+ suggestions.push_back(std::string(*v8::String::Utf8Value(args[0])));
+ render_view->SetSuggestions(suggestions);
return v8::Undefined();
}
diff --git a/chrome/renderer/searchbox.cc b/chrome/renderer/searchbox.cc
new file mode 100644
index 0000000..6766f25
--- /dev/null
+++ b/chrome/renderer/searchbox.cc
@@ -0,0 +1,18 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/searchbox.h"
+
+SearchBox::SearchBox()
+ : verbatim(false),
+ selection_start(0),
+ selection_end(0),
+ x(0),
+ y(0),
+ width(0),
+ height(0) {
+}
+
+SearchBox::~SearchBox() {
+}
diff --git a/chrome/renderer/searchbox.h b/chrome/renderer/searchbox.h
new file mode 100644
index 0000000..d09c73a
--- /dev/null
+++ b/chrome/renderer/searchbox.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_SEARCHBOX_H_
+#define CHROME_RENDERER_SEARCHBOX_H_
+#pragma once
+
+#include "base/string16.h"
+
+struct SearchBox {
+ SearchBox();
+ ~SearchBox();
+
+ string16 value;
+ bool verbatim;
+ uint32 selection_start;
+ uint32 selection_end;
+ uint32 x;
+ uint32 y;
+ uint32 width;
+ uint32 height;
+};
+
+#endif // CHROME_RENDERER_SEARCHBOX_H_
diff --git a/chrome/renderer/searchbox_extension.cc b/chrome/renderer/searchbox_extension.cc
new file mode 100644
index 0000000..40073fa
--- /dev/null
+++ b/chrome/renderer/searchbox_extension.cc
@@ -0,0 +1,381 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/searchbox_extension.h"
+
+#include "base/command_line.h"
+#include "base/string_split.h"
+#include "base/stringprintf.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/render_messages_params.h"
+#include "chrome/renderer/render_view.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "v8/include/v8.h"
+
+using WebKit::WebFrame;
+using WebKit::WebScriptSource;
+using WebKit::WebString;
+using WebKit::WebView;
+
+namespace extensions_v8 {
+
+static const char kSearchBoxExtensionName[] = "v8/SearchBox";
+
+static const char kSearchBoxExtensionScript[] =
+ "var chrome;"
+ "if (!chrome)"
+ " chrome = {};"
+ "if (!chrome.searchBox) {"
+ " chrome.searchBox = new function() {"
+ " native function GetValue();"
+ " native function GetVerbatim();"
+ " native function GetSelectionStart();"
+ " native function GetSelectionEnd();"
+ " native function GetX();"
+ " native function GetY();"
+ " native function GetWidth();"
+ " native function GetHeight();"
+ " native function SetSuggestions();"
+ " this.__defineGetter__('value', GetValue);"
+ " this.__defineGetter__('verbatim', GetVerbatim);"
+ " this.__defineGetter__('selectionStart', GetSelectionStart);"
+ " this.__defineGetter__('selectionEnd', GetSelectionEnd);"
+ " this.__defineGetter__('x', GetX);"
+ " this.__defineGetter__('y', GetY);"
+ " this.__defineGetter__('width', GetWidth);"
+ " this.__defineGetter__('height', GetHeight);"
+ " this.setSuggestions = function(text) {"
+ " SetSuggestions(text);"
+ " };"
+ " this.onchange = null;"
+ " this.onsubmit = null;"
+ " this.oncancel = null;"
+ " this.onresize = null;"
+ " };"
+ "}";
+
+static const char kChangeEventName[] = "chrome.searchBox.onchange";
+
+static const char kSubmitEventName[] = "chrome.searchBox.onsubmit";
+
+static const char kCancelEventName[] = "chrome.searchBox.oncancel";
+
+static const char kResizeEventName[] = "chrome.searchBox.onresize";
+
+// Deprecated API support.
+// TODO(tonyg): Remove these when they are no longer used.
+// ----------------------------------------------------------------------------
+// Script sent as the user is typing and the provider supports instant.
+// Params:
+// . the text the user typed.
+// TODO: add support for the 2nd and 3rd params.
+static const char kUserInputScript[] =
+ "if (window.chrome.userInput)"
+ " window.chrome.userInput("
+ " window.chrome.searchBox.value,"
+ " 0,"
+ " 0);";
+
+// Script sent when the page is committed and the provider supports instant.
+// Params:
+// . the text the user typed.
+// . boolean indicating if the user pressed enter to accept the text.
+static const char kUserDoneScript[] =
+ "if (window.chrome.userWantsQuery)"
+ " window.chrome.userWantsQuery("
+ " window.chrome.searchBox.value,"
+ " window.chrome.searchBox.verbatim);";
+
+// Script sent when the bounds of the omnibox changes and the provider supports
+// instant. The params are the bounds relative to the origin of the preview
+// (x, y, width, height).
+static const char kSetOmniboxBoundsScript[] =
+ "if (window.chrome.setDropdownDimensions)"
+ " window.chrome.setDropdownDimensions("
+ " window.chrome.searchBox.x,"
+ " window.chrome.searchBox.y,"
+ " window.chrome.searchBox.width,"
+ " window.chrome.searchBox.height);";
+
+// We first send this script down to determine if the page supports instant.
+static const char kSupportsInstantScript[] =
+ "if (window.chrome.sv) true; else false;";
+
+// The google.y.first array is a list of functions which are to be executed
+// after the external JavaScript used by Google web search loads. The deprecated
+// API requires setDropdownDimensions and userInput to be invoked after
+// the external JavaScript loads. So if they are not already registered, we add
+// them to the array of functions the page will execute after load. This tight
+// coupling discourages proliferation of the deprecated API.
+static const char kInitScript[] =
+ "(function() {"
+ "var initScript = function(){%s%s};"
+ "if (window.chrome.setDropdownDimensions)"
+ " initScript();"
+ "else if (window.google && window.google.y)"
+ " window.google.y.first.push(initScript);"
+ "})();";
+// ----------------------------------------------------------------------------
+
+class SearchBoxExtensionWrapper : public v8::Extension {
+ public:
+ SearchBoxExtensionWrapper();
+
+ // Allows v8's javascript code to call the native functions defined
+ // in this class for window.chrome.
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction(
+ v8::Handle<v8::String> name);
+
+ // Helper function to find the RenderView. May return NULL.
+ static RenderView* GetRenderView();
+
+ // Gets the value of the user's search query.
+ static v8::Handle<v8::Value> GetValue(const v8::Arguments& args);
+
+ // Gets whether the |value| should be considered final -- as opposed to a
+ // partial match. This may be set if the user clicks a suggestion, presses
+ // forward delete, or in other cases where Chrome overrides.
+ static v8::Handle<v8::Value> GetVerbatim(const v8::Arguments& args);
+
+ // Gets the start of the selection in the search box.
+ static v8::Handle<v8::Value> GetSelectionStart(const v8::Arguments& args);
+
+ // Gets the end of the selection in the search box.
+ static v8::Handle<v8::Value> GetSelectionEnd(const v8::Arguments& args);
+
+ // Gets the x coordinate (relative to |window|) of the left edge of the
+ // region of the search box that overlaps the window.
+ static v8::Handle<v8::Value> GetX(const v8::Arguments& args);
+
+ // Gets the y coordinate (relative to |window|) of the right edge of the
+ // region of the search box that overlaps the window.
+ static v8::Handle<v8::Value> GetY(const v8::Arguments& args);
+
+ // Gets the width of the region of the search box that overlaps the window.
+ static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args);
+
+ // Gets the height of the region of the search box that overlaps the window.
+ static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args);
+
+ // Sets ordered suggestions. Valid for current |value|.
+ static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper);
+};
+
+SearchBoxExtensionWrapper::SearchBoxExtensionWrapper()
+ : v8::Extension(kSearchBoxExtensionName, kSearchBoxExtensionScript) {}
+
+v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction(
+ v8::Handle<v8::String> name) {
+ if (name->Equals(v8::String::New("GetValue"))) {
+ return v8::FunctionTemplate::New(GetValue);
+ } else if (name->Equals(v8::String::New("GetVerbatim"))) {
+ return v8::FunctionTemplate::New(GetVerbatim);
+ } else if (name->Equals(v8::String::New("GetSelectionStart"))) {
+ return v8::FunctionTemplate::New(GetSelectionStart);
+ } else if (name->Equals(v8::String::New("GetSelectionEnd"))) {
+ return v8::FunctionTemplate::New(GetSelectionEnd);
+ } else if (name->Equals(v8::String::New("GetX"))) {
+ return v8::FunctionTemplate::New(GetX);
+ } else if (name->Equals(v8::String::New("GetY"))) {
+ return v8::FunctionTemplate::New(GetY);
+ } else if (name->Equals(v8::String::New("GetWidth"))) {
+ return v8::FunctionTemplate::New(GetWidth);
+ } else if (name->Equals(v8::String::New("GetHeight"))) {
+ return v8::FunctionTemplate::New(GetHeight);
+ } else if (name->Equals(v8::String::New("SetSuggestions"))) {
+ return v8::FunctionTemplate::New(SetSuggestions);
+ }
+ return v8::Handle<v8::FunctionTemplate>();
+}
+
+// static
+RenderView* SearchBoxExtensionWrapper::GetRenderView() {
+ WebFrame* webframe = WebFrame::frameForEnteredContext();
+ DCHECK(webframe) << "There should be an active frame since we just got "
+ "a native function called.";
+ if (!webframe) return NULL;
+
+ WebView* webview = webframe->view();
+ if (!webview) return NULL; // can happen during closing
+
+ return RenderView::FromWebView(webview);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetValue(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::String::New(
+ reinterpret_cast<const uint16_t*>(render_view->searchbox().value.c_str()),
+ render_view->searchbox().value.length());
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetVerbatim(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Boolean::New(render_view->searchbox().verbatim);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSelectionStart(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(render_view->searchbox().selection_start);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSelectionEnd(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(render_view->searchbox().selection_end);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetX(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(render_view->searchbox().x);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetY(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(render_view->searchbox().y);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetWidth(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(render_view->searchbox().width);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetHeight(
+ const v8::Arguments& args) {
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(render_view->searchbox().height);
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions(
+ const v8::Arguments& args) {
+ if (!args.Length() || !args[0]->IsArray()) return v8::Undefined();
+
+ std::vector<std::string> suggestions;
+ v8::Array* suggestions_arg = static_cast<v8::Array*>(*args[0]);
+ uint32_t length = suggestions_arg->Length();
+ for (uint32_t i = 0; i < length; i++) {
+ std::string suggestion = *v8::String::Utf8Value(
+ suggestions_arg->Get(v8::Integer::New(i))->ToString());
+ if (!suggestion.length()) continue;
+ suggestions.push_back(suggestion);
+ }
+
+ RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+
+ render_view->SetSuggestions(suggestions);
+ return v8::Undefined();
+}
+
+// static
+bool Dispatch(WebFrame* frame, const std::string& event_name) {
+ DCHECK(frame) << "Dispatch requires frame";
+ if (!frame) return false;
+
+ v8::HandleScope handle_scope;
+ v8::Local<v8::Context> context = frame->mainWorldScriptContext();
+ v8::Context::Scope context_scope(context);
+
+ v8::Local<v8::Value> value =
+ context->Global()->Get(v8::String::New("window"));
+ std::vector<std::string> components;
+ base::SplitStringDontTrim(event_name, '.', &components);
+ for (size_t i = 0; i < components.size(); ++i) {
+ if (!value.IsEmpty() && value->IsObject())
+ value = value->ToObject()->Get(v8::String::New(components[i].c_str()));
+ }
+ if (value.IsEmpty() || !value->IsFunction())
+ return false;
+
+ v8::Local<v8::Function> function = v8::Local<v8::Function>::Cast(value);
+ if (function.IsEmpty())
+ return false;
+
+ function->Call(v8::Object::New(), 0, NULL);
+ return true;
+}
+
+// static
+void SearchBoxExtension::DispatchChange(WebFrame* frame) {
+ if (Dispatch(frame, kChangeEventName))
+ return;
+ frame->executeScript(WebScriptSource(kUserInputScript));
+}
+
+// static
+void SearchBoxExtension::DispatchSubmit(WebFrame* frame) {
+ if (Dispatch(frame, kSubmitEventName))
+ return;
+ frame->executeScript(WebScriptSource(kUserDoneScript));
+}
+
+// static
+void SearchBoxExtension::DispatchCancel(WebFrame* frame) {
+ if (Dispatch(frame, kCancelEventName))
+ return;
+ frame->executeScript(WebScriptSource(kUserDoneScript));
+}
+
+// static
+void SearchBoxExtension::DispatchResize(WebFrame* frame) {
+ if (Dispatch(frame, kResizeEventName))
+ return;
+ frame->executeScript(WebScriptSource(kSetOmniboxBoundsScript));
+}
+
+// static
+bool SearchBoxExtension::PageSupportsInstant(WebFrame* frame) {
+ DCHECK(frame) << "PageSupportsInstant requires frame";
+ if (!frame) return false;
+
+ bool supports_deprecated_api = frame->executeScriptAndReturnValue(
+ WebScriptSource(kSupportsInstantScript))->BooleanValue();
+ // TODO(tonyg): Add way of detecting instant support to SearchBox API.
+ bool supports_searchbox_api = supports_deprecated_api;
+
+ // The deprecated API needs to notify the page of events it may have missed.
+ // This isn't necessary in the SearchBox API, since the page can query the
+ // API at any time.
+ static std::string init_script(
+ StringPrintf(kInitScript, kSetOmniboxBoundsScript, kUserInputScript));
+ if (supports_deprecated_api) {
+ frame->executeScript(WebScriptSource(WebString::fromUTF8(init_script)));
+ }
+
+ return supports_searchbox_api || supports_deprecated_api;
+}
+
+// static
+v8::Extension* SearchBoxExtension::Get() {
+ return new SearchBoxExtensionWrapper();
+}
+
+} // namespace extensions_v8
diff --git a/chrome/renderer/searchbox_extension.h b/chrome/renderer/searchbox_extension.h
new file mode 100644
index 0000000..61d82b7c
--- /dev/null
+++ b/chrome/renderer/searchbox_extension.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_SEARCHBOX_EXTENSION_H_
+#define CHROME_RENDERER_SEARCHBOX_EXTENSION_H_
+#pragma once
+
+#include "base/basictypes.h"
+
+namespace v8 {
+class Extension;
+}
+
+namespace WebKit {
+class WebFrame;
+}
+
+namespace extensions_v8 {
+
+// Reference implementation of the SearchBox API as described in:
+// http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2010-October/028818.html
+class SearchBoxExtension {
+ public:
+ // Returns the v8::Extension object handling searchbox bindings. Returns null
+ // if match-preview is not enabled. Caller takes ownership of returned object.
+ static v8::Extension* Get();
+
+ static void DispatchChange(WebKit::WebFrame* frame);
+ static void DispatchSubmit(WebKit::WebFrame* frame);
+ static void DispatchCancel(WebKit::WebFrame* frame);
+ static void DispatchResize(WebKit::WebFrame* frame);
+
+ static bool PageSupportsInstant(WebKit::WebFrame* frame);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SearchBoxExtension);
+};
+
+} // namespace extensions_v8
+
+#endif // CHROME_RENDERER_SEARCHBOX_EXTENSION_H_