OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/searchbox/searchbox_extension.h" | 5 #include "chrome/renderer/searchbox/searchbox_extension.h" |
6 | 6 |
7 #include <ctype.h> | |
8 #include <vector> | |
9 | |
10 #include "base/string_number_conversions.h" | |
11 #include "base/string_piece.h" | |
12 #include "base/string_util.h" | |
13 #include "base/utf_string_conversions.h" | |
7 #include "chrome/renderer/searchbox/searchbox.h" | 14 #include "chrome/renderer/searchbox/searchbox.h" |
8 #include "content/public/renderer/render_view.h" | 15 #include "content/public/renderer/render_view.h" |
9 #include "grit/renderer_resources.h" | 16 #include "grit/renderer_resources.h" |
10 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | |
12 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
13 #include "v8/include/v8.h" | 21 #include "v8/include/v8.h" |
14 | 22 |
23 namespace { | |
24 | |
25 // Splits the string in |number| into two pieces, a leading number token (saved | |
26 // in |number|) and the rest (saved in |suffix|). Either piece may become empty, | |
27 // depending on whether the input had no digits or only digits. Neither argument | |
28 // may be NULL. | |
29 void SplitLeadingNumberToken(std::string* number, std::string* suffix) { | |
30 size_t i = 0; | |
31 while (i < number->size() && isdigit((*number)[i])) | |
32 ++i; | |
33 suffix->assign(*number, i, number->size() - i); | |
34 number->resize(i); | |
35 } | |
36 | |
37 // Converts a V8 String to a UTF16 string16. | |
38 // This code also exists in net/proxy/proxy_resolver_v8.cc. | |
39 // TODO(shishir): Find a common place for this function. | |
40 string16 V8StringToUTF16(v8::Handle<v8::String> s) { | |
41 int len = s->Length(); | |
42 string16 result; | |
43 // Note that the reinterpret cast is because on Windows string16 is an alias | |
44 // to wstring, and hence has character type wchar_t not uint16_t. | |
45 if (len > 0) | |
46 s->Write(reinterpret_cast<uint16_t*>(WriteInto(&result, len + 1)), 0, len); | |
sreeram
2012/08/13 22:40:56
How about this instead?
string16 V8ValueToUTF16(v8
Shishir
2012/08/13 23:24:36
Done with minor modifications.
| |
47 return result; | |
48 } | |
49 | |
50 } // namespace | |
51 | |
15 namespace extensions_v8 { | 52 namespace extensions_v8 { |
16 | 53 |
17 static const char kSearchBoxExtensionName[] = "v8/SearchBox"; | 54 static const char kSearchBoxExtensionName[] = "v8/SearchBox"; |
18 | 55 |
19 static const char kDispatchChangeEventScript[] = | 56 static const char kDispatchChangeEventScript[] = |
20 "if (window.chrome &&" | 57 "if (window.chrome &&" |
21 " window.chrome.searchBox &&" | 58 " window.chrome.searchBox &&" |
22 " window.chrome.searchBox.onchange &&" | 59 " window.chrome.searchBox.onchange &&" |
23 " typeof window.chrome.searchBox.onchange == 'function') {" | 60 " typeof window.chrome.searchBox.onchange == 'function') {" |
24 " window.chrome.searchBox.onchange();" | 61 " window.chrome.searchBox.onchange();" |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 static const char kSupportsInstantScript[] = | 93 static const char kSupportsInstantScript[] = |
57 "if (window.chrome &&" | 94 "if (window.chrome &&" |
58 " window.chrome.searchBox &&" | 95 " window.chrome.searchBox &&" |
59 " window.chrome.searchBox.onsubmit &&" | 96 " window.chrome.searchBox.onsubmit &&" |
60 " typeof window.chrome.searchBox.onsubmit == 'function') {" | 97 " typeof window.chrome.searchBox.onsubmit == 'function') {" |
61 " true;" | 98 " true;" |
62 "} else {" | 99 "} else {" |
63 " false;" | 100 " false;" |
64 "}"; | 101 "}"; |
65 | 102 |
103 // Extended API. | |
104 static const char kDispatchAutocompleteResultsEventScript[] = | |
105 "if (window.chrome &&" | |
106 " window.chrome.searchBox &&" | |
107 " window.chrome.searchBox.onnativesuggestions &&" | |
108 " typeof window.chrome.searchBox.onnativesuggestions == 'function') {" | |
109 " window.chrome.searchBox.onnativesuggestions();" | |
110 " true;" | |
111 "}"; | |
112 | |
113 static const char kDispatchKeyPressEventScript[] = | |
114 "if (window.chrome &&" | |
115 " window.chrome.searchBox &&" | |
116 " window.chrome.searchBox.onkeypress &&" | |
117 " typeof window.chrome.searchBox.onkeypress == 'function') {" | |
118 " window.chrome.searchBox.onkeypress(" | |
119 " {keyCode:window.chrome.searchBox.keyCode});" | |
120 " true;" | |
121 "}"; | |
122 | |
66 // ---------------------------------------------------------------------------- | 123 // ---------------------------------------------------------------------------- |
67 | 124 |
68 class SearchBoxExtensionWrapper : public v8::Extension { | 125 class SearchBoxExtensionWrapper : public v8::Extension { |
69 public: | 126 public: |
70 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); | 127 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); |
71 | 128 |
72 // Allows v8's javascript code to call the native functions defined | 129 // Allows v8's javascript code to call the native functions defined |
73 // in this class for window.chrome. | 130 // in this class for window.chrome. |
74 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 131 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
75 v8::Handle<v8::String> name); | 132 v8::Handle<v8::String> name); |
76 | 133 |
77 // Helper function to find the RenderView. May return NULL. | 134 // Helper function to find the RenderView. May return NULL. |
78 static content::RenderView* GetRenderView(); | 135 static content::RenderView* GetRenderView(); |
79 | 136 |
80 // Gets the value of the user's search query. | 137 // Gets the value of the user's search query. |
81 static v8::Handle<v8::Value> GetValue(const v8::Arguments& args); | 138 static v8::Handle<v8::Value> GetQuery(const v8::Arguments& args); |
82 | 139 |
83 // Gets whether the |value| should be considered final -- as opposed to a | 140 // Gets whether the |value| should be considered final -- as opposed to a |
84 // partial match. This may be set if the user clicks a suggestion, presses | 141 // partial match. This may be set if the user clicks a suggestion, presses |
85 // forward delete, or in other cases where Chrome overrides. | 142 // forward delete, or in other cases where Chrome overrides. |
86 static v8::Handle<v8::Value> GetVerbatim(const v8::Arguments& args); | 143 static v8::Handle<v8::Value> GetVerbatim(const v8::Arguments& args); |
87 | 144 |
88 // Gets the start of the selection in the search box. | 145 // Gets the start of the selection in the search box. |
89 static v8::Handle<v8::Value> GetSelectionStart(const v8::Arguments& args); | 146 static v8::Handle<v8::Value> GetSelectionStart(const v8::Arguments& args); |
90 | 147 |
91 // Gets the end of the selection in the search box. | 148 // Gets the end of the selection in the search box. |
92 static v8::Handle<v8::Value> GetSelectionEnd(const v8::Arguments& args); | 149 static v8::Handle<v8::Value> GetSelectionEnd(const v8::Arguments& args); |
93 | 150 |
94 // Gets the x coordinate (relative to |window|) of the left edge of the | 151 // Gets the x coordinate (relative to |window|) of the left edge of the |
95 // region of the search box that overlaps the window. | 152 // region of the search box that overlaps the window. |
96 static v8::Handle<v8::Value> GetX(const v8::Arguments& args); | 153 static v8::Handle<v8::Value> GetX(const v8::Arguments& args); |
97 | 154 |
98 // Gets the y coordinate (relative to |window|) of the right edge of the | 155 // Gets the y coordinate (relative to |window|) of the right edge of the |
99 // region of the search box that overlaps the window. | 156 // region of the search box that overlaps the window. |
100 static v8::Handle<v8::Value> GetY(const v8::Arguments& args); | 157 static v8::Handle<v8::Value> GetY(const v8::Arguments& args); |
101 | 158 |
102 // Gets the width of the region of the search box that overlaps the window. | 159 // Gets the width of the region of the search box that overlaps the window. |
103 static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args); | 160 static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args); |
104 | 161 |
105 // Gets the height of the region of the search box that overlaps the window. | 162 // Gets the height of the region of the search box that overlaps the window. |
106 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); | 163 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); |
107 | 164 |
165 // Gets the autocomplete results from search box. | |
166 static v8::Handle<v8::Value> GetAutocompleteResults( | |
167 const v8::Arguments& args); | |
168 | |
169 // Gets the last key code entered in search box. | |
170 static v8::Handle<v8::Value> GetKeyCode(const v8::Arguments& args); | |
171 | |
108 // Sets ordered suggestions. Valid for current |value|. | 172 // Sets ordered suggestions. Valid for current |value|. |
109 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); | 173 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); |
110 | 174 |
175 // Sets the text to be autocompleted into the search box. | |
176 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); | |
177 | |
178 // Like |SetQuerySuggestion| but uses a restricted ID to identify the text. | |
179 static v8::Handle<v8::Value> SetQuerySuggestionFromAutocompleteResult( | |
180 const v8::Arguments& args); | |
181 | |
182 // Sets the search box text, completely replacing what the user typed. | |
183 static v8::Handle<v8::Value> SetQuery(const v8::Arguments& args); | |
184 | |
185 // Like |SetQuery| but uses a restricted ID to identify the text. | |
186 static v8::Handle<v8::Value> SetQueryFromAutocompleteResult( | |
187 const v8::Arguments& args); | |
188 | |
189 // Resize the preview to the given height. | |
190 static v8::Handle<v8::Value> SetPreviewHeight(const v8::Arguments& args); | |
191 | |
111 private: | 192 private: |
112 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper); | 193 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper); |
113 }; | 194 }; |
114 | 195 |
115 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper( | 196 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper( |
116 const base::StringPiece& code) | 197 const base::StringPiece& code) |
117 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) { | 198 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) { |
118 } | 199 } |
119 | 200 |
120 v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction( | 201 v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction( |
121 v8::Handle<v8::String> name) { | 202 v8::Handle<v8::String> name) { |
122 if (name->Equals(v8::String::New("GetValue"))) { | 203 if (name->Equals(v8::String::New("GetQuery"))) { |
123 return v8::FunctionTemplate::New(GetValue); | 204 return v8::FunctionTemplate::New(GetQuery); |
124 } else if (name->Equals(v8::String::New("GetVerbatim"))) { | 205 } else if (name->Equals(v8::String::New("GetVerbatim"))) { |
125 return v8::FunctionTemplate::New(GetVerbatim); | 206 return v8::FunctionTemplate::New(GetVerbatim); |
126 } else if (name->Equals(v8::String::New("GetSelectionStart"))) { | 207 } else if (name->Equals(v8::String::New("GetSelectionStart"))) { |
127 return v8::FunctionTemplate::New(GetSelectionStart); | 208 return v8::FunctionTemplate::New(GetSelectionStart); |
128 } else if (name->Equals(v8::String::New("GetSelectionEnd"))) { | 209 } else if (name->Equals(v8::String::New("GetSelectionEnd"))) { |
129 return v8::FunctionTemplate::New(GetSelectionEnd); | 210 return v8::FunctionTemplate::New(GetSelectionEnd); |
130 } else if (name->Equals(v8::String::New("GetX"))) { | 211 } else if (name->Equals(v8::String::New("GetX"))) { |
131 return v8::FunctionTemplate::New(GetX); | 212 return v8::FunctionTemplate::New(GetX); |
132 } else if (name->Equals(v8::String::New("GetY"))) { | 213 } else if (name->Equals(v8::String::New("GetY"))) { |
133 return v8::FunctionTemplate::New(GetY); | 214 return v8::FunctionTemplate::New(GetY); |
134 } else if (name->Equals(v8::String::New("GetWidth"))) { | 215 } else if (name->Equals(v8::String::New("GetWidth"))) { |
135 return v8::FunctionTemplate::New(GetWidth); | 216 return v8::FunctionTemplate::New(GetWidth); |
136 } else if (name->Equals(v8::String::New("GetHeight"))) { | 217 } else if (name->Equals(v8::String::New("GetHeight"))) { |
137 return v8::FunctionTemplate::New(GetHeight); | 218 return v8::FunctionTemplate::New(GetHeight); |
219 } else if (name->Equals(v8::String::New("GetAutocompleteResults"))) { | |
220 return v8::FunctionTemplate::New(GetAutocompleteResults); | |
221 } else if (name->Equals(v8::String::New("GetKeyCode"))) { | |
222 return v8::FunctionTemplate::New(GetKeyCode); | |
138 } else if (name->Equals(v8::String::New("SetSuggestions"))) { | 223 } else if (name->Equals(v8::String::New("SetSuggestions"))) { |
139 return v8::FunctionTemplate::New(SetSuggestions); | 224 return v8::FunctionTemplate::New(SetSuggestions); |
225 } else if (name->Equals(v8::String::New("SetQuerySuggestion"))) { | |
226 return v8::FunctionTemplate::New(SetQuerySuggestion); | |
227 } else if (name->Equals(v8::String::New( | |
228 "SetQuerySuggestionFromAutocompleteResult"))) { | |
229 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); | |
230 } else if (name->Equals(v8::String::New("SetQuery"))) { | |
231 return v8::FunctionTemplate::New(SetQuery); | |
232 } else if (name->Equals(v8::String::New("SetQueryFromAutocompleteResult"))) { | |
233 return v8::FunctionTemplate::New(SetQueryFromAutocompleteResult); | |
234 } else if (name->Equals(v8::String::New("SetPreviewHeight"))) { | |
235 return v8::FunctionTemplate::New(SetPreviewHeight); | |
140 } | 236 } |
141 return v8::Handle<v8::FunctionTemplate>(); | 237 return v8::Handle<v8::FunctionTemplate>(); |
142 } | 238 } |
143 | 239 |
144 // static | 240 // static |
145 content::RenderView* SearchBoxExtensionWrapper::GetRenderView() { | 241 content::RenderView* SearchBoxExtensionWrapper::GetRenderView() { |
146 WebKit::WebFrame* webframe = WebKit::WebFrame::frameForEnteredContext(); | 242 WebKit::WebFrame* webframe = WebKit::WebFrame::frameForEnteredContext(); |
147 DCHECK(webframe) << "There should be an active frame since we just got " | 243 DCHECK(webframe) << "There should be an active frame since we just got " |
148 "a native function called."; | 244 "a native function called."; |
149 if (!webframe) return NULL; | 245 if (!webframe) return NULL; |
150 | 246 |
151 WebKit::WebView* webview = webframe->view(); | 247 WebKit::WebView* webview = webframe->view(); |
152 if (!webview) return NULL; // can happen during closing | 248 if (!webview) return NULL; // can happen during closing |
153 | 249 |
154 return content::RenderView::FromWebView(webview); | 250 return content::RenderView::FromWebView(webview); |
155 } | 251 } |
156 | 252 |
157 // static | 253 // static |
158 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetValue( | 254 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetQuery( |
159 const v8::Arguments& args) { | 255 const v8::Arguments& args) { |
160 content::RenderView* render_view = GetRenderView(); | 256 content::RenderView* render_view = GetRenderView(); |
161 if (!render_view) return v8::Undefined(); | 257 if (!render_view) return v8::Undefined(); |
162 return v8::String::New( | 258 return v8::String::New( |
163 reinterpret_cast<const uint16_t*>( | 259 reinterpret_cast<const uint16_t*>( |
164 SearchBox::Get(render_view)->value().data()), | 260 SearchBox::Get(render_view)->query().data()), |
165 SearchBox::Get(render_view)->value().length()); | 261 SearchBox::Get(render_view)->query().length()); |
sreeram
2012/08/13 22:40:56
This can be simplified to:
return UTF16ToV8String(
Shishir
2012/08/13 23:24:36
Done.
| |
166 } | 262 } |
167 | 263 |
168 // static | 264 // static |
169 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetVerbatim( | 265 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetVerbatim( |
170 const v8::Arguments& args) { | 266 const v8::Arguments& args) { |
171 content::RenderView* render_view = GetRenderView(); | 267 content::RenderView* render_view = GetRenderView(); |
172 if (!render_view) return v8::Undefined(); | 268 if (!render_view) return v8::Undefined(); |
173 return v8::Boolean::New(SearchBox::Get(render_view)->verbatim()); | 269 return v8::Boolean::New(SearchBox::Get(render_view)->verbatim()); |
174 } | 270 } |
175 | 271 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 | 311 |
216 // static | 312 // static |
217 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetHeight( | 313 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetHeight( |
218 const v8::Arguments& args) { | 314 const v8::Arguments& args) { |
219 content::RenderView* render_view = GetRenderView(); | 315 content::RenderView* render_view = GetRenderView(); |
220 if (!render_view) return v8::Undefined(); | 316 if (!render_view) return v8::Undefined(); |
221 return v8::Int32::New(SearchBox::Get(render_view)->GetRect().height()); | 317 return v8::Int32::New(SearchBox::Get(render_view)->GetRect().height()); |
222 } | 318 } |
223 | 319 |
224 // static | 320 // static |
321 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetAutocompleteResults( | |
322 const v8::Arguments& args) { | |
323 content::RenderView* render_view = GetRenderView(); | |
324 if (!render_view) return v8::Undefined(); | |
325 const std::vector<InstantAutocompleteResult>& results = | |
326 SearchBox::Get(render_view)->autocomplete_results(); | |
327 const int results_base = SearchBox::Get(render_view)->results_base(); | |
328 v8::Handle<v8::Array> results_array = v8::Array::New(results.size()); | |
329 for (size_t i = 0; i < results.size(); ++i) { | |
330 v8::Handle<v8::Object> result = v8::Object::New(); | |
331 const string16& provider = results[i].provider; | |
332 result->Set( | |
333 v8::String::New("provider"), | |
334 v8::String::New(reinterpret_cast<const uint16_t*>(provider.data()), | |
335 provider.length())); | |
336 const string16& contents = results[i].contents; | |
337 result->Set( | |
338 v8::String::New("contents"), | |
339 v8::String::New(reinterpret_cast<const uint16_t*>(contents.data()), | |
340 contents.length())); | |
sreeram
2012/08/13 22:40:56
These can be simplified to:
result->Set(v8::Stri
Shishir
2012/08/13 23:24:36
Done.
| |
341 result->Set(v8::String::New("destination_url"), | |
342 v8::String::New(results[i].destination_url.spec().c_str())); | |
343 result->Set(v8::String::New("rid"), v8::Uint32::New(results_base + i)); | |
344 | |
345 v8::Handle<v8::Object> ranking_data = v8::Object::New(); | |
346 ranking_data->Set(v8::String::New("relevance"), | |
347 v8::Int32::New(results[i].relevance)); | |
348 result->Set(v8::String::New("rankingData"), ranking_data); | |
349 | |
350 results_array->Set(i, result); | |
351 } | |
352 | |
353 return results_array; | |
354 } | |
355 | |
356 // static | |
357 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetKeyCode( | |
358 const v8::Arguments& args) { | |
359 content::RenderView* render_view = GetRenderView(); | |
360 if (!render_view) return v8::Undefined(); | |
361 return v8::Int32::New(SearchBox::Get(render_view)->key_code()); | |
362 } | |
363 | |
364 // static | |
225 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions( | 365 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions( |
226 const v8::Arguments& args) { | 366 const v8::Arguments& args) { |
227 std::vector<string16> suggestions; | 367 std::vector<InstantSuggestion> suggestions; |
228 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
229 | 368 |
230 if (args.Length() && args[0]->IsObject()) { | 369 if (args.Length() && args[0]->IsObject()) { |
231 v8::Local<v8::Object> suggestion_json = args[0]->ToObject(); | 370 v8::Local<v8::Object> suggestion_json = args[0]->ToObject(); |
sreeram
2012/08/13 22:40:56
I'm not sure why we refer to v8::Local explicitly,
Shishir
2012/08/13 23:24:36
Done.
| |
232 | 371 |
372 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
373 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; | |
233 v8::Local<v8::Value> complete_value = | 374 v8::Local<v8::Value> complete_value = |
234 suggestion_json->Get(v8::String::New("complete_behavior")); | 375 suggestion_json->Get(v8::String::New("complete_behavior")); |
235 if (complete_value->IsString()) { | 376 if (complete_value->IsString()) { |
236 if (complete_value->Equals(v8::String::New("now"))) { | 377 if (complete_value->Equals(v8::String::New("now"))) { |
237 behavior = INSTANT_COMPLETE_NOW; | 378 behavior = INSTANT_COMPLETE_NOW; |
238 } else if (complete_value->Equals(v8::String::New("never"))) { | 379 } else if (complete_value->Equals(v8::String::New("never"))) { |
239 behavior = INSTANT_COMPLETE_NEVER; | 380 behavior = INSTANT_COMPLETE_NEVER; |
240 } else if (complete_value->Equals(v8::String::New("delayed"))) { | 381 } else if (complete_value->Equals(v8::String::New("delayed"))) { |
241 behavior = INSTANT_COMPLETE_DELAYED; | 382 behavior = INSTANT_COMPLETE_DELAYED; |
383 } else if (complete_value->Equals(v8::String::New("replace"))) { | |
384 behavior = INSTANT_COMPLETE_REPLACE; | |
242 } else { | 385 } else { |
243 VLOG(1) << "Unsupported complete behavior '" | 386 VLOG(1) << "Unsupported complete behavior '" |
244 << *v8::String::Utf8Value(complete_value) << "'"; | 387 << *v8::String::Utf8Value(complete_value) << "'"; |
245 } | 388 } |
246 } | 389 } |
247 | |
248 v8::Local<v8::Value> suggestions_field = | 390 v8::Local<v8::Value> suggestions_field = |
249 suggestion_json->Get(v8::String::New("suggestions")); | 391 suggestion_json->Get(v8::String::New("suggestions")); |
250 | |
251 if (suggestions_field->IsArray()) { | 392 if (suggestions_field->IsArray()) { |
252 v8::Local<v8::Array> suggestions_array = | 393 v8::Local<v8::Array> suggestions_array = |
253 suggestions_field.As<v8::Array>(); | 394 suggestions_field.As<v8::Array>(); |
254 | |
255 size_t length = suggestions_array->Length(); | 395 size_t length = suggestions_array->Length(); |
256 for (size_t i = 0; i < length; i++) { | 396 for (size_t i = 0; i < length; i++) { |
257 v8::Local<v8::Value> suggestion_value = suggestions_array->Get(i); | 397 v8::Local<v8::Value> suggestion_value = suggestions_array->Get(i); |
258 if (!suggestion_value->IsObject()) continue; | 398 if (!suggestion_value->IsObject()) continue; |
259 | 399 |
260 v8::Local<v8::Object> suggestion_object = suggestion_value->ToObject(); | 400 v8::Local<v8::Object> suggestion_object = suggestion_value->ToObject(); |
261 v8::Local<v8::Value> suggestion_object_value = | 401 v8::Local<v8::Value> suggestion_object_value = |
262 suggestion_object->Get(v8::String::New("value")); | 402 suggestion_object->Get(v8::String::New("value")); |
263 if (!suggestion_object_value->IsString()) continue; | 403 if (!suggestion_object_value->IsString()) continue; |
404 string16 text = V8StringToUTF16(suggestion_object_value->ToString()); | |
sreeram
2012/08/13 22:40:56
This can be simplified to:
string16 text = V8Value
Shishir
2012/08/13 23:24:36
Done.
| |
264 | 405 |
265 string16 suggestion(reinterpret_cast<char16*>(*v8::String::Value( | 406 suggestions.push_back(InstantSuggestion(text, behavior, type)); |
266 suggestion_object_value->ToString()))); | |
267 suggestions.push_back(suggestion); | |
268 } | 407 } |
269 } | 408 } |
270 } | 409 } |
271 | 410 |
272 if (content::RenderView* render_view = GetRenderView()) | 411 if (content::RenderView* render_view = GetRenderView()) |
273 SearchBox::Get(render_view)->SetSuggestions(suggestions, behavior); | 412 SearchBox::Get(render_view)->SetSuggestions(suggestions); |
274 return v8::Undefined(); | 413 return v8::Undefined(); |
275 } | 414 } |
276 | 415 |
416 // static | |
417 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetQuerySuggestion( | |
418 const v8::Arguments& args) { | |
419 if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsString()) { | |
420 string16 text = V8StringToUTF16(args[0]->ToString()); | |
421 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
422 InstantSuggestionType type = INSTANT_SUGGESTION_URL; | |
423 | |
424 if (args.Length() >= 2 && args[1]->Uint32Value() == 2) { | |
425 behavior = INSTANT_COMPLETE_NEVER; | |
426 // TODO(sreeram): The page should really set the type explicitly. | |
427 type = INSTANT_SUGGESTION_SEARCH; | |
428 } | |
429 | |
430 if (content::RenderView* render_view = GetRenderView()) { | |
431 std::vector<InstantSuggestion> suggestions; | |
432 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
433 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
434 } | |
435 } | |
436 return v8::Undefined(); | |
437 } | |
438 | |
439 // static | |
440 v8::Handle<v8::Value> | |
441 SearchBoxExtensionWrapper::SetQuerySuggestionFromAutocompleteResult( | |
442 const v8::Arguments& args) { | |
443 content::RenderView* render_view = GetRenderView(); | |
444 if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsNumber() && | |
445 render_view) { | |
446 const int results_id = args[0]->Uint32Value(); | |
447 const int results_base = SearchBox::Get(render_view)->results_base(); | |
448 // Note that stale results_ids, less than the current results_base, will | |
449 // wrap. | |
450 const size_t index = results_id - results_base; | |
451 const std::vector<InstantAutocompleteResult>& suggestions = | |
452 SearchBox::Get(render_view)->autocomplete_results(); | |
453 if (index < suggestions.size()) { | |
454 string16 text = UTF8ToUTF16(suggestions[index].destination_url.spec()); | |
455 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
456 InstantSuggestionType type = INSTANT_SUGGESTION_URL; | |
457 | |
458 if (args.Length() >= 2 && args[1]->Uint32Value() == 2) | |
459 behavior = INSTANT_COMPLETE_NEVER; | |
460 | |
461 if (suggestions[index].is_search) { | |
462 text = suggestions[index].contents; | |
463 type = INSTANT_SUGGESTION_SEARCH; | |
464 } | |
465 | |
466 std::vector<InstantSuggestion> suggestions; | |
467 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
468 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
469 } else { | |
470 VLOG(1) << "Invalid results_id " << results_id << "; " | |
471 << "results_base is " << results_base << "."; | |
472 } | |
473 } | |
474 return v8::Undefined(); | |
475 } | |
476 | |
477 // static | |
478 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetQuery( | |
479 const v8::Arguments& args) { | |
480 // TODO(sreeram): Make the second argument (type) mandatory. | |
481 if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsString()) { | |
482 string16 text = V8StringToUTF16(args[0]->ToString()); | |
483 InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE; | |
484 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; | |
485 | |
486 if (args.Length() >= 2 && args[1]->Uint32Value() == 1) | |
487 type = INSTANT_SUGGESTION_URL; | |
488 | |
489 if (content::RenderView* render_view = GetRenderView()) { | |
490 std::vector<InstantSuggestion> suggestions; | |
491 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
492 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
493 } | |
494 } | |
495 return v8::Undefined(); | |
496 } | |
497 | |
498 v8::Handle<v8::Value> | |
499 SearchBoxExtensionWrapper::SetQueryFromAutocompleteResult( | |
500 const v8::Arguments& args) { | |
501 content::RenderView* render_view = GetRenderView(); | |
502 if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsNumber() && | |
503 render_view) { | |
504 const int results_id = args[0]->Uint32Value(); | |
505 const int results_base = SearchBox::Get(render_view)->results_base(); | |
506 // Note that stale results_ids, less than the current results_base, will | |
507 // wrap. | |
508 const size_t index = results_id - results_base; | |
509 const std::vector<InstantAutocompleteResult>& suggestions = | |
510 SearchBox::Get(render_view)->autocomplete_results(); | |
511 if (index < suggestions.size()) { | |
512 string16 text = UTF8ToUTF16(suggestions[index].destination_url.spec()); | |
513 InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE; | |
514 InstantSuggestionType type = INSTANT_SUGGESTION_URL; | |
515 | |
516 if ((args.Length() >= 2 && args[1]->Uint32Value() == 0) || | |
517 (args.Length() < 2 && suggestions[index].is_search)) { | |
518 text = suggestions[index].contents; | |
519 type = INSTANT_SUGGESTION_SEARCH; | |
520 } | |
521 | |
522 std::vector<InstantSuggestion> suggestions; | |
523 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
524 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
525 } else { | |
526 VLOG(1) << "Invalid results_id " << results_id << "; " | |
527 << "results_base is " << results_base << "."; | |
528 } | |
529 } | |
530 return v8::Undefined(); | |
531 } | |
532 | |
533 // static | |
534 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetPreviewHeight( | |
535 const v8::Arguments& args) { | |
536 if (args.Length() == 1) { | |
537 int height = 0; | |
538 InstantSizeUnits units = INSTANT_SIZE_PIXELS; | |
539 if (args[0]->IsInt32()) { | |
540 height = args[0]->Int32Value(); | |
541 } else if (args[0]->IsString()) { | |
542 std::string height_str = *v8::String::Utf8Value(args[0]); | |
543 std::string units_str; | |
544 SplitLeadingNumberToken(&height_str, &units_str); | |
545 if (!base::StringToInt(height_str, &height)) | |
546 return v8::Undefined(); | |
547 if (units_str == "%") { | |
548 units = INSTANT_SIZE_PERCENT; | |
549 } else if (!units_str.empty() && units_str != "px") { | |
550 return v8::Undefined(); | |
551 } | |
552 } else { | |
553 return v8::Undefined(); | |
554 } | |
555 content::RenderView* render_view = GetRenderView(); | |
556 if (render_view && height >= 0) | |
557 SearchBox::Get(render_view)->SetInstantPreviewHeight(height, units); | |
558 } | |
559 return v8::Undefined(); | |
560 } | |
561 | |
277 // static | 562 // static |
278 void Dispatch(WebKit::WebFrame* frame, WebKit::WebString script) { | 563 void Dispatch(WebKit::WebFrame* frame, WebKit::WebString script) { |
279 DCHECK(frame) << "Dispatch requires frame"; | 564 DCHECK(frame) << "Dispatch requires frame"; |
280 if (!frame) return; | 565 if (!frame) return; |
281 frame->executeScript(WebKit::WebScriptSource(script)); | 566 frame->executeScript(WebKit::WebScriptSource(script)); |
282 } | 567 } |
283 | 568 |
284 // static | 569 // static |
285 void SearchBoxExtension::DispatchChange(WebKit::WebFrame* frame) { | 570 void SearchBoxExtension::DispatchChange(WebKit::WebFrame* frame) { |
286 Dispatch(frame, kDispatchChangeEventScript); | 571 Dispatch(frame, kDispatchChangeEventScript); |
287 } | 572 } |
288 | 573 |
289 // static | 574 // static |
290 void SearchBoxExtension::DispatchSubmit(WebKit::WebFrame* frame) { | 575 void SearchBoxExtension::DispatchSubmit(WebKit::WebFrame* frame) { |
291 Dispatch(frame, kDispatchSubmitEventScript); | 576 Dispatch(frame, kDispatchSubmitEventScript); |
292 } | 577 } |
293 | 578 |
294 // static | 579 // static |
295 void SearchBoxExtension::DispatchCancel(WebKit::WebFrame* frame) { | 580 void SearchBoxExtension::DispatchCancel(WebKit::WebFrame* frame) { |
296 Dispatch(frame, kDispatchCancelEventScript); | 581 Dispatch(frame, kDispatchCancelEventScript); |
297 } | 582 } |
298 | 583 |
299 // static | 584 // static |
300 void SearchBoxExtension::DispatchResize(WebKit::WebFrame* frame) { | 585 void SearchBoxExtension::DispatchResize(WebKit::WebFrame* frame) { |
301 Dispatch(frame, kDispatchResizeEventScript); | 586 Dispatch(frame, kDispatchResizeEventScript); |
302 } | 587 } |
303 | 588 |
304 // static | 589 // static |
590 void SearchBoxExtension::DispatchAutocompleteResults(WebKit::WebFrame* frame) { | |
591 Dispatch(frame, kDispatchAutocompleteResultsEventScript); | |
592 } | |
593 | |
594 // static | |
595 void SearchBoxExtension::DispatchKeyPress(WebKit::WebFrame* frame) { | |
596 Dispatch(frame, kDispatchKeyPressEventScript); | |
597 } | |
598 | |
599 // static | |
305 bool SearchBoxExtension::PageSupportsInstant(WebKit::WebFrame* frame) { | 600 bool SearchBoxExtension::PageSupportsInstant(WebKit::WebFrame* frame) { |
306 DCHECK(frame) << "PageSupportsInstant requires frame"; | 601 DCHECK(frame) << "PageSupportsInstant requires frame"; |
307 if (!frame) return false; | 602 if (!frame) return false; |
308 | 603 |
309 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( | 604 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( |
310 WebKit::WebScriptSource(kSupportsInstantScript)); | 605 WebKit::WebScriptSource(kSupportsInstantScript)); |
311 bool supports_instant = !v.IsEmpty() && v->BooleanValue(); | 606 bool supports_instant = !v.IsEmpty() && v->BooleanValue(); |
312 | 607 |
313 // Send a resize message to tell the page that Chrome is actively using the | 608 // Send a resize message to tell the page that Chrome is actively using the |
314 // searchbox API with it. The page uses the message to transition from | 609 // searchbox API with it. The page uses the message to transition from |
315 // "homepage" mode to "search" mode. | 610 // "homepage" mode to "search" mode. |
316 if (supports_instant) | 611 if (supports_instant) |
317 DispatchResize(frame); | 612 DispatchResize(frame); |
318 | 613 |
319 return supports_instant; | 614 return supports_instant; |
320 } | 615 } |
321 | 616 |
322 // static | 617 // static |
323 v8::Extension* SearchBoxExtension::Get() { | 618 v8::Extension* SearchBoxExtension::Get() { |
324 const base::StringPiece code = | 619 const base::StringPiece code = |
325 ResourceBundle::GetSharedInstance().GetRawDataResource( | 620 ResourceBundle::GetSharedInstance().GetRawDataResource( |
326 IDR_SEARCHBOX_API, ui::SCALE_FACTOR_NONE); | 621 IDR_SEARCHBOX_API, ui::SCALE_FACTOR_NONE); |
327 return new SearchBoxExtensionWrapper(code); | 622 return new SearchBoxExtensionWrapper(code); |
328 } | 623 } |
329 | 624 |
330 } // namespace extensions_v8 | 625 } // namespace extensions_v8 |
OLD | NEW |