OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/searchbox/searchbox_extension.h" | 5 #include "chrome/renderer/searchbox/searchbox_extension.h" |
6 | 6 |
7 #include "base/string_number_conversions.h" | |
7 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
8 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
10 #include "chrome/browser/themes/theme_service.h" | |
11 #include "chrome/common/extensions/extension.h" | |
9 #include "chrome/renderer/searchbox/searchbox.h" | 12 #include "chrome/renderer/searchbox/searchbox.h" |
10 #include "content/public/renderer/render_view.h" | 13 #include "content/public/renderer/render_view.h" |
11 #include "grit/renderer_resources.h" | 14 #include "grit/renderer_resources.h" |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
15 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques t.h" | 18 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques t.h" |
16 #include "ui/base/keycodes/keyboard_codes.h" | 19 #include "ui/base/keycodes/keyboard_codes.h" |
17 #include "ui/base/resource/resource_bundle.h" | 20 #include "ui/base/resource/resource_bundle.h" |
18 #include "v8/include/v8.h" | 21 #include "v8/include/v8.h" |
19 | 22 |
20 namespace { | 23 namespace { |
21 | 24 |
25 const char kCSSBackgroundImageFormat[] = | |
26 "-webkit-image-set(url(chrome://theme/IDR_THEME_BACKGROUND?%s) 1x)"; | |
27 | |
28 const char kCSSBackgroundColorFormat[] = "rgba(%d,%d,%d,%s)"; | |
29 | |
22 // Converts a V8 value to a string16. | 30 // Converts a V8 value to a string16. |
23 string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { | 31 string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { |
24 v8::String::Value s(v); | 32 v8::String::Value s(v); |
25 return string16(reinterpret_cast<const char16*>(*s), s.length()); | 33 return string16(reinterpret_cast<const char16*>(*s), s.length()); |
26 } | 34 } |
27 | 35 |
28 // Converts string16 to V8 String. | 36 // Converts string16 to V8 String. |
29 v8::Handle<v8::String> UTF16ToV8String(const string16& s) { | 37 v8::Handle<v8::String> UTF16ToV8String(const string16& s) { |
30 return v8::String::New(reinterpret_cast<const uint16_t*>(s.data()), s.size()); | 38 return v8::String::New(reinterpret_cast<const uint16_t*>(s.data()), s.size()); |
31 } | 39 } |
32 | 40 |
41 // Converts std::string to V8 String. | |
42 v8::Handle<v8::String> UTF8ToV8String(const std::string& s) { | |
43 return v8::String::New(s.data(), s.size()); | |
44 } | |
45 | |
33 void Dispatch(WebKit::WebFrame* frame, const WebKit::WebString& script) { | 46 void Dispatch(WebKit::WebFrame* frame, const WebKit::WebString& script) { |
34 if (!frame) return; | 47 if (!frame) return; |
35 frame->executeScript(WebKit::WebScriptSource(script)); | 48 frame->executeScript(WebKit::WebScriptSource(script)); |
36 } | 49 } |
37 | 50 |
38 } // namespace | 51 } // namespace |
39 | 52 |
40 namespace extensions_v8 { | 53 namespace extensions_v8 { |
41 | 54 |
42 static const char kSearchBoxExtensionName[] = "v8/SearchBox"; | 55 static const char kSearchBoxExtensionName[] = "v8/SearchBox"; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
111 | 124 |
112 static const char kDispatchContextChangeEventScript[] = | 125 static const char kDispatchContextChangeEventScript[] = |
113 "if (window.chrome &&" | 126 "if (window.chrome &&" |
114 " window.chrome.searchBox &&" | 127 " window.chrome.searchBox &&" |
115 " window.chrome.searchBox.oncontextchange &&" | 128 " window.chrome.searchBox.oncontextchange &&" |
116 " typeof window.chrome.searchBox.oncontextchange == 'function') {" | 129 " typeof window.chrome.searchBox.oncontextchange == 'function') {" |
117 " window.chrome.searchBox.oncontextchange();" | 130 " window.chrome.searchBox.oncontextchange();" |
118 " true;" | 131 " true;" |
119 "}"; | 132 "}"; |
120 | 133 |
134 static const char kDispatchThemeChangeEventScript[] = | |
135 "if (window.chrome &&" | |
136 " window.chrome.searchBox &&" | |
137 " window.chrome.searchBox.onthemechange &&" | |
138 " typeof window.chrome.searchBox.onthemechange == 'function') {" | |
139 " window.chrome.searchBox.onthemechange();" | |
140 " true;" | |
141 "}"; | |
142 | |
143 static const char kDispatchThemeAreaHeightChangeEventScript[] = | |
144 "if (window.chrome &&" | |
145 " window.chrome.searchBox &&" | |
146 " window.chrome.searchBox.onthemeareaheightchange &&" | |
147 " typeof window.chrome.searchBox.onthemeareaheightchange ==" | |
148 " 'function') {" | |
149 " window.chrome.searchBox.onthemeareaheightchange();" | |
150 " true;" | |
151 "}"; | |
152 | |
121 // ---------------------------------------------------------------------------- | 153 // ---------------------------------------------------------------------------- |
122 | 154 |
123 class SearchBoxExtensionWrapper : public v8::Extension { | 155 class SearchBoxExtensionWrapper : public v8::Extension { |
124 public: | 156 public: |
125 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); | 157 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); |
126 | 158 |
127 // Allows v8's javascript code to call the native functions defined | 159 // Allows v8's javascript code to call the native functions defined |
128 // in this class for window.chrome. | 160 // in this class for window.chrome. |
129 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 161 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
130 v8::Handle<v8::String> name); | 162 v8::Handle<v8::String> name); |
(...skipping 29 matching lines...) Expand all Loading... | |
160 // Gets the height of the region of the search box that overlaps the window. | 192 // Gets the height of the region of the search box that overlaps the window. |
161 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); | 193 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); |
162 | 194 |
163 // Gets the autocomplete results from search box. | 195 // Gets the autocomplete results from search box. |
164 static v8::Handle<v8::Value> GetAutocompleteResults( | 196 static v8::Handle<v8::Value> GetAutocompleteResults( |
165 const v8::Arguments& args); | 197 const v8::Arguments& args); |
166 | 198 |
167 // Gets the current session context. | 199 // Gets the current session context. |
168 static v8::Handle<v8::Value> GetContext(const v8::Arguments& args); | 200 static v8::Handle<v8::Value> GetContext(const v8::Arguments& args); |
169 | 201 |
202 // Gets the background info of the theme currently adopted by browser. | |
203 // Call only when overlay is showing NTP page. | |
204 static v8::Handle<v8::Value> GetThemeBackgroundInfo( | |
205 const v8::Arguments& args); | |
206 | |
207 // Gets the theme area height that the entire theme background image should | |
208 // fill up. | |
209 // Call only when overlay is showing NTP page and GetThemeBackgroundInfo | |
210 // returns a non-empty image_url and an image_vertical_alignment that is not | |
211 // "top". | |
212 static v8::Handle<v8::Value> GetThemeAreaHeight(const v8::Arguments& args); | |
213 | |
170 // Navigates the window to a URL represented by either a URL string or a | 214 // Navigates the window to a URL represented by either a URL string or a |
171 // restricted ID. | 215 // restricted ID. |
172 static v8::Handle<v8::Value> NavigateContentWindow(const v8::Arguments& args); | 216 static v8::Handle<v8::Value> NavigateContentWindow(const v8::Arguments& args); |
173 | 217 |
174 // Sets ordered suggestions. Valid for current |value|. | 218 // Sets ordered suggestions. Valid for current |value|. |
175 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); | 219 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); |
176 | 220 |
177 // Sets the text to be autocompleted into the search box. | 221 // Sets the text to be autocompleted into the search box. |
178 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); | 222 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); |
179 | 223 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
215 if (name->Equals(v8::String::New("GetY"))) | 259 if (name->Equals(v8::String::New("GetY"))) |
216 return v8::FunctionTemplate::New(GetY); | 260 return v8::FunctionTemplate::New(GetY); |
217 if (name->Equals(v8::String::New("GetWidth"))) | 261 if (name->Equals(v8::String::New("GetWidth"))) |
218 return v8::FunctionTemplate::New(GetWidth); | 262 return v8::FunctionTemplate::New(GetWidth); |
219 if (name->Equals(v8::String::New("GetHeight"))) | 263 if (name->Equals(v8::String::New("GetHeight"))) |
220 return v8::FunctionTemplate::New(GetHeight); | 264 return v8::FunctionTemplate::New(GetHeight); |
221 if (name->Equals(v8::String::New("GetAutocompleteResults"))) | 265 if (name->Equals(v8::String::New("GetAutocompleteResults"))) |
222 return v8::FunctionTemplate::New(GetAutocompleteResults); | 266 return v8::FunctionTemplate::New(GetAutocompleteResults); |
223 if (name->Equals(v8::String::New("GetContext"))) | 267 if (name->Equals(v8::String::New("GetContext"))) |
224 return v8::FunctionTemplate::New(GetContext); | 268 return v8::FunctionTemplate::New(GetContext); |
269 if (name->Equals(v8::String::New("GetThemeBackgroundInfo"))) | |
270 return v8::FunctionTemplate::New(GetThemeBackgroundInfo); | |
271 if (name->Equals(v8::String::New("GetThemeAreaHeight"))) | |
272 return v8::FunctionTemplate::New(GetThemeAreaHeight); | |
225 if (name->Equals(v8::String::New("NavigateContentWindow"))) | 273 if (name->Equals(v8::String::New("NavigateContentWindow"))) |
226 return v8::FunctionTemplate::New(NavigateContentWindow); | 274 return v8::FunctionTemplate::New(NavigateContentWindow); |
227 if (name->Equals(v8::String::New("SetSuggestions"))) | 275 if (name->Equals(v8::String::New("SetSuggestions"))) |
228 return v8::FunctionTemplate::New(SetSuggestions); | 276 return v8::FunctionTemplate::New(SetSuggestions); |
229 if (name->Equals(v8::String::New("SetQuerySuggestion"))) | 277 if (name->Equals(v8::String::New("SetQuerySuggestion"))) |
230 return v8::FunctionTemplate::New(SetQuerySuggestion); | 278 return v8::FunctionTemplate::New(SetQuerySuggestion); |
231 if (name->Equals(v8::String::New("SetQuerySuggestionFromAutocompleteResult"))) | 279 if (name->Equals(v8::String::New("SetQuerySuggestionFromAutocompleteResult"))) |
232 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); | 280 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); |
233 if (name->Equals(v8::String::New("SetQuery"))) | 281 if (name->Equals(v8::String::New("SetQuery"))) |
234 return v8::FunctionTemplate::New(SetQuery); | 282 return v8::FunctionTemplate::New(SetQuery); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
360 content::RenderView* render_view = GetRenderView(); | 408 content::RenderView* render_view = GetRenderView(); |
361 if (!render_view) return v8::Undefined(); | 409 if (!render_view) return v8::Undefined(); |
362 | 410 |
363 v8::Handle<v8::Object> context = v8::Object::New(); | 411 v8::Handle<v8::Object> context = v8::Object::New(); |
364 context->Set( | 412 context->Set( |
365 v8::String::New("isNewTabPage"), | 413 v8::String::New("isNewTabPage"), |
366 v8::Boolean::New(SearchBox::Get(render_view)->active_tab_is_ntp())); | 414 v8::Boolean::New(SearchBox::Get(render_view)->active_tab_is_ntp())); |
367 return context; | 415 return context; |
368 } | 416 } |
369 | 417 |
418 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetThemeBackgroundInfo( | |
419 const v8::Arguments& args) { | |
420 content::RenderView* render_view = GetRenderView(); | |
421 if (!render_view) return v8::Undefined(); | |
422 | |
423 const ThemeBackgroundInfo& theme_info = | |
424 SearchBox::Get(render_view)->GetThemeBackgroundInfo(); | |
425 v8::Handle<v8::Object> info = v8::Object::New(); | |
426 | |
427 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and | |
428 // B are between 0 and 255 inclusive, and A is a double between 0 and 1 | |
429 // inclusive. | |
430 // This is the CSS "background-color" format. | |
431 // Value is always valid. | |
432 info->Set(v8::String::New("colorRgba"), UTF8ToV8String( | |
433 // Convert the alpha using DoubleToString because StringPrintf will use | |
434 // locale specific formatters (e.g., use , instead of . in German). | |
435 base::StringPrintf( | |
436 kCSSBackgroundColorFormat, | |
437 theme_info.color_r, | |
438 theme_info.color_g, | |
439 theme_info.color_b, | |
440 base::DoubleToString(theme_info.color_a / 255.0).c_str()))); | |
palmer
2012/11/19 22:23:20
Seems strange to convert this to a string. Can you
kuan
2012/11/20 00:12:44
the comment just above base::StringPrintf explains
palmer
2012/11/20 19:55:30
But I had thought that %f followed the same locale
| |
441 | |
442 // The theme background image url is of format | |
443 // "-webkit-image-set(url(chrome://theme/IDR_THEME_BACKGROUND?<theme_id>) 1x)" | |
444 // where <theme_id> is the id that identifies the theme. | |
445 // This is the CSS "background-image" format. | |
446 // Value is only valid if there's a custom theme background image. | |
447 std::string image_url; | |
448 if (extensions::Extension::IdIsValid(theme_info.theme_id)) { | |
449 image_url = base::StringPrintf(kCSSBackgroundImageFormat, | |
450 theme_info.theme_id.c_str()); | |
palmer
2012/11/19 22:23:20
Where does this get validated to ensure that it is
kuan
2012/11/20 00:12:44
in the line just above StringPrintf, i call IdIsVa
palmer
2012/11/20 19:55:30
Sorry, my bad. :)
| |
451 } | |
452 info->Set(v8::String::New("imageUrl"), UTF8ToV8String(image_url)); | |
453 | |
454 // The theme background image horizontal alignment is one of "left", "right", | |
455 // "center". | |
456 // This is the horizontal component of the CSS "background-position" format. | |
457 // Value is only valid if |image_url| is not empty. | |
458 std::string alignment = ThemeService::kAlignmentCenter; | |
459 if (!image_url.empty()) { | |
460 if (theme_info.image_alignment & ThemeService::ALIGN_LEFT) | |
461 alignment = ThemeService::kAlignmentLeft; | |
462 else if (theme_info.image_alignment & ThemeService::ALIGN_RIGHT) | |
463 alignment = ThemeService::kAlignmentRight; | |
464 } | |
465 info->Set(v8::String::New("imageHorizontalAlignment"), | |
466 UTF8ToV8String(alignment)); | |
467 | |
468 // The theme background image vertical alignment is one of "top", "bottom", | |
469 // "center". | |
470 // This is the vertical component of the CSS "background-position" format. | |
471 // Value is only valid if |image_url| is not empty. | |
472 alignment = alignment = ThemeService::kAlignmentCenter; | |
473 if (!image_url.empty()) { | |
474 if (theme_info.image_alignment & ThemeService::ALIGN_TOP) | |
475 alignment = ThemeService::kAlignmentTop; | |
476 else if (theme_info.image_alignment & ThemeService::ALIGN_BOTTOM) | |
477 alignment = ThemeService::kAlignmentBottom; | |
478 } | |
479 info->Set(v8::String::New("imageVerticalAlignment"), | |
480 UTF8ToV8String(alignment)); | |
481 | |
482 // The tiling of the theme background image is one of "no-repeat", "repeat-x", | |
483 // "repeat-y", "repeat". | |
484 // This is the CSS "background-repeat" format. | |
485 // Value is only valid if |image_url| is not empty. | |
486 std::string tiling = ThemeService::kTilingNoRepeat; | |
487 if (!image_url.empty()) | |
488 tiling = ThemeService::TilingToString(theme_info.image_tiling); | |
489 info->Set(v8::String::New("imageTiling"), UTF8ToV8String(tiling)); | |
490 | |
491 // The theme background image height is only valid if |imageUrl| is valid. | |
492 info->Set(v8::String::New("imageHeight"), | |
493 v8::Int32::New(image_url.empty() ? 0 : theme_info.image_height)); | |
494 | |
495 return info; | |
496 } | |
497 | |
498 | |
499 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetThemeAreaHeight( | |
500 const v8::Arguments& args) { | |
501 content::RenderView* render_view = GetRenderView(); | |
502 if (!render_view) return v8::Undefined(); | |
503 | |
504 return v8::Int32::New(SearchBox::Get(render_view)->GetThemeAreaHeight()); | |
505 } | |
506 | |
370 // static | 507 // static |
371 v8::Handle<v8::Value> SearchBoxExtensionWrapper::NavigateContentWindow( | 508 v8::Handle<v8::Value> SearchBoxExtensionWrapper::NavigateContentWindow( |
372 const v8::Arguments& args) { | 509 const v8::Arguments& args) { |
373 content::RenderView* render_view = GetRenderView(); | 510 content::RenderView* render_view = GetRenderView(); |
374 if (!render_view || !args.Length()) return v8::Undefined(); | 511 if (!render_view || !args.Length()) return v8::Undefined(); |
375 | 512 |
376 GURL destination_url; | 513 GURL destination_url; |
377 if (args[0]->IsNumber()) { | 514 if (args[0]->IsNumber()) { |
378 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> | 515 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> |
379 GetAutocompleteResultWithId(args[0]->Uint32Value()); | 516 GetAutocompleteResultWithId(args[0]->Uint32Value()); |
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
594 base::StringPrintf(kDispatchUpOrDownKeyPressEventScript, abs(count), | 731 base::StringPrintf(kDispatchUpOrDownKeyPressEventScript, abs(count), |
595 count < 0 ? ui::VKEY_UP : ui::VKEY_DOWN))); | 732 count < 0 ? ui::VKEY_UP : ui::VKEY_DOWN))); |
596 } | 733 } |
597 | 734 |
598 // static | 735 // static |
599 void SearchBoxExtension::DispatchContextChange(WebKit::WebFrame* frame) { | 736 void SearchBoxExtension::DispatchContextChange(WebKit::WebFrame* frame) { |
600 Dispatch(frame, kDispatchContextChangeEventScript); | 737 Dispatch(frame, kDispatchContextChangeEventScript); |
601 } | 738 } |
602 | 739 |
603 // static | 740 // static |
741 void SearchBoxExtension::DispatchThemeChange(WebKit::WebFrame* frame) { | |
742 Dispatch(frame, kDispatchThemeChangeEventScript); | |
743 } | |
744 | |
745 // static | |
746 void SearchBoxExtension::DispatchThemeAreaHeightChange( | |
747 WebKit::WebFrame* frame) { | |
748 Dispatch(frame, kDispatchThemeAreaHeightChangeEventScript); | |
749 } | |
750 | |
751 // static | |
604 v8::Extension* SearchBoxExtension::Get() { | 752 v8::Extension* SearchBoxExtension::Get() { |
605 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). | 753 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). |
606 GetRawDataResource(IDR_SEARCHBOX_API)); | 754 GetRawDataResource(IDR_SEARCHBOX_API)); |
607 } | 755 } |
608 | 756 |
609 } // namespace extensions_v8 | 757 } // namespace extensions_v8 |
OLD | NEW |