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