Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1352)

Unified Diff: chrome/renderer/searchbox_extension.cc

Issue 10809063: Adding Javascript support for the Extended Searchbox API. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/renderer/searchbox_extension.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: chrome/renderer/searchbox_extension.cc
diff --git a/chrome/renderer/searchbox_extension.cc b/chrome/renderer/searchbox_extension.cc
index 29bddcfecf0669d5b96f5d5210f016fbc3dda72c..d15db22e21242ee8eecf7d3a40f3e4530ff7d9fc 100644
--- a/chrome/renderer/searchbox_extension.cc
+++ b/chrome/renderer/searchbox_extension.cc
@@ -8,15 +8,19 @@
#include <vector>
#include "base/basictypes.h"
-#include "base/command_line.h"
+#include "base/string_number_conversions.h"
+#include "base/string_piece.h"
#include "base/string_split.h"
#include "base/stringprintf.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/renderer/searchbox.h"
#include "content/public/renderer/render_view.h"
#include "grit/renderer_resources.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLRequest.h"
#include "ui/base/resource/resource_bundle.h"
#include "v8/include/v8.h"
@@ -25,6 +29,22 @@ using WebKit::WebScriptSource;
using WebKit::WebString;
using WebKit::WebView;
+namespace {
+
+// Splits the string in |number| into two pieces, a leading number token (saved
+// in |number|) and the rest (saved in |suffix|). Either piece may become empty,
+// depending on whether the input had no digits or only digits. Neither argument
+// may be NULL.
+void SplitLeadingNumberToken(std::string* number, std::string* suffix) {
+ size_t i = 0;
+ while (i < number->size() && isdigit((*number)[i]))
+ ++i;
+ suffix->assign(*number, i, number->size() - i);
+ number->resize(i);
+}
+
+} // namespace
+
namespace extensions_v8 {
static const char kSearchBoxExtensionName[] = "v8/SearchBox";
@@ -65,60 +85,55 @@ static const char kDispatchResizeEventScript[] =
" true;"
"}";
-// 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.
-// '46' forces the server to give us verbatim results.
-static const char kUserInputScript[] =
- "if (window.chrome.userInput)"
- " window.chrome.userInput("
- " window.chrome.searchBox.value,"
- " window.chrome.searchBox.verbatim ? 46 : 0,"
- " window.chrome.searchBox.selectionStart);";
-
-// 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);";
+// Extended API.
+
+static const char kDispatchNativeSuggestionsEventScript[] =
+ "if (window.chrome &&"
+ " window.chrome.searchBox &&"
+ " window.chrome.searchBox.onnativesuggestions &&"
+ " typeof window.chrome.searchBox.onnativesuggestions == 'function') {"
+ " window.chrome.searchBox.onnativesuggestions();"
+ " true;"
+ "}";
+
+static const char kDispatchKeyPressEventScript[] =
+ "if (window.chrome &&"
+ " window.chrome.searchBox &&"
+ " window.chrome.searchBox.onkeypress &&"
+ " typeof window.chrome.searchBox.onkeypress == 'function') {"
+ " window.chrome.searchBox.onkeypress("
+ " {keyCode:window.chrome.searchBox.keyCode});"
+ " true;"
+ "}";
+
+static const char kDispatchFocusEventScript[] =
+ "if (window.chrome &&"
+ " window.chrome.searchBox &&"
+ " window.chrome.searchBox.onfocus &&"
+ " typeof window.chrome.searchBox.onfocus == 'function') {"
+ " window.chrome.searchBox.onfocus();"
+ " true;"
+ "}";
+
+static const char kDispatchBlurEventScript[] =
+ "if (window.chrome &&"
+ " window.chrome.searchBox &&"
+ " window.chrome.searchBox.onblur &&"
+ " typeof window.chrome.searchBox.onblur == 'function') {"
+ " window.chrome.searchBox.onblur();"
+ " true;"
+ "}";
// 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);"
- "})();";
-// ----------------------------------------------------------------------------
+ "if (window.chrome &&"
+ " window.chrome.searchBox &&"
+ " window.chrome.searchBox.onsubmit &&"
+ " typeof window.chrome.searchBox.onsubmit == 'function') {"
+ " true;"
+ "} else {"
+ " false;"
+ "}";
class SearchBoxExtensionWrapper : public v8::Extension {
public:
@@ -160,9 +175,42 @@ class SearchBoxExtensionWrapper : public v8::Extension {
// Gets the height of the region of the search box that overlaps the window.
static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args);
+ // Gets the native suggestions from search box.
+ static v8::Handle<v8::Value> GetNativeSuggestions(const v8::Arguments& args);
+
+ // Gets the last key code entered in search box.
+ static v8::Handle<v8::Value> GetKeyCode(const v8::Arguments& args);
+
+ // Gets some info about the last search session committed in the search box.
+ static v8::Handle<v8::Value> GetSessionContext(const v8::Arguments& args);
+
+ // Gets whether the search box currently has keyboard focus or not.
+ static v8::Handle<v8::Value> GetIsFocused(const v8::Arguments& args);
+
// Sets ordered suggestions. Valid for current |value|.
static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args);
+ // Sets the text to be autocompleted into the search box.
+ static v8::Handle<v8::Value> SetAutocompleteText(const v8::Arguments& args);
+
+ // Like |SetAutocompleteText| but uses a restricted ID to identify the text.
+ static v8::Handle<v8::Value> SetRestrictedAutocompleteText(
+ const v8::Arguments& args);
+
+ // Sets the search box text, completely replacing what the user typed.
+ static v8::Handle<v8::Value> SetValue(const v8::Arguments& args);
+
+ // Like |SetValue| but uses a restricted ID to identify the text.
+ static v8::Handle<v8::Value> SetRestrictedValue(const v8::Arguments& args);
+
+ // Resize the preview to the given height.
+ static v8::Handle<v8::Value> SetNonNativeDropdownHeight(
+ const v8::Arguments& args);
+
+ // Navigate the window to the URL identified by a restricted ID.
+ static v8::Handle<v8::Value> NavigateContentWindow(const v8::Arguments& args);
+
+
private:
DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper);
};
@@ -189,8 +237,28 @@ v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction(
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("GetNativeSuggestions"))) {
David Black 2012/07/24 00:28:40 Access to these new functions should be guarded be
sreeram 2012/07/24 18:09:22 It's painful to guard them properly since it intro
David Black 2012/07/24 22:34:56 Then that guarding code should be moved out to a c
sreeram 2012/07/24 22:56:27 Agreed. However, this CL doesn't expose the sessio
David Black 2012/07/24 23:05:07 From what I can tell from the GetSessionContext fu
sreeram 2012/07/25 17:35:00 All of the accessors (current_url, last_query, or
+ return v8::FunctionTemplate::New(GetNativeSuggestions);
+ } else if (name->Equals(v8::String::New("GetKeyCode"))) {
+ return v8::FunctionTemplate::New(GetKeyCode);
+ } else if (name->Equals(v8::String::New("GetSessionContext"))) {
+ return v8::FunctionTemplate::New(GetSessionContext);
+ } else if (name->Equals(v8::String::New("GetIsFocused"))) {
+ return v8::FunctionTemplate::New(GetIsFocused);
} else if (name->Equals(v8::String::New("SetSuggestions"))) {
return v8::FunctionTemplate::New(SetSuggestions);
+ } else if (name->Equals(v8::String::New("SetAutocompleteText"))) {
+ return v8::FunctionTemplate::New(SetAutocompleteText);
+ } else if (name->Equals(v8::String::New("SetRestrictedAutocompleteText"))) {
+ return v8::FunctionTemplate::New(SetRestrictedAutocompleteText);
+ } else if (name->Equals(v8::String::New("SetValue"))) {
+ return v8::FunctionTemplate::New(SetValue);
+ } else if (name->Equals(v8::String::New("SetRestrictedValue"))) {
+ return v8::FunctionTemplate::New(SetRestrictedValue);
+ } else if (name->Equals(v8::String::New("SetNonNativeDropdownHeight"))) {
+ return v8::FunctionTemplate::New(SetNonNativeDropdownHeight);
+ } else if (name->Equals(v8::String::New("NavigateContentWindow"))) {
+ return v8::FunctionTemplate::New(NavigateContentWindow);
}
return v8::Handle<v8::FunctionTemplate>();
}
@@ -199,7 +267,7 @@ v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction(
content::RenderView* SearchBoxExtensionWrapper::GetRenderView() {
WebFrame* webframe = WebFrame::frameForEnteredContext();
DCHECK(webframe) << "There should be an active frame since we just got "
- "a native function called.";
+ "a native function called.";
if (!webframe) return NULL;
WebView* webview = webframe->view();
@@ -216,7 +284,7 @@ v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetValue(
return v8::String::New(
reinterpret_cast<const uint16_t*>(
SearchBox::Get(render_view)->value().c_str()),
- SearchBox::Get(render_view)->value().length());
+ SearchBox::Get(render_view)->value().length());
}
// static
@@ -275,112 +343,333 @@ v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetHeight(
return v8::Int32::New(SearchBox::Get(render_view)->GetRect().height());
}
-// Accepts a single argument in form:
-// {
-// suggestions: [
-// {
-// value: "..."
-// }
-// ]
-// }
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetNativeSuggestions(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ const std::vector<InstantNativeSuggestionsParts>& suggestions =
+ SearchBox::Get(render_view)->native_suggestions();
+ const int rid_base = SearchBox::Get(render_view)->rid_base();
+ v8::Handle<v8::Array> suggestions_array(v8::Array::New(suggestions.size()));
+ for (size_t i = 0; i < suggestions.size(); ++i) {
+ v8::Handle<v8::Object> suggestion(v8::Object::New());
+ suggestion->Set(v8::String::New("provider"),
+ v8::String::New(suggestions[i].provider.c_str()));
+ suggestion->Set(v8::String::New("contents"),
+ v8::String::New(suggestions[i].contents.c_str()));
+ suggestion->Set(v8::String::New("destination_url"),
+ v8::String::New(suggestions[i].destination_url.spec().c_str()));
+ suggestion->Set(v8::String::New("rid"), v8::Uint32::New(rid_base + i));
+
+ v8::Handle<v8::Object> ranking_data(v8::Object::New());
+ ranking_data->Set(v8::String::New("relevance"),
+ v8::Int32::New(suggestions[i].relevance));
+ suggestion->Set(v8::String::New("rankingData"), ranking_data);
+
+ suggestions_array->Set(i, suggestion);
+ }
+
+ return suggestions_array;
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetKeyCode(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Int32::New(SearchBox::Get(render_view)->key_code());
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSessionContext(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ v8::Handle<v8::Object> session_context(v8::Object::New());
+ session_context->Set(v8::String::New("lastSearchQuery"),
+ v8::String::New(SearchBox::Get(render_view)->last_query().c_str()));
+ // NOTE: SECURITY RISK -- Providing the current url in this way is insecure.
+ session_context->Set(v8::String::New("currentUrl"),
+ v8::String::New(SearchBox::Get(render_view)->current_url().c_str()));
+ return session_context;
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetIsFocused(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (!render_view) return v8::Undefined();
+ return v8::Boolean::New(SearchBox::Get(render_view)->is_focused());
+}
+
// static
v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions(
David Black 2012/07/24 00:28:40 It would probably be best to make a new ExtendedSe
sreeram 2012/07/24 18:09:22 Same reason as before with respect to the guard. B
const v8::Arguments& args) {
- std::vector<std::string> suggestions;
- InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW;
-
- if (args.Length() && args[0]->IsArray()) {
- // For backwards compatibility, also accept an array of strings.
- // TODO(tonyg): Remove this when it is confirmed to be unused.
- v8::Local<v8::Array> suggestions_array =
- v8::Local<v8::Array>::Cast(args[0]);
- uint32_t length = suggestions_array->Length();
- for (uint32_t i = 0; i < length; i++) {
- std::string suggestion = *v8::String::Utf8Value(
- suggestions_array->Get(v8::Integer::New(i))->ToString());
- if (!suggestion.length()) continue;
- suggestions.push_back(suggestion);
+ std::vector<InstantSuggestion> suggestions;
+
+ if (args.Length() && args[0]->IsObject()) {
+ v8::Local<v8::Object> suggestion_json(args[0]->ToObject());
+
+ InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW;
+ InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH;
+ v8::Local<v8::Value> complete_value(
+ suggestion_json->Get(v8::String::New("complete_behavior")));
+ if (complete_value->IsString()) {
+ if (complete_value->Equals(v8::String::New("now"))) {
+ behavior = INSTANT_COMPLETE_NOW;
+ } else if (complete_value->Equals(v8::String::New("never"))) {
+ behavior = INSTANT_COMPLETE_NEVER;
+ } else if (complete_value->Equals(v8::String::New("delayed"))) {
+ behavior = INSTANT_COMPLETE_DELAYED;
+ } else if (complete_value->Equals(v8::String::New("replace"))) {
+ behavior = INSTANT_COMPLETE_REPLACE;
+ } else {
+ VLOG(1) << "Unsupported complete behavior '"
+ << *v8::String::Utf8Value(complete_value) << "'";
+ }
}
- } else if (args.Length() && args[0]->IsObject()) {
- // Standard version, object argument.
- v8::Local<v8::Object> suggestion_json =
- v8::Local<v8::Object>::Cast(args[0]);
- v8::Local<v8::Value> suggestions_field =
- suggestion_json->Get(v8::String::New("suggestions"));
+ v8::Local<v8::Value> suggestions_field(
+ suggestion_json->Get(v8::String::New("suggestions")));
if (suggestions_field->IsArray()) {
- v8::Local<v8::Array> suggestions_array =
- suggestions_field.As<v8::Array>();
-
- uint32_t length = suggestions_array->Length();
- for (uint32_t i = 0; i < length; i++) {
- v8::Local<v8::Value> suggestion_value =
- suggestions_array->Get(v8::Integer::New(i));
+ v8::Local<v8::Array> suggestions_array(
+ suggestions_field.As<v8::Array>());
+ size_t length = suggestions_array->Length();
+ for (size_t i = 0; i < length; i++) {
+ v8::Local<v8::Value> suggestion_value(suggestions_array->Get(i));
if (!suggestion_value->IsObject()) continue;
- v8::Local<v8::Object> suggestion_object =
- suggestion_value.As<v8::Object>();
- v8::Local<v8::Value> suggestion_object_value =
- suggestion_object->Get(v8::String::New("value"));
+ v8::Local<v8::Object> suggestion_object(suggestion_value->ToObject());
+ v8::Local<v8::Value> suggestion_object_value(
+ suggestion_object->Get(v8::String::New("value")));
if (!suggestion_object_value->IsString()) continue;
- std::string suggestion = *v8::String::Utf8Value(
- suggestion_object_value->ToString());
- if (!suggestion.length()) continue;
- suggestions.push_back(suggestion);
+ std::string text = *v8::String::Utf8Value(suggestion_object_value);
+
+ suggestions.push_back(InstantSuggestion(text, behavior, type));
}
}
- if (suggestion_json->Has(v8::String::New("complete_behavior"))) {
- v8::Local<v8::Value> complete_value =
- suggestion_json->Get(v8::String::New("complete_behavior"));
- if (complete_value->IsString()) {
- if (complete_value->Equals(v8::String::New("never")))
- behavior = INSTANT_COMPLETE_NEVER;
- else if (complete_value->Equals(v8::String::New("delayed")))
- behavior = INSTANT_COMPLETE_DELAYED;
+ }
+
+ if (content::RenderView* render_view = GetRenderView())
+ SearchBox::Get(render_view)->SetSuggestions(suggestions);
+ return v8::Undefined();
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetAutocompleteText(
+ const v8::Arguments& args) {
+ if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsString()) {
+ std::string text = *v8::String::Utf8Value(args[0]);
+ InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW;
+ InstantSuggestionType type = INSTANT_SUGGESTION_URL;
+
+ if (args.Length() >= 2 && args[1]->Uint32Value() == 2) {
+ behavior = INSTANT_COMPLETE_NEVER;
+ // TODO(sreeram): The page should really set the type explicitly.
+ type = INSTANT_SUGGESTION_SEARCH;
+ }
+
+ if (content::RenderView* render_view = GetRenderView()) {
+ std::vector<InstantSuggestion> suggestions;
+ suggestions.push_back(InstantSuggestion(text, behavior, type));
+ SearchBox::Get(render_view)->SetSuggestions(suggestions);
+ }
+ }
+ return v8::Undefined();
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetRestrictedAutocompleteText(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsNumber() &&
+ render_view) {
+ const int rid = args[0]->Uint32Value();
+ const int rid_base = SearchBox::Get(render_view)->rid_base();
+ // Note that stale rids, less than the current rid_base, will wrap.
+ const size_t index = rid - rid_base;
+ const std::vector<InstantNativeSuggestionsParts>& suggestions =
+ SearchBox::Get(render_view)->native_suggestions();
+ if (index < suggestions.size()) {
+ std::string text = suggestions[index].destination_url.spec();
+ InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW;
+ InstantSuggestionType type = INSTANT_SUGGESTION_URL;
+
+ if (args.Length() >= 2 && args[1]->Uint32Value() == 2)
+ behavior = INSTANT_COMPLETE_NEVER;
+
+ if (suggestions[index].is_search) {
+ text = suggestions[index].contents;
+ type = INSTANT_SUGGESTION_SEARCH;
}
+
+ std::vector<InstantSuggestion> suggestions;
+ suggestions.push_back(InstantSuggestion(text, behavior, type));
+ SearchBox::Get(render_view)->SetSuggestions(suggestions);
+ } else {
+ VLOG(1) << "Invalid rid " << rid << "; "
+ << "rid_base is " << rid_base << ".";
}
}
+ return v8::Undefined();
+}
- if (content::RenderView* render_view = GetRenderView())
- SearchBox::Get(render_view)->SetSuggestions(suggestions, behavior);
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetValue(
+ const v8::Arguments& args) {
+ // TODO(sreeram): Make the second argument (type) mandatory.
+ if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsString()) {
+ std::string text = *v8::String::Utf8Value(args[0]);
+ InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE;
+ InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH;
+
+ if (args.Length() >= 2 && args[1]->Uint32Value() == 1)
+ type = INSTANT_SUGGESTION_URL;
+
+ if (content::RenderView* render_view = GetRenderView()) {
+ std::vector<InstantSuggestion> suggestions;
+ suggestions.push_back(InstantSuggestion(text, behavior, type));
+ SearchBox::Get(render_view)->SetSuggestions(suggestions);
+ }
+ }
return v8::Undefined();
}
// static
-void Dispatch(WebFrame* frame,
- WebString event_dispatch_script,
- WebString no_event_handler_script) {
- DCHECK(frame) << "Dispatch requires frame";
- if (!frame)
- return;
-
- v8::Handle<v8::Value> result = frame->executeScriptAndReturnValue(
- WebScriptSource(event_dispatch_script));
- if (result.IsEmpty() || result->IsUndefined() || result->IsNull() ||
- result->IsFalse()) {
- frame->executeScript(WebScriptSource(no_event_handler_script));
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetRestrictedValue(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsNumber() &&
+ render_view) {
+ const int rid = args[0]->Uint32Value();
+ const int rid_base = SearchBox::Get(render_view)->rid_base();
+ // Note that stale rids, less than the current rid_base, will wrap.
+ const size_t index = rid - rid_base;
+ const std::vector<InstantNativeSuggestionsParts>& suggestions =
+ SearchBox::Get(render_view)->native_suggestions();
+ if (index < suggestions.size()) {
+ std::string text = suggestions[index].destination_url.spec();
+ InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE;
+ InstantSuggestionType type = INSTANT_SUGGESTION_URL;
+
+ if ((args.Length() >= 2 && args[1]->Uint32Value() == 0) ||
+ (args.Length() < 2 && suggestions[index].is_search)) {
+ text = suggestions[index].contents;
+ type = INSTANT_SUGGESTION_SEARCH;
+ }
+
+ std::vector<InstantSuggestion> suggestions;
+ suggestions.push_back(InstantSuggestion(text, behavior, type));
+ SearchBox::Get(render_view)->SetSuggestions(suggestions);
+ } else {
+ VLOG(1) << "Invalid rid " << rid << "; "
+ << "rid_base is " << rid_base << ".";
+ }
}
+ return v8::Undefined();
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetNonNativeDropdownHeight(
+ const v8::Arguments& args) {
+ if (args.Length() == 1) {
+ int height = 0;
+ InstantSizeUnits units = INSTANT_SIZE_PIXELS;
+ if (args[0]->IsInt32()) {
+ height = args[0]->Int32Value();
+ } else if (args[0]->IsString()) {
+ std::string height_str = *v8::String::Utf8Value(args[0]);
+ std::string units_str;
+ SplitLeadingNumberToken(&height_str, &units_str);
+ if (!base::StringToInt(height_str, &height))
+ return v8::Undefined();
+ if (units_str == "%") {
+ units = INSTANT_SIZE_PERCENT;
+ } else if (!units_str.empty() && units_str != "px") {
+ return v8::Undefined();
+ }
+ } else {
+ return v8::Undefined();
+ }
+ content::RenderView* render_view = GetRenderView();
+ if (render_view && height >= 0)
+ SearchBox::Get(render_view)->SetInstantPreviewHeight(height, units);
+ }
+ return v8::Undefined();
+}
+
+// static
+v8::Handle<v8::Value> SearchBoxExtensionWrapper::NavigateContentWindow(
+ const v8::Arguments& args) {
+ content::RenderView* render_view = GetRenderView();
+ if (args.Length() == 1 && args[0]->IsNumber() && render_view) {
+ const int rid = args[0]->Uint32Value();
+ const int rid_base = SearchBox::Get(render_view)->rid_base();
+ // Note that stale rids, less than the current rid_base, will wrap.
+ const size_t index = rid - rid_base;
+ const std::vector<InstantNativeSuggestionsParts>& suggestions =
+ SearchBox::Get(render_view)->native_suggestions();
+ if (index < suggestions.size()) {
+ // Navigate directly to the selected URL.
+ // TODO(sreeram): SECURITY RISK! Disconnect the InstantLoader and call
+ // SearchBox::Reset to not leak sensitive data to the new page.
+ WebKit::WebURLRequest request(suggestions[index].destination_url);
+ render_view->GetWebView()->mainFrame()->loadRequest(request);
+ } else {
+ VLOG(1) << "Invalid rid " << rid << "; "
+ << "rid_base is " << rid_base << ".";
+ }
+ }
+ return v8::Undefined();
+}
+
+// static
+void Dispatch(WebFrame* frame, WebString event_dispatch_script) {
+ DCHECK(frame) << "Dispatch requires frame";
+ if (!frame) return;
+ frame->executeScript(WebScriptSource(event_dispatch_script));
}
// static
void SearchBoxExtension::DispatchChange(WebFrame* frame) {
- Dispatch(frame, kDispatchChangeEventScript, kUserInputScript);
+ Dispatch(frame, kDispatchChangeEventScript);
}
// static
void SearchBoxExtension::DispatchSubmit(WebFrame* frame) {
- Dispatch(frame, kDispatchSubmitEventScript, kUserDoneScript);
+ Dispatch(frame, kDispatchSubmitEventScript);
}
// static
void SearchBoxExtension::DispatchCancel(WebFrame* frame) {
- Dispatch(frame, kDispatchCancelEventScript, kUserDoneScript);
+ Dispatch(frame, kDispatchCancelEventScript);
}
// static
void SearchBoxExtension::DispatchResize(WebFrame* frame) {
- Dispatch(frame, kDispatchResizeEventScript, kSetOmniboxBoundsScript);
+ Dispatch(frame, kDispatchResizeEventScript);
+}
+
+// static
+void SearchBoxExtension::DispatchNativeSuggestions(WebFrame* frame) {
+ Dispatch(frame, kDispatchNativeSuggestionsEventScript);
+}
+
+// static
+void SearchBoxExtension::DispatchKeyPress(WebFrame* frame) {
+ Dispatch(frame, kDispatchKeyPressEventScript);
+}
+
+// static
+void SearchBoxExtension::DispatchFocus(WebFrame* frame) {
+ Dispatch(frame, kDispatchFocusEventScript);
+}
+
+// static
+void SearchBoxExtension::DispatchBlur(WebFrame* frame) {
+ Dispatch(frame, kDispatchBlurEventScript);
}
// static
@@ -390,20 +679,14 @@ bool SearchBoxExtension::PageSupportsInstant(WebFrame* frame) {
v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue(
WebScriptSource(kSupportsInstantScript));
- bool supports_deprecated_api = !v.IsEmpty() && v->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.
- CR_DEFINE_STATIC_LOCAL(std::string, init_script,
- (StringPrintf(kInitScript, kSetOmniboxBoundsScript, kUserInputScript)));
- if (supports_deprecated_api) {
- frame->executeScript(WebScriptSource(WebString::fromUTF8(init_script)));
+ if (!v.IsEmpty() && v->BooleanValue()) {
+ // Send a resize message to tell the page that Chrome is actively using
+ // the searchbox API with it. The page uses the message to transition from
+ // "homepage" mode to "search" mode.
+ DispatchResize(frame);
+ return true;
}
-
- return supports_searchbox_api || supports_deprecated_api;
+ return false;
}
// static
« no previous file with comments | « chrome/renderer/searchbox_extension.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698