OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 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 "base/i18n/rtl.h" | |
8 #include "base/stringprintf.h" | |
9 #include "base/strings/string_number_conversions.h" | |
10 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
11 #include "chrome/common/extensions/extension.h" | 8 #include "chrome/common/instant_types.h" |
12 #include "chrome/renderer/searchbox/searchbox.h" | 9 #include "chrome/renderer/searchbox/searchbox.h" |
13 #include "content/public/renderer/render_view.h" | 10 #include "content/public/renderer/render_view.h" |
14 #include "grit/renderer_resources.h" | 11 #include "grit/renderer_resources.h" |
15 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h" | |
16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
19 #include "ui/base/keycodes/keyboard_codes.h" | |
20 #include "ui/base/resource/resource_bundle.h" | 15 #include "ui/base/resource/resource_bundle.h" |
21 #include "ui/base/window_open_disposition.h" | |
22 #include "v8/include/v8.h" | 16 #include "v8/include/v8.h" |
23 | 17 |
24 namespace { | 18 namespace { |
25 | 19 |
26 const char kCSSBackgroundImageFormat[] = "-webkit-image-set(" | 20 const char kSearchBoxExtensionName[] = "v8/SearchBox"; |
27 "url(chrome-search://theme/IDR_THEME_NTP_BACKGROUND?%s) 1x)"; | 21 |
28 | 22 const char kDetermineInstantSupportScript[] = |
29 const char kCSSBackgroundColorFormat[] = "rgba(%d,%d,%d,%s)"; | 23 "chrome &&" |
Jered
2013/03/26 16:36:42
Is it safe to omit window (could this have functio
| |
30 | 24 "chrome.searchBox &&" |
31 const char kCSSBackgroundPositionCenter[] = "center"; | 25 "chrome.searchBox.onsubmit &&" |
32 const char kCSSBackgroundPositionLeft[] = "left"; | 26 "typeof chrome.searchBox.onsubmit == 'function';"; |
33 const char kCSSBackgroundPositionTop[] = "top"; | 27 |
34 const char kCSSBackgroundPositionRight[] = "right"; | 28 const char kOnChangeScript[] = |
35 const char kCSSBackgroundPositionBottom[] = "bottom"; | 29 "if (chrome &&" |
36 | 30 " chrome.searchBox &&" |
37 const char kCSSBackgroundRepeatNo[] = "no-repeat"; | 31 " chrome.searchBox.onchange &&" |
38 const char kCSSBackgroundRepeatX[] = "repeat-x"; | 32 " typeof chrome.searchBox.onchange == 'function')" |
39 const char kCSSBackgroundRepeatY[] = "repeat-y"; | 33 " chrome.searchBox.onchange();"; |
40 const char kCSSBackgroundRepeat[] = "repeat"; | 34 |
41 | 35 const char kOnSubmitScript[] = |
42 const char kLTRHtmlTextDirection[] = "ltr"; | 36 "if (chrome &&" |
43 const char kRTLHtmlTextDirection[] = "rtl"; | 37 " chrome.searchBox &&" |
44 | 38 " chrome.searchBox.onsubmit &&" |
45 // Converts a V8 value to a string16. | 39 " typeof chrome.searchBox.onsubmit == 'function')" |
40 " chrome.searchBox.onsubmit();"; | |
41 | |
42 const char kOnBlurScript[] = | |
43 "if (chrome &&" | |
44 " chrome.searchBox &&" | |
45 " chrome.searchBox.oncancel &&" | |
46 " typeof chrome.searchBox.oncancel == 'function')" | |
47 " chrome.searchBox.oncancel();"; | |
48 | |
49 const char kOnPopupBoundsScript[] = | |
50 "if (chrome &&" | |
51 " chrome.searchBox &&" | |
52 " chrome.searchBox.onresize &&" | |
53 " typeof chrome.searchBox.onresize == 'function')" | |
54 " chrome.searchBox.onresize();"; | |
55 | |
46 string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { | 56 string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { |
47 v8::String::Value s(v); | 57 v8::String::Value s(v); |
48 return string16(reinterpret_cast<const char16*>(*s), s.length()); | 58 return string16(reinterpret_cast<const char16*>(*s), s.length()); |
49 } | 59 } |
50 | 60 |
51 // Converts string16 to V8 String. | |
52 v8::Handle<v8::String> UTF16ToV8String(const string16& s) { | 61 v8::Handle<v8::String> UTF16ToV8String(const string16& s) { |
53 return v8::String::New(reinterpret_cast<const uint16_t*>(s.data()), s.size()); | 62 return v8::String::New(reinterpret_cast<const uint16_t*>(s.data()), s.size()); |
54 } | 63 } |
55 | 64 |
56 // Converts std::string to V8 String. | 65 SearchBox* GetSearchBox() { |
57 v8::Handle<v8::String> UTF8ToV8String(const std::string& s) { | 66 WebKit::WebFrame* frame = WebKit::WebFrame::frameForCurrentContext(); |
58 return v8::String::New(s.data(), s.size()); | 67 // The WebView may be NULL during closing. |
59 } | 68 if (!frame || !frame->view()) |
60 | 69 return NULL; |
61 void Dispatch(WebKit::WebFrame* frame, const WebKit::WebString& script) { | 70 |
62 if (!frame) return; | 71 content::RenderView* render_view = |
63 frame->executeScript(WebKit::WebScriptSource(script)); | 72 content::RenderView::FromWebView(frame->view()); |
73 if (!render_view) | |
74 return NULL; | |
75 | |
76 return SearchBox::Get(render_view); | |
77 } | |
78 | |
79 WebKit::WebFrame* GetFrame(content::RenderView* render_view) { | |
80 return render_view->GetWebView() ? render_view->GetWebView()->mainFrame() : | |
81 NULL; | |
82 } | |
83 | |
84 void Dispatch(content::RenderView* render_view, | |
85 const WebKit::WebString& script) { | |
86 WebKit::WebFrame* frame = GetFrame(render_view); | |
87 if (frame) | |
88 frame->executeScript(WebKit::WebScriptSource(script)); | |
64 } | 89 } |
65 | 90 |
66 } // namespace | 91 } // namespace |
67 | 92 |
68 namespace extensions_v8 { | 93 namespace extensions_v8 { |
69 | 94 |
70 static const char kSearchBoxExtensionName[] = "v8/EmbeddedSearch"; | 95 // SearchBoxExtensionWrapper -------------------------------------------------- |
Jered
2013/03/26 16:36:42
Where did all this stuff go? :-)
| |
71 | |
72 static const char kDispatchChangeEventScript[] = | |
73 "if (window.chrome &&" | |
74 " window.chrome.embeddedSearch &&" | |
75 " window.chrome.embeddedSearch.searchBox &&" | |
76 " window.chrome.embeddedSearch.searchBox.onchange &&" | |
77 " typeof window.chrome.embeddedSearch.searchBox.onchange ==" | |
78 " 'function') {" | |
79 " window.chrome.embeddedSearch.searchBox.onchange();" | |
80 " true;" | |
81 "}"; | |
82 | |
83 static const char kDispatchSubmitEventScript[] = | |
84 "if (window.chrome &&" | |
85 " window.chrome.embeddedSearch &&" | |
86 " window.chrome.embeddedSearch.searchBox &&" | |
87 " window.chrome.embeddedSearch.searchBox.onsubmit &&" | |
88 " typeof window.chrome.embeddedSearch.searchBox.onsubmit ==" | |
89 " 'function') {" | |
90 " window.chrome.embeddedSearch.searchBox.onsubmit();" | |
91 " true;" | |
92 "}"; | |
93 | |
94 static const char kDispatchCancelEventScript[] = | |
95 "if (window.chrome &&" | |
96 " window.chrome.embeddedSearch &&" | |
97 " window.chrome.embeddedSearch.searchBox &&" | |
98 " window.chrome.embeddedSearch.searchBox.oncancel &&" | |
99 " typeof window.chrome.embeddedSearch.searchBox.oncancel ==" | |
100 " 'function') {" | |
101 " window.chrome.embeddedSearch.searchBox.oncancel();" | |
102 " true;" | |
103 "}"; | |
104 | |
105 static const char kDispatchResizeEventScript[] = | |
106 "if (window.chrome &&" | |
107 " window.chrome.embeddedSearch &&" | |
108 " window.chrome.embeddedSearch.searchBox &&" | |
109 " window.chrome.embeddedSearch.searchBox.onresize &&" | |
110 " typeof window.chrome.embeddedSearch.searchBox.onresize ==" | |
111 " 'function') {" | |
112 " window.chrome.embeddedSearch.searchBox.onresize();" | |
113 " true;" | |
114 "}"; | |
115 | |
116 // We first send this script down to determine if the page supports instant. | |
117 static const char kSupportsInstantScript[] = | |
118 "if (window.chrome &&" | |
119 " window.chrome.embeddedSearch &&" | |
120 " window.chrome.embeddedSearch.searchBox &&" | |
121 " window.chrome.embeddedSearch.searchBox.onsubmit &&" | |
122 " typeof window.chrome.embeddedSearch.searchBox.onsubmit ==" | |
123 " 'function') {" | |
124 " true;" | |
125 "} else {" | |
126 " false;" | |
127 "}"; | |
128 | |
129 // Extended API. | |
130 | |
131 // Per-context initialization. | |
132 static const char kDispatchOnWindowReady[] = | |
133 "if (window.chrome &&" | |
134 " window.chrome.embeddedSearchOnWindowReady &&" | |
135 " typeof window.chrome.embeddedSearchOnWindowReady == 'function') {" | |
136 " window.chrome.embeddedSearchOnWindowReady();" | |
137 "}"; | |
138 | |
139 static const char kDispatchAutocompleteResultsEventScript[] = | |
140 "if (window.chrome &&" | |
141 " window.chrome.embeddedSearch &&" | |
142 " window.chrome.embeddedSearch.searchBox &&" | |
143 " window.chrome.embeddedSearch.searchBox.onnativesuggestions &&" | |
144 " typeof window.chrome.embeddedSearch.searchBox.onnativesuggestions ==" | |
145 " 'function') {" | |
146 " window.chrome.embeddedSearch.searchBox.onnativesuggestions();" | |
147 " true;" | |
148 "}"; | |
149 | |
150 // Takes two printf-style replaceable values: count, key_code. | |
151 static const char kDispatchUpOrDownKeyPressEventScript[] = | |
152 "if (window.chrome &&" | |
153 " window.chrome.embeddedSearch &&" | |
154 " window.chrome.embeddedSearch.searchBox &&" | |
155 " window.chrome.embeddedSearch.searchBox.onkeypress &&" | |
156 " typeof window.chrome.embeddedSearch.searchBox.onkeypress ==" | |
157 " 'function') {" | |
158 " for (var i = 0; i < %d; ++i)" | |
159 " window.chrome.embeddedSearch.searchBox.onkeypress({keyCode: %d});" | |
160 " true;" | |
161 "}"; | |
162 | |
163 // Takes one printf-style replaceable value: key_code. | |
164 static const char kDispatchEscKeyPressEventScript[] = | |
165 "if (window.chrome &&" | |
166 " window.chrome.embeddedSearch &&" | |
167 " window.chrome.embeddedSearch.searchBox &&" | |
168 " window.chrome.embeddedSearch.searchBox.onkeypress &&" | |
169 " typeof window.chrome.embeddedSearch.searchBox.onkeypress ==" | |
170 " 'function') {" | |
171 " window.chrome.embeddedSearch.searchBox.onkeypress({keyCode: %d});" | |
172 " true;" | |
173 "}"; | |
174 | |
175 static const char kDispatchKeyCaptureChangeScript[] = | |
176 "if (window.chrome &&" | |
177 " window.chrome.embeddedSearch &&" | |
178 " window.chrome.embeddedSearch.searchBox &&" | |
179 " window.chrome.embeddedSearch.searchBox.onkeycapturechange &&" | |
180 " typeof window.chrome.embeddedSearch.searchBox.onkeycapturechange ==" | |
181 " 'function') {" | |
182 " window.chrome.embeddedSearch.searchBox.onkeycapturechange();" | |
183 " true;" | |
184 "}"; | |
185 | |
186 static const char kDispatchThemeChangeEventScript[] = | |
187 "if (window.chrome &&" | |
188 " window.chrome.embeddedSearch &&" | |
189 " window.chrome.embeddedSearch.newTabPage &&" | |
190 " window.chrome.embeddedSearch.newTabPage.onthemechange &&" | |
191 " typeof window.chrome.embeddedSearch.newTabPage.onthemechange ==" | |
192 " 'function') {" | |
193 " window.chrome.embeddedSearch.newTabPage.onthemechange();" | |
194 " true;" | |
195 "}"; | |
196 | |
197 static const char kDispatchMarginChangeEventScript[] = | |
198 "if (window.chrome &&" | |
199 " window.chrome.embeddedSearch &&" | |
200 " window.chrome.embeddedSearch.searchBox &&" | |
201 " window.chrome.embeddedSearch.searchBox.onmarginchange &&" | |
202 " typeof window.chrome.embeddedSearch.searchBox.onmarginchange ==" | |
203 " 'function') {" | |
204 " window.chrome.embeddedSearch.searchBox.onmarginchange();" | |
205 " true;" | |
206 "}"; | |
207 | |
208 static const char kDispatchMostVisitedChangedScript[] = | |
209 "if (window.chrome &&" | |
210 " window.chrome.embeddedSearch &&" | |
211 " window.chrome.embeddedSearch.newTabPage &&" | |
212 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange &&" | |
213 " typeof window.chrome.embeddedSearch.newTabPage.onmostvisitedchange ==" | |
214 " 'function') {" | |
215 " window.chrome.embeddedSearch.newTabPage.onmostvisitedchange();" | |
216 " true;" | |
217 "}"; | |
218 | |
219 // ---------------------------------------------------------------------------- | |
220 | 96 |
221 class SearchBoxExtensionWrapper : public v8::Extension { | 97 class SearchBoxExtensionWrapper : public v8::Extension { |
222 public: | 98 public: |
223 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); | 99 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); |
224 | 100 |
225 // Allows v8's javascript code to call the native functions defined | 101 // Allows v8's JavaScript code to call the native functions defined in this |
226 // in this class for window.chrome. | 102 // class for window.chrome.searchBox. |
227 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 103 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
228 v8::Handle<v8::String> name) OVERRIDE; | 104 v8::Handle<v8::String> name) OVERRIDE; |
229 | 105 |
230 // Helper function to find the RenderView. May return NULL. | 106 // Gets the user's search query. |
231 static content::RenderView* GetRenderView(); | |
232 | |
233 // Deletes a Most Visited item. | |
234 static v8::Handle<v8::Value> DeleteMostVisitedItem(const v8::Arguments& args); | |
235 | |
236 // Gets the value of the user's search query. | |
237 static v8::Handle<v8::Value> GetQuery(const v8::Arguments& args); | 107 static v8::Handle<v8::Value> GetQuery(const v8::Arguments& args); |
238 | 108 |
239 // Gets whether the |value| should be considered final -- as opposed to a | 109 // Gets whether the search query should be considered final -- as opposed to |
240 // partial match. This may be set if the user clicks a suggestion, presses | 110 // a partial match. This may be set if the user clicks a suggestion, presses |
241 // forward delete, or in other cases where Chrome overrides. | 111 // forward delete, or in other cases where Chrome overrides. |
242 static v8::Handle<v8::Value> GetVerbatim(const v8::Arguments& args); | 112 static v8::Handle<v8::Value> GetVerbatim(const v8::Arguments& args); |
243 | 113 |
244 // Gets the start of the selection in the search box. | 114 // Gets the start of the selection in the searchbox. |
245 static v8::Handle<v8::Value> GetSelectionStart(const v8::Arguments& args); | 115 static v8::Handle<v8::Value> GetSelectionStart(const v8::Arguments& args); |
246 | 116 |
247 // Gets the end of the selection in the search box. | 117 // Gets the end of the selection in the searchbox. |
248 static v8::Handle<v8::Value> GetSelectionEnd(const v8::Arguments& args); | 118 static v8::Handle<v8::Value> GetSelectionEnd(const v8::Arguments& args); |
249 | 119 |
250 // Gets the x coordinate (relative to |window|) of the left edge of the | 120 // Gets the x coordinate (relative to the window) of the left edge of the |
251 // region of the search box that overlaps the window. | 121 // region of the searchbox popup that overlaps the window. |
252 static v8::Handle<v8::Value> GetX(const v8::Arguments& args); | 122 static v8::Handle<v8::Value> GetX(const v8::Arguments& args); |
253 | 123 |
254 // Gets the y coordinate (relative to |window|) of the right edge of the | 124 // Gets the y coordinate (relative to the window) of the right edge of the |
255 // region of the search box that overlaps the window. | 125 // region of the searchbox popup that overlaps the window. |
256 static v8::Handle<v8::Value> GetY(const v8::Arguments& args); | 126 static v8::Handle<v8::Value> GetY(const v8::Arguments& args); |
257 | 127 |
258 // Gets the width of the region of the search box that overlaps the window, | 128 // Gets the width of the searchbox popup region that overlaps the window. |
259 // i.e., the width of the omnibox. | |
260 static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args); | 129 static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args); |
261 | 130 |
262 // Gets the height of the region of the search box that overlaps the window. | 131 // Gets the height of the searchbox popup region that overlaps the window. |
263 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); | 132 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); |
264 | 133 |
265 // Gets Most Visited Items. | 134 // Suggests an autocompletion for the current query. |
266 static v8::Handle<v8::Value> GetMostVisitedItems(const v8::Arguments& args); | 135 static v8::Handle<v8::Value> SetSuggestion(const v8::Arguments& args); |
267 | |
268 // Gets the start-edge margin to use with extended Instant. | |
269 static v8::Handle<v8::Value> GetStartMargin(const v8::Arguments& args); | |
270 | |
271 // Returns true if the Searchbox itself is oriented right-to-left. | |
272 static v8::Handle<v8::Value> GetRightToLeft(const v8::Arguments& args); | |
273 | |
274 // Gets the autocomplete results from search box. | |
275 static v8::Handle<v8::Value> GetAutocompleteResults( | |
276 const v8::Arguments& args); | |
277 | |
278 // Gets whether to display Instant results. | |
279 static v8::Handle<v8::Value> GetDisplayInstantResults( | |
280 const v8::Arguments& args); | |
281 | |
282 // Gets the background info of the theme currently adopted by browser. | |
283 // Call only when overlay is showing NTP page. | |
284 static v8::Handle<v8::Value> GetThemeBackgroundInfo( | |
285 const v8::Arguments& args); | |
286 | |
287 // Gets whether the browser is capturing key strokes. | |
288 static v8::Handle<v8::Value> IsKeyCaptureEnabled(const v8::Arguments& args); | |
289 | |
290 // Gets the font family of the text in the omnibox. | |
291 static v8::Handle<v8::Value> GetFont(const v8::Arguments& args); | |
292 | |
293 // Gets the font size of the text in the omnibox. | |
294 static v8::Handle<v8::Value> GetFontSize(const v8::Arguments& args); | |
295 | |
296 // Navigates the window to a URL represented by either a URL string or a | |
297 // restricted ID. | |
298 static v8::Handle<v8::Value> NavigateContentWindow(const v8::Arguments& args); | |
299 | |
300 // Sets ordered suggestions. Valid for current |value|. | |
301 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); | |
302 | |
303 // Sets the text to be autocompleted into the search box. | |
304 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); | |
305 | |
306 // Like |SetQuerySuggestion| but uses a restricted ID to identify the text. | |
307 static v8::Handle<v8::Value> SetQuerySuggestionFromAutocompleteResult( | |
308 const v8::Arguments& args); | |
309 | |
310 // Sets the search box text, completely replacing what the user typed. | |
311 static v8::Handle<v8::Value> SetQuery(const v8::Arguments& args); | |
312 | |
313 // Like |SetQuery| but uses a restricted ID to identify the text. | |
314 static v8::Handle<v8::Value> SetQueryFromAutocompleteResult( | |
315 const v8::Arguments& args); | |
316 | |
317 // Requests the overlay be shown with the specified contents and height. | |
318 static v8::Handle<v8::Value> ShowOverlay(const v8::Arguments& args); | |
319 | |
320 // Sets the focus to the omnibox. | |
321 static v8::Handle<v8::Value> FocusOmnibox(const v8::Arguments& args); | |
322 | |
323 // Start capturing user key strokes. | |
324 static v8::Handle<v8::Value> StartCapturingKeyStrokes( | |
325 const v8::Arguments& args); | |
326 | |
327 // Stop capturing user key strokes. | |
328 static v8::Handle<v8::Value> StopCapturingKeyStrokes( | |
329 const v8::Arguments& args); | |
330 | |
331 // Undoes the deletion of all Most Visited itens. | |
332 static v8::Handle<v8::Value> UndoAllMostVisitedDeletions( | |
333 const v8::Arguments& args); | |
334 | |
335 // Undoes the deletion of a Most Visited item. | |
336 static v8::Handle<v8::Value> UndoMostVisitedDeletion( | |
337 const v8::Arguments& args); | |
338 | 136 |
339 private: | 137 private: |
138 std::map<string16, v8::InvocationCallback> functions_; | |
139 | |
340 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper); | 140 DISALLOW_COPY_AND_ASSIGN(SearchBoxExtensionWrapper); |
341 }; | 141 }; |
342 | 142 |
343 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper( | 143 SearchBoxExtensionWrapper::SearchBoxExtensionWrapper( |
344 const base::StringPiece& code) | 144 const base::StringPiece& code) |
345 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) { | 145 : v8::Extension(kSearchBoxExtensionName, code.data(), 0, 0, code.size()) { |
146 functions_[ASCIIToUTF16("GetQuery")] = GetQuery; | |
147 functions_[ASCIIToUTF16("GetVerbatim")] = GetVerbatim; | |
148 functions_[ASCIIToUTF16("GetSelectionStart")] = GetSelectionStart; | |
149 functions_[ASCIIToUTF16("GetSelectionEnd")] = GetSelectionEnd; | |
150 functions_[ASCIIToUTF16("GetX")] = GetX; | |
151 functions_[ASCIIToUTF16("GetY")] = GetY; | |
152 functions_[ASCIIToUTF16("GetWidth")] = GetWidth; | |
153 functions_[ASCIIToUTF16("GetHeight")] = GetHeight; | |
154 functions_[ASCIIToUTF16("SetSuggestion")] = SetSuggestion; | |
346 } | 155 } |
347 | 156 |
348 v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction( | 157 v8::Handle<v8::FunctionTemplate> SearchBoxExtensionWrapper::GetNativeFunction( |
349 v8::Handle<v8::String> name) { | 158 v8::Handle<v8::String> name) { |
350 if (name->Equals(v8::String::New("DeleteMostVisitedItem"))) | 159 std::map<string16, v8::InvocationCallback>::const_iterator iter = |
351 return v8::FunctionTemplate::New(DeleteMostVisitedItem); | 160 functions_.find(V8ValueToUTF16(name)); |
352 if (name->Equals(v8::String::New("GetQuery"))) | 161 if (iter != functions_.end()) |
353 return v8::FunctionTemplate::New(GetQuery); | 162 return v8::FunctionTemplate::New(iter->second); |
354 if (name->Equals(v8::String::New("GetVerbatim"))) | |
355 return v8::FunctionTemplate::New(GetVerbatim); | |
356 if (name->Equals(v8::String::New("GetSelectionStart"))) | |
357 return v8::FunctionTemplate::New(GetSelectionStart); | |
358 if (name->Equals(v8::String::New("GetSelectionEnd"))) | |
359 return v8::FunctionTemplate::New(GetSelectionEnd); | |
360 if (name->Equals(v8::String::New("GetX"))) | |
361 return v8::FunctionTemplate::New(GetX); | |
362 if (name->Equals(v8::String::New("GetY"))) | |
363 return v8::FunctionTemplate::New(GetY); | |
364 if (name->Equals(v8::String::New("GetWidth"))) | |
365 return v8::FunctionTemplate::New(GetWidth); | |
366 if (name->Equals(v8::String::New("GetHeight"))) | |
367 return v8::FunctionTemplate::New(GetHeight); | |
368 if (name->Equals(v8::String::New("GetMostVisitedItems"))) | |
369 return v8::FunctionTemplate::New(GetMostVisitedItems); | |
370 if (name->Equals(v8::String::New("GetStartMargin"))) | |
371 return v8::FunctionTemplate::New(GetStartMargin); | |
372 if (name->Equals(v8::String::New("GetRightToLeft"))) | |
373 return v8::FunctionTemplate::New(GetRightToLeft); | |
374 if (name->Equals(v8::String::New("GetAutocompleteResults"))) | |
375 return v8::FunctionTemplate::New(GetAutocompleteResults); | |
376 if (name->Equals(v8::String::New("GetDisplayInstantResults"))) | |
377 return v8::FunctionTemplate::New(GetDisplayInstantResults); | |
378 if (name->Equals(v8::String::New("GetThemeBackgroundInfo"))) | |
379 return v8::FunctionTemplate::New(GetThemeBackgroundInfo); | |
380 if (name->Equals(v8::String::New("IsKeyCaptureEnabled"))) | |
381 return v8::FunctionTemplate::New(IsKeyCaptureEnabled); | |
382 if (name->Equals(v8::String::New("GetFont"))) | |
383 return v8::FunctionTemplate::New(GetFont); | |
384 if (name->Equals(v8::String::New("GetFontSize"))) | |
385 return v8::FunctionTemplate::New(GetFontSize); | |
386 if (name->Equals(v8::String::New("NavigateContentWindow"))) | |
387 return v8::FunctionTemplate::New(NavigateContentWindow); | |
388 if (name->Equals(v8::String::New("SetSuggestions"))) | |
389 return v8::FunctionTemplate::New(SetSuggestions); | |
390 if (name->Equals(v8::String::New("SetQuerySuggestion"))) | |
391 return v8::FunctionTemplate::New(SetQuerySuggestion); | |
392 if (name->Equals(v8::String::New("SetQuerySuggestionFromAutocompleteResult"))) | |
393 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); | |
394 if (name->Equals(v8::String::New("SetQuery"))) | |
395 return v8::FunctionTemplate::New(SetQuery); | |
396 if (name->Equals(v8::String::New("SetQueryFromAutocompleteResult"))) | |
397 return v8::FunctionTemplate::New(SetQueryFromAutocompleteResult); | |
398 if (name->Equals(v8::String::New("ShowOverlay"))) | |
399 return v8::FunctionTemplate::New(ShowOverlay); | |
400 if (name->Equals(v8::String::New("FocusOmnibox"))) | |
401 return v8::FunctionTemplate::New(FocusOmnibox); | |
402 if (name->Equals(v8::String::New("StartCapturingKeyStrokes"))) | |
403 return v8::FunctionTemplate::New(StartCapturingKeyStrokes); | |
404 if (name->Equals(v8::String::New("StopCapturingKeyStrokes"))) | |
405 return v8::FunctionTemplate::New(StopCapturingKeyStrokes); | |
406 if (name->Equals(v8::String::New("UndoAllMostVisitedDeletions"))) | |
407 return v8::FunctionTemplate::New(UndoAllMostVisitedDeletions); | |
408 if (name->Equals(v8::String::New("UndoMostVisitedDeletion"))) | |
409 return v8::FunctionTemplate::New(UndoMostVisitedDeletion); | |
410 return v8::Handle<v8::FunctionTemplate>(); | 163 return v8::Handle<v8::FunctionTemplate>(); |
411 } | 164 } |
412 | 165 |
413 // static | 166 // static |
414 content::RenderView* SearchBoxExtensionWrapper::GetRenderView() { | |
415 WebKit::WebFrame* webframe = WebKit::WebFrame::frameForCurrentContext(); | |
416 if (!webframe) return NULL; | |
417 | |
418 WebKit::WebView* webview = webframe->view(); | |
419 if (!webview) return NULL; // can happen during closing | |
420 | |
421 return content::RenderView::FromWebView(webview); | |
422 } | |
423 | |
424 // static | |
425 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetQuery( | 167 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetQuery( |
426 const v8::Arguments& args) { | 168 const v8::Arguments& args) { |
427 content::RenderView* render_view = GetRenderView(); | 169 SearchBox* searchbox = GetSearchBox(); |
428 if (!render_view) return v8::Undefined(); | 170 if (!searchbox) return v8::Undefined(); |
429 | 171 |
430 DVLOG(1) << render_view << " GetQuery: '" | 172 return UTF16ToV8String(searchbox->query()); |
431 << SearchBox::Get(render_view)->query() << "'"; | |
432 return UTF16ToV8String(SearchBox::Get(render_view)->query()); | |
433 } | 173 } |
434 | 174 |
435 // static | 175 // static |
436 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetVerbatim( | 176 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetVerbatim( |
437 const v8::Arguments& args) { | 177 const v8::Arguments& args) { |
438 content::RenderView* render_view = GetRenderView(); | 178 SearchBox* searchbox = GetSearchBox(); |
439 if (!render_view) return v8::Undefined(); | 179 if (!searchbox) return v8::Undefined(); |
440 | 180 |
441 DVLOG(1) << render_view << " GetVerbatim: " | 181 return v8::Boolean::New(searchbox->verbatim()); |
442 << SearchBox::Get(render_view)->verbatim(); | |
443 return v8::Boolean::New(SearchBox::Get(render_view)->verbatim()); | |
444 } | 182 } |
445 | 183 |
446 // static | 184 // static |
447 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSelectionStart( | 185 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSelectionStart( |
448 const v8::Arguments& args) { | 186 const v8::Arguments& args) { |
449 content::RenderView* render_view = GetRenderView(); | 187 SearchBox* searchbox = GetSearchBox(); |
450 if (!render_view) return v8::Undefined(); | 188 if (!searchbox) return v8::Undefined(); |
451 | 189 |
452 return v8::Uint32::New(SearchBox::Get(render_view)->selection_start()); | 190 return v8::Uint32::New(searchbox->selection_start()); |
453 } | 191 } |
454 | 192 |
455 // static | 193 // static |
456 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSelectionEnd( | 194 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetSelectionEnd( |
457 const v8::Arguments& args) { | 195 const v8::Arguments& args) { |
458 content::RenderView* render_view = GetRenderView(); | 196 SearchBox* searchbox = GetSearchBox(); |
459 if (!render_view) return v8::Undefined(); | 197 if (!searchbox) return v8::Undefined(); |
460 | 198 |
461 return v8::Uint32::New(SearchBox::Get(render_view)->selection_end()); | 199 return v8::Uint32::New(searchbox->selection_end()); |
462 } | 200 } |
463 | 201 |
464 // static | 202 // static |
465 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetX( | 203 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetX( |
466 const v8::Arguments& args) { | 204 const v8::Arguments& args) { |
467 content::RenderView* render_view = GetRenderView(); | 205 SearchBox* searchbox = GetSearchBox(); |
468 if (!render_view) return v8::Undefined(); | 206 if (!searchbox) return v8::Undefined(); |
469 | 207 |
470 return v8::Int32::New(SearchBox::Get(render_view)->GetPopupBounds().x()); | 208 return v8::Int32::New(searchbox->GetPopupBounds().x()); |
471 } | 209 } |
472 | 210 |
473 // static | 211 // static |
474 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetY( | 212 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetY( |
475 const v8::Arguments& args) { | 213 const v8::Arguments& args) { |
476 content::RenderView* render_view = GetRenderView(); | 214 SearchBox* searchbox = GetSearchBox(); |
477 if (!render_view) return v8::Undefined(); | 215 if (!searchbox) return v8::Undefined(); |
478 | 216 |
479 return v8::Int32::New(SearchBox::Get(render_view)->GetPopupBounds().y()); | 217 return v8::Int32::New(searchbox->GetPopupBounds().y()); |
480 } | 218 } |
481 | 219 |
482 // static | 220 // static |
483 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetWidth( | 221 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetWidth( |
484 const v8::Arguments& args) { | 222 const v8::Arguments& args) { |
485 content::RenderView* render_view = GetRenderView(); | 223 SearchBox* searchbox = GetSearchBox(); |
486 if (!render_view) return v8::Undefined(); | 224 if (!searchbox) return v8::Undefined(); |
487 return v8::Int32::New(SearchBox::Get(render_view)->GetPopupBounds().width()); | 225 |
226 return v8::Int32::New(searchbox->GetPopupBounds().width()); | |
488 } | 227 } |
489 | 228 |
490 // static | 229 // static |
491 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetHeight( | 230 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetHeight( |
492 const v8::Arguments& args) { | 231 const v8::Arguments& args) { |
493 content::RenderView* render_view = GetRenderView(); | 232 SearchBox* searchbox = GetSearchBox(); |
494 if (!render_view) return v8::Undefined(); | 233 if (!searchbox) return v8::Undefined(); |
495 | 234 |
496 return v8::Int32::New(SearchBox::Get(render_view)->GetPopupBounds().height()); | 235 return v8::Int32::New(searchbox->GetPopupBounds().height()); |
497 } | 236 } |
498 | 237 |
499 // static | 238 // static |
500 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetStartMargin( | 239 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestion( |
501 const v8::Arguments& args) { | 240 const v8::Arguments& args) { |
502 content::RenderView* render_view = GetRenderView(); | 241 SearchBox* searchbox = GetSearchBox(); |
503 if (!render_view) return v8::Undefined(); | 242 if (!searchbox || !args.Length()) return v8::Undefined(); |
504 return v8::Int32::New(SearchBox::Get(render_view)->GetStartMargin()); | 243 |
505 } | 244 InstantSuggestion suggestion; |
506 | 245 |
507 // static | |
508 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetRightToLeft( | |
509 const v8::Arguments& args) { | |
510 return v8::Boolean::New(base::i18n::IsRTL()); | |
511 } | |
512 | |
513 // static | |
514 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetAutocompleteResults( | |
515 const v8::Arguments& args) { | |
516 content::RenderView* render_view = GetRenderView(); | |
517 if (!render_view) return v8::Undefined(); | |
518 | |
519 DVLOG(1) << render_view << " GetAutocompleteResults"; | |
520 const std::vector<InstantAutocompleteResult>& results = | |
521 SearchBox::Get(render_view)->GetAutocompleteResults(); | |
522 size_t results_base = SearchBox::Get(render_view)->results_base(); | |
523 | |
524 v8::Handle<v8::Array> results_array = v8::Array::New(results.size()); | |
525 for (size_t i = 0; i < results.size(); ++i) { | |
526 v8::Handle<v8::Object> result = v8::Object::New(); | |
527 result->Set(v8::String::New("provider"), | |
528 UTF16ToV8String(results[i].provider)); | |
529 result->Set(v8::String::New("type"), UTF16ToV8String(results[i].type)); | |
530 result->Set(v8::String::New("contents"), | |
531 UTF16ToV8String(results[i].description)); | |
532 result->Set(v8::String::New("destination_url"), | |
533 UTF16ToV8String(results[i].destination_url)); | |
534 result->Set(v8::String::New("rid"), v8::Uint32::New(results_base + i)); | |
535 | |
536 v8::Handle<v8::Object> ranking_data = v8::Object::New(); | |
537 ranking_data->Set(v8::String::New("relevance"), | |
538 v8::Int32::New(results[i].relevance)); | |
539 result->Set(v8::String::New("rankingData"), ranking_data); | |
540 | |
541 results_array->Set(i, result); | |
542 } | |
543 return results_array; | |
544 } | |
545 | |
546 // static | |
547 v8::Handle<v8::Value> SearchBoxExtensionWrapper::IsKeyCaptureEnabled( | |
548 const v8::Arguments& args) { | |
549 content::RenderView* render_view = GetRenderView(); | |
550 if (!render_view) return v8::Undefined(); | |
551 | |
552 return v8::Boolean::New(SearchBox::Get(render_view)-> | |
553 is_key_capture_enabled()); | |
554 } | |
555 | |
556 // static | |
557 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetDisplayInstantResults( | |
558 const v8::Arguments& args) { | |
559 content::RenderView* render_view = GetRenderView(); | |
560 if (!render_view) return v8::Undefined(); | |
561 | |
562 bool display_instant_results = | |
563 SearchBox::Get(render_view)->display_instant_results(); | |
564 DVLOG(1) << render_view << " " | |
565 << "GetDisplayInstantResults: " << display_instant_results; | |
566 return v8::Boolean::New(display_instant_results); | |
567 } | |
568 | |
569 // static | |
570 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetThemeBackgroundInfo( | |
571 const v8::Arguments& args) { | |
572 content::RenderView* render_view = GetRenderView(); | |
573 if (!render_view) return v8::Undefined(); | |
574 | |
575 DVLOG(1) << render_view << " GetThemeBackgroundInfo"; | |
576 const ThemeBackgroundInfo& theme_info = | |
577 SearchBox::Get(render_view)->GetThemeBackgroundInfo(); | |
578 v8::Handle<v8::Object> info = v8::Object::New(); | |
579 | |
580 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and | |
581 // B are between 0 and 255 inclusive, and A is a double between 0 and 1 | |
582 // inclusive. | |
583 // This is the CSS "background-color" format. | |
584 // Value is always valid. | |
585 info->Set(v8::String::New("colorRgba"), UTF8ToV8String( | |
586 // Convert the alpha using DoubleToString because StringPrintf will use | |
587 // locale specific formatters (e.g., use , instead of . in German). | |
588 base::StringPrintf( | |
589 kCSSBackgroundColorFormat, | |
590 theme_info.color_r, | |
591 theme_info.color_g, | |
592 theme_info.color_b, | |
593 base::DoubleToString(theme_info.color_a / 255.0).c_str()))); | |
594 | |
595 // The theme background image url is of format | |
596 // "-webkit-image-set(url(chrome://theme/IDR_THEME_BACKGROUND?<theme_id>) 1x)" | |
597 // where <theme_id> is the id that identifies the theme. | |
598 // This is the CSS "background-image" format. | |
599 // Value is only valid if there's a custom theme background image. | |
600 if (extensions::Extension::IdIsValid(theme_info.theme_id)) { | |
601 info->Set(v8::String::New("imageUrl"), UTF8ToV8String( | |
602 base::StringPrintf(kCSSBackgroundImageFormat, | |
603 theme_info.theme_id.c_str()))); | |
604 | |
605 // The theme background image horizontal alignment is one of "left", | |
606 // "right", "center". | |
607 // This is the horizontal component of the CSS "background-position" format. | |
608 // Value is only valid if |imageUrl| is not empty. | |
609 std::string alignment = kCSSBackgroundPositionCenter; | |
610 if (theme_info.image_horizontal_alignment == | |
611 THEME_BKGRND_IMAGE_ALIGN_LEFT) { | |
612 alignment = kCSSBackgroundPositionLeft; | |
613 } else if (theme_info.image_horizontal_alignment == | |
614 THEME_BKGRND_IMAGE_ALIGN_RIGHT) { | |
615 alignment = kCSSBackgroundPositionRight; | |
616 } | |
617 info->Set(v8::String::New("imageHorizontalAlignment"), | |
618 UTF8ToV8String(alignment)); | |
619 | |
620 // The theme background image vertical alignment is one of "top", "bottom", | |
621 // "center". | |
622 // This is the vertical component of the CSS "background-position" format. | |
623 // Value is only valid if |image_url| is not empty. | |
624 if (theme_info.image_vertical_alignment == THEME_BKGRND_IMAGE_ALIGN_TOP) { | |
625 alignment = kCSSBackgroundPositionTop; | |
626 } else if (theme_info.image_vertical_alignment == | |
627 THEME_BKGRND_IMAGE_ALIGN_BOTTOM) { | |
628 alignment = kCSSBackgroundPositionBottom; | |
629 } else { | |
630 alignment = kCSSBackgroundPositionCenter; | |
631 } | |
632 info->Set(v8::String::New("imageVerticalAlignment"), | |
633 UTF8ToV8String(alignment)); | |
634 | |
635 // The tiling of the theme background image is one of "no-repeat", | |
636 // "repeat-x", "repeat-y", "repeat". | |
637 // This is the CSS "background-repeat" format. | |
638 // Value is only valid if |image_url| is not empty. | |
639 std::string tiling = kCSSBackgroundRepeatNo; | |
640 switch (theme_info.image_tiling) { | |
641 case THEME_BKGRND_IMAGE_NO_REPEAT: | |
642 tiling = kCSSBackgroundRepeatNo; | |
643 break; | |
644 case THEME_BKGRND_IMAGE_REPEAT_X: | |
645 tiling = kCSSBackgroundRepeatX; | |
646 break; | |
647 case THEME_BKGRND_IMAGE_REPEAT_Y: | |
648 tiling = kCSSBackgroundRepeatY; | |
649 break; | |
650 case THEME_BKGRND_IMAGE_REPEAT: | |
651 tiling = kCSSBackgroundRepeat; | |
652 break; | |
653 } | |
654 info->Set(v8::String::New("imageTiling"), UTF8ToV8String(tiling)); | |
655 | |
656 // The theme background image height is only valid if |imageUrl| is valid. | |
657 info->Set(v8::String::New("imageHeight"), | |
658 v8::Int32::New(theme_info.image_height)); | |
659 } | |
660 | |
661 return info; | |
662 } | |
663 | |
664 // static | |
665 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetFont( | |
666 const v8::Arguments& args) { | |
667 content::RenderView* render_view = GetRenderView(); | |
668 if (!render_view) return v8::Undefined(); | |
669 | |
670 return UTF16ToV8String(SearchBox::Get(render_view)->omnibox_font()); | |
671 } | |
672 | |
673 // static | |
674 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetFontSize( | |
675 const v8::Arguments& args) { | |
676 content::RenderView* render_view = GetRenderView(); | |
677 if (!render_view) return v8::Undefined(); | |
678 | |
679 return v8::Uint32::New(SearchBox::Get(render_view)->omnibox_font_size()); | |
680 } | |
681 | |
682 // static | |
683 v8::Handle<v8::Value> SearchBoxExtensionWrapper::NavigateContentWindow( | |
684 const v8::Arguments& args) { | |
685 content::RenderView* render_view = GetRenderView(); | |
686 if (!render_view || !args.Length()) return v8::Undefined(); | |
687 | |
688 GURL destination_url; | |
689 content::PageTransition transition = content::PAGE_TRANSITION_TYPED; | |
690 if (args[0]->IsNumber()) { | |
691 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> | |
692 GetAutocompleteResultWithId(args[0]->Uint32Value()); | |
693 if (result) { | |
694 destination_url = GURL(result->destination_url); | |
695 transition = result->transition; | |
696 } | |
697 } else { | |
698 destination_url = GURL(V8ValueToUTF16(args[0])); | |
699 } | |
700 | |
701 // Navigate the main frame. | |
702 if (destination_url.is_valid()) { | |
703 WindowOpenDisposition disposition = CURRENT_TAB; | |
704 if (args[1]->Uint32Value() == 2) | |
705 disposition = NEW_BACKGROUND_TAB; | |
706 SearchBox::Get(render_view)->NavigateToURL( | |
707 destination_url, transition, disposition); | |
708 } | |
709 return v8::Undefined(); | |
710 } | |
711 | |
712 // static | |
713 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions( | |
714 const v8::Arguments& args) { | |
715 content::RenderView* render_view = GetRenderView(); | |
716 if (!render_view || !args.Length()) return v8::Undefined(); | |
717 | |
718 DVLOG(1) << render_view << " SetSuggestions"; | |
719 v8::Handle<v8::Object> suggestion_json = args[0]->ToObject(); | 246 v8::Handle<v8::Object> suggestion_json = args[0]->ToObject(); |
720 | 247 |
721 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
722 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; | |
723 v8::Handle<v8::Value> complete_value = | |
724 suggestion_json->Get(v8::String::New("complete_behavior")); | |
725 if (complete_value->Equals(v8::String::New("now"))) { | |
726 behavior = INSTANT_COMPLETE_NOW; | |
727 } else if (complete_value->Equals(v8::String::New("never"))) { | |
728 behavior = INSTANT_COMPLETE_NEVER; | |
729 } else if (complete_value->Equals(v8::String::New("replace"))) { | |
730 behavior = INSTANT_COMPLETE_REPLACE; | |
731 } | |
732 | |
733 std::vector<InstantSuggestion> suggestions; | |
734 | |
735 v8::Handle<v8::Value> suggestions_field = | 248 v8::Handle<v8::Value> suggestions_field = |
736 suggestion_json->Get(v8::String::New("suggestions")); | 249 suggestion_json->Get(v8::String::New("suggestions")); |
737 if (suggestions_field->IsArray()) { | 250 if (suggestions_field->IsArray()) { |
738 v8::Handle<v8::Array> suggestions_array = suggestions_field.As<v8::Array>(); | 251 v8::Handle<v8::Array> suggestions_array = suggestions_field.As<v8::Array>(); |
739 for (size_t i = 0; i < suggestions_array->Length(); i++) { | 252 if (suggestions_array->Length() > 0) { |
740 string16 text = V8ValueToUTF16( | 253 suggestion.text = V8ValueToUTF16( |
741 suggestions_array->Get(i)->ToObject()->Get(v8::String::New("value"))); | 254 suggestions_array->Get(0)->ToObject()->Get(v8::String::New("value"))); |
742 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
743 } | 255 } |
744 } | 256 } |
745 | 257 |
746 SearchBox::Get(render_view)->SetSuggestions(suggestions); | 258 searchbox->SetSuggestion(suggestion); |
747 | 259 |
748 return v8::Undefined(); | 260 return v8::Undefined(); |
749 } | 261 } |
750 | 262 |
751 // static | 263 // SearchBoxExtension --------------------------------------------------------- |
752 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetQuerySuggestion( | |
753 const v8::Arguments& args) { | |
754 content::RenderView* render_view = GetRenderView(); | |
755 if (!render_view || args.Length() < 2) return v8::Undefined(); | |
756 | |
757 DVLOG(1) << render_view << " SetQuerySuggestion"; | |
758 string16 text = V8ValueToUTF16(args[0]); | |
759 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
760 InstantSuggestionType type = INSTANT_SUGGESTION_URL; | |
761 | |
762 if (args[1]->Uint32Value() == 2) { | |
763 behavior = INSTANT_COMPLETE_NEVER; | |
764 type = INSTANT_SUGGESTION_SEARCH; | |
765 } | |
766 | |
767 std::vector<InstantSuggestion> suggestions; | |
768 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
769 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
770 | |
771 return v8::Undefined(); | |
772 } | |
773 | |
774 // static | |
775 v8::Handle<v8::Value> | |
776 SearchBoxExtensionWrapper::SetQuerySuggestionFromAutocompleteResult( | |
777 const v8::Arguments& args) { | |
778 content::RenderView* render_view = GetRenderView(); | |
779 if (!render_view || !args.Length()) return v8::Undefined(); | |
780 | |
781 DVLOG(1) << render_view << " SetQuerySuggestionFromAutocompleteResult"; | |
782 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> | |
783 GetAutocompleteResultWithId(args[0]->Uint32Value()); | |
784 if (!result) return v8::Undefined(); | |
785 | |
786 // We only support selecting autocomplete results that are URLs. | |
787 string16 text = result->destination_url; | |
788 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | |
789 InstantSuggestionType type = INSTANT_SUGGESTION_URL; | |
790 | |
791 std::vector<InstantSuggestion> suggestions; | |
792 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
793 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
794 | |
795 return v8::Undefined(); | |
796 } | |
797 | |
798 // static | |
799 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetQuery( | |
800 const v8::Arguments& args) { | |
801 content::RenderView* render_view = GetRenderView(); | |
802 if (!render_view || args.Length() < 2) return v8::Undefined(); | |
803 | |
804 DVLOG(1) << render_view << " SetQuery"; | |
805 string16 text = V8ValueToUTF16(args[0]); | |
806 InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE; | |
807 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; | |
808 | |
809 if (args[1]->Uint32Value() == 1) | |
810 type = INSTANT_SUGGESTION_URL; | |
811 | |
812 std::vector<InstantSuggestion> suggestions; | |
813 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
814 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
815 | |
816 return v8::Undefined(); | |
817 } | |
818 | |
819 v8::Handle<v8::Value> | |
820 SearchBoxExtensionWrapper::SetQueryFromAutocompleteResult( | |
821 const v8::Arguments& args) { | |
822 content::RenderView* render_view = GetRenderView(); | |
823 if (!render_view || !args.Length()) return v8::Undefined(); | |
824 | |
825 DVLOG(1) << render_view << " SetQueryFromAutocompleteResult"; | |
826 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> | |
827 GetAutocompleteResultWithId(args[0]->Uint32Value()); | |
828 if (!result) return v8::Undefined(); | |
829 | |
830 // We only support selecting autocomplete results that are URLs. | |
831 string16 text = result->destination_url; | |
832 InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE; | |
833 // TODO(jered): Distinguish between history URLs and search provider | |
834 // navsuggest URLs so that we can do proper accounting on history URLs. | |
835 InstantSuggestionType type = INSTANT_SUGGESTION_URL; | |
836 | |
837 std::vector<InstantSuggestion> suggestions; | |
838 suggestions.push_back(InstantSuggestion(text, behavior, type)); | |
839 SearchBox::Get(render_view)->SetSuggestions(suggestions); | |
840 | |
841 return v8::Undefined(); | |
842 } | |
843 | |
844 // static | |
845 v8::Handle<v8::Value> SearchBoxExtensionWrapper::ShowOverlay( | |
846 const v8::Arguments& args) { | |
847 content::RenderView* render_view = GetRenderView(); | |
848 if (!render_view || args.Length() < 2) return v8::Undefined(); | |
849 | |
850 DVLOG(1) << render_view << " ShowOverlay"; | |
851 InstantShownReason reason = INSTANT_SHOWN_NOT_SPECIFIED; | |
852 switch (args[0]->Uint32Value()) { | |
853 case 1: reason = INSTANT_SHOWN_CUSTOM_NTP_CONTENT; break; | |
854 case 2: reason = INSTANT_SHOWN_QUERY_SUGGESTIONS; break; | |
855 case 3: reason = INSTANT_SHOWN_ZERO_SUGGESTIONS; break; | |
856 case 4: reason = INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION; break; | |
857 } | |
858 | |
859 int height = 100; | |
860 InstantSizeUnits units = INSTANT_SIZE_PERCENT; | |
861 if (args[1]->IsInt32()) { | |
862 height = args[1]->Int32Value(); | |
863 units = INSTANT_SIZE_PIXELS; | |
864 } | |
865 | |
866 SearchBox::Get(render_view)->ShowInstantOverlay(reason, height, units); | |
867 | |
868 return v8::Undefined(); | |
869 } | |
870 | |
871 // static | |
872 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetMostVisitedItems( | |
873 const v8::Arguments& args) { | |
874 content::RenderView* render_view = GetRenderView(); | |
875 if (!render_view) return v8::Undefined(); | |
876 | |
877 DVLOG(1) << render_view << " GetMostVisitedItems"; | |
878 | |
879 const std::vector<MostVisitedItem>& items = | |
880 SearchBox::Get(render_view)->GetMostVisitedItems(); | |
881 v8::Handle<v8::Array> items_array = v8::Array::New(items.size()); | |
882 for (size_t i = 0; i < items.size(); ++i) { | |
883 | |
884 const string16 url = UTF8ToUTF16(items[i].url.spec()); | |
885 const string16 host = UTF8ToUTF16(items[i].url.host()); | |
886 int restrict_id = | |
887 SearchBox::Get(render_view)->UrlToRestrictedId(url); | |
888 | |
889 // We set the "dir" attribute of the title, so that in RTL locales, a LTR | |
890 // title is rendered left-to-right and truncated from the right. For | |
891 // example, the title of http://msdn.microsoft.com/en-us/default.aspx is | |
892 // "MSDN: Microsoft developer network". In RTL locales, in the New Tab | |
893 // page, if the "dir" of this title is not specified, it takes Chrome UI's | |
894 // directionality. So the title will be truncated as "soft developer | |
895 // network". Setting the "dir" attribute as "ltr" renders the truncated | |
896 // title as "MSDN: Microsoft D...". As another example, the title of | |
897 // http://yahoo.com is "Yahoo!". In RTL locales, in the New Tab page, the | |
898 // title will be rendered as "!Yahoo" if its "dir" attribute is not set to | |
899 // "ltr". | |
900 std::string direction; | |
901 if (base::i18n::StringContainsStrongRTLChars(items[i].title)) | |
902 direction = kRTLHtmlTextDirection; | |
903 else | |
904 direction = kLTRHtmlTextDirection; | |
905 | |
906 string16 title = items[i].title; | |
907 if (title.empty()) | |
908 title = url; | |
909 | |
910 v8::Handle<v8::Object> item = v8::Object::New(); | |
911 item->Set(v8::String::New("rid"), | |
912 v8::Int32::New(restrict_id)); | |
913 item->Set(v8::String::New("thumbnailUrl"), | |
914 UTF16ToV8String(SearchBox::Get(render_view)-> | |
915 GenerateThumbnailUrl(restrict_id))); | |
916 item->Set(v8::String::New("faviconUrl"), | |
917 UTF16ToV8String(SearchBox::Get(render_view)-> | |
918 GenerateFaviconUrl(restrict_id))); | |
919 item->Set(v8::String::New("title"), | |
920 UTF16ToV8String(title)); | |
921 item->Set(v8::String::New("domain"), UTF16ToV8String(host)); | |
922 item->Set(v8::String::New("direction"), | |
923 UTF8ToV8String(direction)); | |
924 | |
925 items_array->Set(i, item); | |
926 } | |
927 return items_array; | |
928 } | |
929 | |
930 // static | |
931 v8::Handle<v8::Value> SearchBoxExtensionWrapper::DeleteMostVisitedItem( | |
932 const v8::Arguments& args) { | |
933 content::RenderView* render_view = GetRenderView(); | |
934 if (!render_view || !args.Length()) return v8::Undefined(); | |
935 | |
936 DVLOG(1) << render_view << " DeleteMostVisitedItem"; | |
937 SearchBox::Get(render_view)->DeleteMostVisitedItem(args[0]->IntegerValue()); | |
938 return v8::Undefined(); | |
939 } | |
940 | |
941 // static | |
942 v8::Handle<v8::Value> SearchBoxExtensionWrapper::UndoMostVisitedDeletion( | |
943 const v8::Arguments& args) { | |
944 content::RenderView* render_view = GetRenderView(); | |
945 if (!render_view || !args.Length()) return v8::Undefined(); | |
946 | |
947 DVLOG(1) << render_view << " UndoMostVisitedDeletion"; | |
948 SearchBox::Get(render_view)->UndoMostVisitedDeletion(args[0]->IntegerValue()); | |
949 return v8::Undefined(); | |
950 } | |
951 | |
952 // static | |
953 v8::Handle<v8::Value> SearchBoxExtensionWrapper::UndoAllMostVisitedDeletions( | |
954 const v8::Arguments& args) { | |
955 content::RenderView* render_view = GetRenderView(); | |
956 if (!render_view) return v8::Undefined(); | |
957 | |
958 DVLOG(1) << render_view << " UndoAllMostVisitedDeletions"; | |
959 SearchBox::Get(render_view)->UndoAllMostVisitedDeletions(); | |
960 return v8::Undefined(); | |
961 } | |
962 | |
963 // static | |
964 v8::Handle<v8::Value> SearchBoxExtensionWrapper::FocusOmnibox( | |
965 const v8::Arguments& args) { | |
966 content::RenderView* render_view = GetRenderView(); | |
967 if (!render_view) return v8::Undefined(); | |
968 | |
969 DVLOG(1) << render_view << " FocusOmnibox"; | |
970 SearchBox::Get(render_view)->FocusOmnibox(); | |
971 | |
972 return v8::Undefined(); | |
973 } | |
974 | |
975 // static | |
976 v8::Handle<v8::Value> SearchBoxExtensionWrapper::StartCapturingKeyStrokes( | |
977 const v8::Arguments& args) { | |
978 content::RenderView* render_view = GetRenderView(); | |
979 if (!render_view) return v8::Undefined(); | |
980 | |
981 DVLOG(1) << render_view << " StartCapturingKeyStrokes"; | |
982 SearchBox::Get(render_view)->StartCapturingKeyStrokes(); | |
983 return v8::Undefined(); | |
984 } | |
985 | |
986 // static | |
987 v8::Handle<v8::Value> SearchBoxExtensionWrapper::StopCapturingKeyStrokes( | |
988 const v8::Arguments& args) { | |
989 content::RenderView* render_view = GetRenderView(); | |
990 if (!render_view) return v8::Undefined(); | |
991 | |
992 DVLOG(1) << render_view << " StopCapturingKeyStrokes"; | |
993 SearchBox::Get(render_view)->StopCapturingKeyStrokes(); | |
994 return v8::Undefined(); | |
995 } | |
996 | 264 |
997 // static | 265 // static |
998 v8::Extension* SearchBoxExtension::Get() { | 266 v8::Extension* SearchBoxExtension::Get() { |
999 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). | 267 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). |
1000 GetRawDataResource(IDR_SEARCHBOX_API)); | 268 GetRawDataResource(IDR_SEARCHBOX_API)); |
1001 } | 269 } |
1002 | 270 |
1003 // static | 271 // static |
1004 bool SearchBoxExtension::PageSupportsInstant(WebKit::WebFrame* frame) { | 272 bool SearchBoxExtension::DetermineInstantSupport( |
1005 if (!frame) return false; | 273 content::RenderView* render_view) { |
274 WebKit::WebFrame* frame = GetFrame(render_view); | |
275 if (!frame) | |
276 return false; | |
277 | |
1006 v8::HandleScope handle_scope; | 278 v8::HandleScope handle_scope; |
1007 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( | 279 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( |
1008 WebKit::WebScriptSource(kSupportsInstantScript)); | 280 WebKit::WebScriptSource(kDetermineInstantSupportScript)); |
1009 return !v.IsEmpty() && v->BooleanValue(); | 281 return !v.IsEmpty() && v->BooleanValue(); |
1010 } | 282 } |
1011 | 283 |
1012 // static | 284 // static |
1013 void SearchBoxExtension::DispatchChange(WebKit::WebFrame* frame) { | 285 void SearchBoxExtension::Change(content::RenderView* render_view) { |
1014 Dispatch(frame, kDispatchChangeEventScript); | 286 Dispatch(render_view, kOnChangeScript); |
1015 } | 287 } |
1016 | 288 |
1017 // static | 289 // static |
1018 void SearchBoxExtension::DispatchSubmit(WebKit::WebFrame* frame) { | 290 void SearchBoxExtension::Submit(content::RenderView* render_view) { |
1019 Dispatch(frame, kDispatchSubmitEventScript); | 291 Dispatch(render_view, kOnSubmitScript); |
1020 } | 292 } |
1021 | 293 |
1022 // static | 294 // static |
1023 void SearchBoxExtension::DispatchCancel(WebKit::WebFrame* frame) { | 295 void SearchBoxExtension::Blur(content::RenderView* render_view) { |
1024 Dispatch(frame, kDispatchCancelEventScript); | 296 Dispatch(render_view, kOnBlurScript); |
1025 } | 297 } |
1026 | 298 |
1027 // static | 299 // static |
1028 void SearchBoxExtension::DispatchResize(WebKit::WebFrame* frame) { | 300 void SearchBoxExtension::PopupBounds(content::RenderView* render_view) { |
1029 Dispatch(frame, kDispatchResizeEventScript); | 301 Dispatch(render_view, kOnPopupBoundsScript); |
1030 } | 302 } |
1031 | 303 |
1032 // static | |
1033 void SearchBoxExtension::DispatchOnWindowReady(WebKit::WebFrame* frame) { | |
1034 Dispatch(frame, kDispatchOnWindowReady); | |
1035 } | |
1036 | |
1037 // static | |
1038 void SearchBoxExtension::DispatchAutocompleteResults(WebKit::WebFrame* frame) { | |
1039 Dispatch(frame, kDispatchAutocompleteResultsEventScript); | |
1040 } | |
1041 | |
1042 // static | |
1043 void SearchBoxExtension::DispatchUpOrDownKeyPress(WebKit::WebFrame* frame, | |
1044 int count) { | |
1045 Dispatch(frame, WebKit::WebString::fromUTF8( | |
1046 base::StringPrintf(kDispatchUpOrDownKeyPressEventScript, abs(count), | |
1047 count < 0 ? ui::VKEY_UP : ui::VKEY_DOWN))); | |
1048 } | |
1049 | |
1050 // static | |
1051 void SearchBoxExtension::DispatchEscKeyPress(WebKit::WebFrame* frame) { | |
1052 Dispatch(frame, WebKit::WebString::fromUTF8( | |
1053 base::StringPrintf(kDispatchEscKeyPressEventScript, ui::VKEY_ESCAPE))); | |
1054 } | |
1055 | |
1056 // static | |
1057 void SearchBoxExtension::DispatchKeyCaptureChange(WebKit::WebFrame* frame) { | |
1058 Dispatch(frame, kDispatchKeyCaptureChangeScript); | |
1059 } | |
1060 | |
1061 // static | |
1062 void SearchBoxExtension::DispatchMarginChange(WebKit::WebFrame* frame) { | |
1063 Dispatch(frame, kDispatchMarginChangeEventScript); | |
1064 } | |
1065 | |
1066 // static | |
1067 void SearchBoxExtension::DispatchThemeChange(WebKit::WebFrame* frame) { | |
1068 Dispatch(frame, kDispatchThemeChangeEventScript); | |
1069 } | |
1070 | |
1071 // static | |
1072 void SearchBoxExtension::DispatchMostVisitedChanged( | |
1073 WebKit::WebFrame* frame) { | |
1074 Dispatch(frame, kDispatchMostVisitedChangedScript); | |
1075 } | |
1076 } // namespace extensions_v8 | 304 } // namespace extensions_v8 |
OLD | NEW |