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/string_number_conversions.h" |
7 #include "base/stringprintf.h" | 8 #include "base/stringprintf.h" |
| 9 #include "chrome/common/extensions/extension.h" |
8 #include "chrome/renderer/searchbox/searchbox.h" | 10 #include "chrome/renderer/searchbox/searchbox.h" |
9 #include "content/public/renderer/render_view.h" | 11 #include "content/public/renderer/render_view.h" |
10 #include "grit/renderer_resources.h" | 12 #include "grit/renderer_resources.h" |
11 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
12 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | 14 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
13 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" |
14 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques
t.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebURLReques
t.h" |
15 #include "ui/base/keycodes/keyboard_codes.h" | 17 #include "ui/base/keycodes/keyboard_codes.h" |
16 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
17 #include "v8/include/v8.h" | 19 #include "v8/include/v8.h" |
18 | 20 |
19 namespace { | 21 namespace { |
20 | 22 |
| 23 const char kCSSBackgroundImageFormat[] = |
| 24 "-webkit-image-set(url(chrome://theme/IDR_THEME_BACKGROUND?%s) 1x)"; |
| 25 |
| 26 const char kCSSBackgroundColorFormat[] = "rgba(%d,%d,%d,%s)"; |
| 27 |
| 28 const char kCSSBackgroundPositionCenter[] = "center"; |
| 29 const char kCSSBackgroundPositionLeft[] = "left"; |
| 30 const char kCSSBackgroundPositionTop[] = "top"; |
| 31 const char kCSSBackgroundPositionRight[] = "right"; |
| 32 const char kCSSBackgroundPositionBottom[] = "bottom"; |
| 33 |
| 34 const char kCSSBackgroundRepeatNo[] = "no-repeat"; |
| 35 const char kCSSBackgroundRepeatX[] = "repeat-x"; |
| 36 const char kCSSBackgroundRepeatY[] = "repeat-y"; |
| 37 const char kCSSBackgroundRepeat[] = "repeat"; |
| 38 |
21 // Converts a V8 value to a string16. | 39 // Converts a V8 value to a string16. |
22 string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { | 40 string16 V8ValueToUTF16(v8::Handle<v8::Value> v) { |
23 v8::String::Value s(v); | 41 v8::String::Value s(v); |
24 return string16(reinterpret_cast<const char16*>(*s), s.length()); | 42 return string16(reinterpret_cast<const char16*>(*s), s.length()); |
25 } | 43 } |
26 | 44 |
27 // Converts string16 to V8 String. | 45 // Converts string16 to V8 String. |
28 v8::Handle<v8::String> UTF16ToV8String(const string16& s) { | 46 v8::Handle<v8::String> UTF16ToV8String(const string16& s) { |
29 return v8::String::New(reinterpret_cast<const uint16_t*>(s.data()), s.size()); | 47 return v8::String::New(reinterpret_cast<const uint16_t*>(s.data()), s.size()); |
30 } | 48 } |
31 | 49 |
| 50 // Converts std::string to V8 String. |
| 51 v8::Handle<v8::String> UTF8ToV8String(const std::string& s) { |
| 52 return v8::String::New(s.data(), s.size()); |
| 53 } |
| 54 |
32 void Dispatch(WebKit::WebFrame* frame, const WebKit::WebString& script) { | 55 void Dispatch(WebKit::WebFrame* frame, const WebKit::WebString& script) { |
33 if (!frame) return; | 56 if (!frame) return; |
34 frame->executeScript(WebKit::WebScriptSource(script)); | 57 frame->executeScript(WebKit::WebScriptSource(script)); |
35 } | 58 } |
36 | 59 |
37 } // namespace | 60 } // namespace |
38 | 61 |
39 namespace extensions_v8 { | 62 namespace extensions_v8 { |
40 | 63 |
41 static const char kSearchBoxExtensionName[] = "v8/SearchBox"; | 64 static const char kSearchBoxExtensionName[] = "v8/SearchBox"; |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
110 | 133 |
111 static const char kDispatchContextChangeEventScript[] = | 134 static const char kDispatchContextChangeEventScript[] = |
112 "if (window.chrome &&" | 135 "if (window.chrome &&" |
113 " window.chrome.searchBox &&" | 136 " window.chrome.searchBox &&" |
114 " window.chrome.searchBox.oncontextchange &&" | 137 " window.chrome.searchBox.oncontextchange &&" |
115 " typeof window.chrome.searchBox.oncontextchange == 'function') {" | 138 " typeof window.chrome.searchBox.oncontextchange == 'function') {" |
116 " window.chrome.searchBox.oncontextchange();" | 139 " window.chrome.searchBox.oncontextchange();" |
117 " true;" | 140 " true;" |
118 "}"; | 141 "}"; |
119 | 142 |
| 143 static const char kDispatchThemeChangeEventScript[] = |
| 144 "if (window.chrome &&" |
| 145 " window.chrome.searchBox &&" |
| 146 " window.chrome.searchBox.onthemechange &&" |
| 147 " typeof window.chrome.searchBox.onthemechange == 'function') {" |
| 148 " window.chrome.searchBox.onthemechange();" |
| 149 " true;" |
| 150 "}"; |
| 151 |
| 152 static const char kDispatchThemeAreaHeightChangeEventScript[] = |
| 153 "if (window.chrome &&" |
| 154 " window.chrome.searchBox &&" |
| 155 " window.chrome.searchBox.onthemeareaheightchange &&" |
| 156 " typeof window.chrome.searchBox.onthemeareaheightchange ==" |
| 157 " 'function') {" |
| 158 " window.chrome.searchBox.onthemeareaheightchange();" |
| 159 " true;" |
| 160 "}"; |
| 161 |
120 // ---------------------------------------------------------------------------- | 162 // ---------------------------------------------------------------------------- |
121 | 163 |
122 class SearchBoxExtensionWrapper : public v8::Extension { | 164 class SearchBoxExtensionWrapper : public v8::Extension { |
123 public: | 165 public: |
124 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); | 166 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); |
125 | 167 |
126 // Allows v8's javascript code to call the native functions defined | 168 // Allows v8's javascript code to call the native functions defined |
127 // in this class for window.chrome. | 169 // in this class for window.chrome. |
128 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( | 170 virtual v8::Handle<v8::FunctionTemplate> GetNativeFunction( |
129 v8::Handle<v8::String> name); | 171 v8::Handle<v8::String> name); |
(...skipping 29 matching lines...) Expand all Loading... |
159 // Gets the height of the region of the search box that overlaps the window. | 201 // Gets the height of the region of the search box that overlaps the window. |
160 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); | 202 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); |
161 | 203 |
162 // Gets the autocomplete results from search box. | 204 // Gets the autocomplete results from search box. |
163 static v8::Handle<v8::Value> GetAutocompleteResults( | 205 static v8::Handle<v8::Value> GetAutocompleteResults( |
164 const v8::Arguments& args); | 206 const v8::Arguments& args); |
165 | 207 |
166 // Gets the current session context. | 208 // Gets the current session context. |
167 static v8::Handle<v8::Value> GetContext(const v8::Arguments& args); | 209 static v8::Handle<v8::Value> GetContext(const v8::Arguments& args); |
168 | 210 |
| 211 // Gets the background info of the theme currently adopted by browser. |
| 212 // Call only when overlay is showing NTP page. |
| 213 static v8::Handle<v8::Value> GetThemeBackgroundInfo( |
| 214 const v8::Arguments& args); |
| 215 |
| 216 // Gets the theme area height that the entire theme background image should |
| 217 // fill up. |
| 218 // Call only when overlay is showing NTP page and GetThemeBackgroundInfo |
| 219 // returns a non-empty image_url and an image_vertical_alignment that is not |
| 220 // "top". |
| 221 static v8::Handle<v8::Value> GetThemeAreaHeight(const v8::Arguments& args); |
| 222 |
169 // Navigates the window to a URL represented by either a URL string or a | 223 // Navigates the window to a URL represented by either a URL string or a |
170 // restricted ID. | 224 // restricted ID. |
171 static v8::Handle<v8::Value> NavigateContentWindow(const v8::Arguments& args); | 225 static v8::Handle<v8::Value> NavigateContentWindow(const v8::Arguments& args); |
172 | 226 |
173 // Sets ordered suggestions. Valid for current |value|. | 227 // Sets ordered suggestions. Valid for current |value|. |
174 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); | 228 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); |
175 | 229 |
176 // Sets the text to be autocompleted into the search box. | 230 // Sets the text to be autocompleted into the search box. |
177 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); | 231 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); |
178 | 232 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
214 if (name->Equals(v8::String::New("GetY"))) | 268 if (name->Equals(v8::String::New("GetY"))) |
215 return v8::FunctionTemplate::New(GetY); | 269 return v8::FunctionTemplate::New(GetY); |
216 if (name->Equals(v8::String::New("GetWidth"))) | 270 if (name->Equals(v8::String::New("GetWidth"))) |
217 return v8::FunctionTemplate::New(GetWidth); | 271 return v8::FunctionTemplate::New(GetWidth); |
218 if (name->Equals(v8::String::New("GetHeight"))) | 272 if (name->Equals(v8::String::New("GetHeight"))) |
219 return v8::FunctionTemplate::New(GetHeight); | 273 return v8::FunctionTemplate::New(GetHeight); |
220 if (name->Equals(v8::String::New("GetAutocompleteResults"))) | 274 if (name->Equals(v8::String::New("GetAutocompleteResults"))) |
221 return v8::FunctionTemplate::New(GetAutocompleteResults); | 275 return v8::FunctionTemplate::New(GetAutocompleteResults); |
222 if (name->Equals(v8::String::New("GetContext"))) | 276 if (name->Equals(v8::String::New("GetContext"))) |
223 return v8::FunctionTemplate::New(GetContext); | 277 return v8::FunctionTemplate::New(GetContext); |
| 278 if (name->Equals(v8::String::New("GetThemeBackgroundInfo"))) |
| 279 return v8::FunctionTemplate::New(GetThemeBackgroundInfo); |
| 280 if (name->Equals(v8::String::New("GetThemeAreaHeight"))) |
| 281 return v8::FunctionTemplate::New(GetThemeAreaHeight); |
224 if (name->Equals(v8::String::New("NavigateContentWindow"))) | 282 if (name->Equals(v8::String::New("NavigateContentWindow"))) |
225 return v8::FunctionTemplate::New(NavigateContentWindow); | 283 return v8::FunctionTemplate::New(NavigateContentWindow); |
226 if (name->Equals(v8::String::New("SetSuggestions"))) | 284 if (name->Equals(v8::String::New("SetSuggestions"))) |
227 return v8::FunctionTemplate::New(SetSuggestions); | 285 return v8::FunctionTemplate::New(SetSuggestions); |
228 if (name->Equals(v8::String::New("SetQuerySuggestion"))) | 286 if (name->Equals(v8::String::New("SetQuerySuggestion"))) |
229 return v8::FunctionTemplate::New(SetQuerySuggestion); | 287 return v8::FunctionTemplate::New(SetQuerySuggestion); |
230 if (name->Equals(v8::String::New("SetQuerySuggestionFromAutocompleteResult"))) | 288 if (name->Equals(v8::String::New("SetQuerySuggestionFromAutocompleteResult"))) |
231 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); | 289 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); |
232 if (name->Equals(v8::String::New("SetQuery"))) | 290 if (name->Equals(v8::String::New("SetQuery"))) |
233 return v8::FunctionTemplate::New(SetQuery); | 291 return v8::FunctionTemplate::New(SetQuery); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 | 422 |
365 DVLOG(1) << "GetContext: isNewTabPage=" | 423 DVLOG(1) << "GetContext: isNewTabPage=" |
366 << SearchBox::Get(render_view)->active_tab_is_ntp(); | 424 << SearchBox::Get(render_view)->active_tab_is_ntp(); |
367 v8::Handle<v8::Object> context = v8::Object::New(); | 425 v8::Handle<v8::Object> context = v8::Object::New(); |
368 context->Set( | 426 context->Set( |
369 v8::String::New("isNewTabPage"), | 427 v8::String::New("isNewTabPage"), |
370 v8::Boolean::New(SearchBox::Get(render_view)->active_tab_is_ntp())); | 428 v8::Boolean::New(SearchBox::Get(render_view)->active_tab_is_ntp())); |
371 return context; | 429 return context; |
372 } | 430 } |
373 | 431 |
| 432 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetThemeBackgroundInfo( |
| 433 const v8::Arguments& args) { |
| 434 DVLOG(1) << "GetThemeBackgroundInfo"; |
| 435 content::RenderView* render_view = GetRenderView(); |
| 436 if (!render_view) return v8::Undefined(); |
| 437 |
| 438 const ThemeBackgroundInfo& theme_info = |
| 439 SearchBox::Get(render_view)->GetThemeBackgroundInfo(); |
| 440 v8::Handle<v8::Object> info = v8::Object::New(); |
| 441 |
| 442 // The theme background color is in RGBA format "rgba(R,G,B,A)" where R, G and |
| 443 // B are between 0 and 255 inclusive, and A is a double between 0 and 1 |
| 444 // inclusive. |
| 445 // This is the CSS "background-color" format. |
| 446 // Value is always valid. |
| 447 info->Set(v8::String::New("colorRgba"), UTF8ToV8String( |
| 448 // Convert the alpha using DoubleToString because StringPrintf will use |
| 449 // locale specific formatters (e.g., use , instead of . in German). |
| 450 base::StringPrintf( |
| 451 kCSSBackgroundColorFormat, |
| 452 theme_info.color_r, |
| 453 theme_info.color_g, |
| 454 theme_info.color_b, |
| 455 base::DoubleToString(theme_info.color_a / 255.0).c_str()))); |
| 456 |
| 457 // The theme background image url is of format |
| 458 // "-webkit-image-set(url(chrome://theme/IDR_THEME_BACKGROUND?<theme_id>) 1x)" |
| 459 // where <theme_id> is the id that identifies the theme. |
| 460 // This is the CSS "background-image" format. |
| 461 // Value is only valid if there's a custom theme background image. |
| 462 std::string image_url; |
| 463 if (extensions::Extension::IdIsValid(theme_info.theme_id)) { |
| 464 image_url = base::StringPrintf(kCSSBackgroundImageFormat, |
| 465 theme_info.theme_id.c_str()); |
| 466 } |
| 467 info->Set(v8::String::New("imageUrl"), UTF8ToV8String(image_url)); |
| 468 |
| 469 // The theme background image horizontal alignment is one of "left", "right", |
| 470 // "center". |
| 471 // This is the horizontal component of the CSS "background-position" format. |
| 472 // Value is only valid if |image_url| is not empty. |
| 473 std::string alignment = kCSSBackgroundPositionCenter; |
| 474 if (!image_url.empty()) { |
| 475 if (theme_info.image_horizontal_alignment == THEME_BKGRND_IMAGE_ALIGN_LEFT) |
| 476 alignment = kCSSBackgroundPositionLeft; |
| 477 else if (theme_info.image_horizontal_alignment == |
| 478 THEME_BKGRND_IMAGE_ALIGN_RIGHT) |
| 479 alignment = kCSSBackgroundPositionRight; |
| 480 } |
| 481 info->Set(v8::String::New("imageHorizontalAlignment"), |
| 482 UTF8ToV8String(alignment)); |
| 483 |
| 484 // The theme background image vertical alignment is one of "top", "bottom", |
| 485 // "center". |
| 486 // This is the vertical component of the CSS "background-position" format. |
| 487 // Value is only valid if |image_url| is not empty. |
| 488 alignment = kCSSBackgroundPositionCenter; |
| 489 if (!image_url.empty()) { |
| 490 if (theme_info.image_vertical_alignment == THEME_BKGRND_IMAGE_ALIGN_TOP) |
| 491 alignment = kCSSBackgroundPositionTop; |
| 492 else if (theme_info.image_vertical_alignment == |
| 493 THEME_BKGRND_IMAGE_ALIGN_BOTTOM) |
| 494 alignment = kCSSBackgroundPositionBottom; |
| 495 } |
| 496 info->Set(v8::String::New("imageVerticalAlignment"), |
| 497 UTF8ToV8String(alignment)); |
| 498 |
| 499 // The tiling of the theme background image is one of "no-repeat", "repeat-x", |
| 500 // "repeat-y", "repeat". |
| 501 // This is the CSS "background-repeat" format. |
| 502 // Value is only valid if |image_url| is not empty. |
| 503 std::string tiling = kCSSBackgroundRepeatNo; |
| 504 if (!image_url.empty()) { |
| 505 switch (theme_info.image_tiling) { |
| 506 case THEME_BKGRND_IMAGE_NO_REPEAT: |
| 507 tiling = kCSSBackgroundRepeatNo; |
| 508 break; |
| 509 case THEME_BKGRND_IMAGE_REPEAT_X: |
| 510 tiling = kCSSBackgroundRepeatX; |
| 511 break; |
| 512 case THEME_BKGRND_IMAGE_REPEAT_Y: |
| 513 tiling = kCSSBackgroundRepeatY; |
| 514 break; |
| 515 case THEME_BKGRND_IMAGE_REPEAT: |
| 516 tiling = kCSSBackgroundRepeat; |
| 517 break; |
| 518 } |
| 519 } |
| 520 info->Set(v8::String::New("imageTiling"), UTF8ToV8String(tiling)); |
| 521 |
| 522 // The theme background image height is only valid if |imageUrl| is valid. |
| 523 info->Set(v8::String::New("imageHeight"), |
| 524 v8::Int32::New(image_url.empty() ? 0 : theme_info.image_height)); |
| 525 |
| 526 return info; |
| 527 } |
| 528 |
| 529 |
| 530 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetThemeAreaHeight( |
| 531 const v8::Arguments& args) { |
| 532 content::RenderView* render_view = GetRenderView(); |
| 533 if (!render_view) return v8::Undefined(); |
| 534 |
| 535 DVLOG(1) << "GetThemeAreaHeight: " |
| 536 << SearchBox::Get(render_view)->GetThemeAreaHeight(); |
| 537 return v8::Int32::New(SearchBox::Get(render_view)->GetThemeAreaHeight()); |
| 538 } |
| 539 |
374 // static | 540 // static |
375 v8::Handle<v8::Value> SearchBoxExtensionWrapper::NavigateContentWindow( | 541 v8::Handle<v8::Value> SearchBoxExtensionWrapper::NavigateContentWindow( |
376 const v8::Arguments& args) { | 542 const v8::Arguments& args) { |
377 content::RenderView* render_view = GetRenderView(); | 543 content::RenderView* render_view = GetRenderView(); |
378 if (!render_view || !args.Length()) return v8::Undefined(); | 544 if (!render_view || !args.Length()) return v8::Undefined(); |
379 | 545 |
380 GURL destination_url; | 546 GURL destination_url; |
381 if (args[0]->IsNumber()) { | 547 if (args[0]->IsNumber()) { |
382 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> | 548 const InstantAutocompleteResult* result = SearchBox::Get(render_view)-> |
383 GetAutocompleteResultWithId(args[0]->Uint32Value()); | 549 GetAutocompleteResultWithId(args[0]->Uint32Value()); |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 count < 0 ? ui::VKEY_UP : ui::VKEY_DOWN))); | 773 count < 0 ? ui::VKEY_UP : ui::VKEY_DOWN))); |
608 } | 774 } |
609 | 775 |
610 // static | 776 // static |
611 void SearchBoxExtension::DispatchContextChange(WebKit::WebFrame* frame) { | 777 void SearchBoxExtension::DispatchContextChange(WebKit::WebFrame* frame) { |
612 DVLOG(1) << "DispatchContextChange"; | 778 DVLOG(1) << "DispatchContextChange"; |
613 Dispatch(frame, kDispatchContextChangeEventScript); | 779 Dispatch(frame, kDispatchContextChangeEventScript); |
614 } | 780 } |
615 | 781 |
616 // static | 782 // static |
| 783 void SearchBoxExtension::DispatchThemeChange(WebKit::WebFrame* frame) { |
| 784 Dispatch(frame, kDispatchThemeChangeEventScript); |
| 785 } |
| 786 |
| 787 // static |
| 788 void SearchBoxExtension::DispatchThemeAreaHeightChange( |
| 789 WebKit::WebFrame* frame) { |
| 790 Dispatch(frame, kDispatchThemeAreaHeightChangeEventScript); |
| 791 } |
| 792 |
| 793 // static |
617 v8::Extension* SearchBoxExtension::Get() { | 794 v8::Extension* SearchBoxExtension::Get() { |
618 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). | 795 return new SearchBoxExtensionWrapper(ResourceBundle::GetSharedInstance(). |
619 GetRawDataResource(IDR_SEARCHBOX_API)); | 796 GetRawDataResource(IDR_SEARCHBOX_API)); |
620 } | 797 } |
621 | 798 |
622 } // namespace extensions_v8 | 799 } // namespace extensions_v8 |
OLD | NEW |