Chromium Code Reviews| 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 |