| 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 <ctype.h> | 7 #include <ctype.h> |
| 8 #include <vector> | |
| 9 | 8 |
| 10 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 11 #include "base/string_piece.h" | 10 #include "base/stringprintf.h" |
| 12 #include "base/string_util.h" | |
| 13 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
| 14 #include "chrome/renderer/searchbox/searchbox.h" | 12 #include "chrome/renderer/searchbox/searchbox.h" |
| 15 #include "content/public/renderer/render_view.h" | 13 #include "content/public/renderer/render_view.h" |
| 16 #include "grit/renderer_resources.h" | 14 #include "grit/renderer_resources.h" |
| 17 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" | 15 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" |
| 18 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" | 16 #include "third_party/WebKit/Source/WebKit/chromium/public/WebScriptSource.h" |
| 19 #include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h" | 17 #include "ui/base/keycodes/keyboard_codes.h" |
| 20 #include "ui/base/resource/resource_bundle.h" | 18 #include "ui/base/resource/resource_bundle.h" |
| 21 #include "v8/include/v8.h" | 19 #include "v8/include/v8.h" |
| 22 | 20 |
| 23 namespace { | 21 namespace { |
| 24 | 22 |
| 25 // Splits the string in |number| into two pieces, a leading number token (saved | 23 // Splits the string in |number| into two pieces, a leading number token (saved |
| 26 // in |number|) and the rest (saved in |suffix|). Either piece may become empty, | 24 // in |number|) and the rest (saved in |suffix|). Either piece may become empty, |
| 27 // depending on whether the input had no digits or only digits. Neither argument | 25 // depending on whether the input had no digits or only digits. Neither argument |
| 28 // may be NULL. | 26 // may be NULL. |
| 29 void SplitLeadingNumberToken(std::string* number, std::string* suffix) { | 27 void SplitLeadingNumberToken(std::string* number, std::string* suffix) { |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 101 // Extended API. | 99 // Extended API. |
| 102 static const char kDispatchAutocompleteResultsEventScript[] = | 100 static const char kDispatchAutocompleteResultsEventScript[] = |
| 103 "if (window.chrome &&" | 101 "if (window.chrome &&" |
| 104 " window.chrome.searchBox &&" | 102 " window.chrome.searchBox &&" |
| 105 " window.chrome.searchBox.onnativesuggestions &&" | 103 " window.chrome.searchBox.onnativesuggestions &&" |
| 106 " typeof window.chrome.searchBox.onnativesuggestions == 'function') {" | 104 " typeof window.chrome.searchBox.onnativesuggestions == 'function') {" |
| 107 " window.chrome.searchBox.onnativesuggestions();" | 105 " window.chrome.searchBox.onnativesuggestions();" |
| 108 " true;" | 106 " true;" |
| 109 "}"; | 107 "}"; |
| 110 | 108 |
| 111 static const char kDispatchKeyPressEventScript[] = | 109 // Takes two printf-style replaceable values: count, key_code. |
| 110 static const char kDispatchUpOrDownKeyPressEventScript[] = |
| 112 "if (window.chrome &&" | 111 "if (window.chrome &&" |
| 113 " window.chrome.searchBox &&" | 112 " window.chrome.searchBox &&" |
| 114 " window.chrome.searchBox.onkeypress &&" | 113 " window.chrome.searchBox.onkeypress &&" |
| 115 " typeof window.chrome.searchBox.onkeypress == 'function') {" | 114 " typeof window.chrome.searchBox.onkeypress == 'function') {" |
| 116 " window.chrome.searchBox.onkeypress(" | 115 " for (var i = 0; i < %d; ++i)" |
| 117 " {keyCode:window.chrome.searchBox.keyCode});" | 116 " window.chrome.searchBox.onkeypress({keyCode: %d});" |
| 118 " true;" | 117 " true;" |
| 119 "}"; | 118 "}"; |
| 120 | 119 |
| 121 // ---------------------------------------------------------------------------- | 120 // ---------------------------------------------------------------------------- |
| 122 | 121 |
| 123 class SearchBoxExtensionWrapper : public v8::Extension { | 122 class SearchBoxExtensionWrapper : public v8::Extension { |
| 124 public: | 123 public: |
| 125 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); | 124 explicit SearchBoxExtensionWrapper(const base::StringPiece& code); |
| 126 | 125 |
| 127 // Allows v8's javascript code to call the native functions defined | 126 // Allows v8's javascript code to call the native functions defined |
| (...skipping 29 matching lines...) Expand all Loading... |
| 157 // Gets the width of the region of the search box that overlaps the window. | 156 // Gets the width of the region of the search box that overlaps the window. |
| 158 static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args); | 157 static v8::Handle<v8::Value> GetWidth(const v8::Arguments& args); |
| 159 | 158 |
| 160 // Gets the height of the region of the search box that overlaps the window. | 159 // 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); | 160 static v8::Handle<v8::Value> GetHeight(const v8::Arguments& args); |
| 162 | 161 |
| 163 // Gets the autocomplete results from search box. | 162 // Gets the autocomplete results from search box. |
| 164 static v8::Handle<v8::Value> GetAutocompleteResults( | 163 static v8::Handle<v8::Value> GetAutocompleteResults( |
| 165 const v8::Arguments& args); | 164 const v8::Arguments& args); |
| 166 | 165 |
| 167 // Gets the last key code entered in search box. | |
| 168 static v8::Handle<v8::Value> GetKeyCode(const v8::Arguments& args); | |
| 169 | |
| 170 // Sets ordered suggestions. Valid for current |value|. | 166 // Sets ordered suggestions. Valid for current |value|. |
| 171 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); | 167 static v8::Handle<v8::Value> SetSuggestions(const v8::Arguments& args); |
| 172 | 168 |
| 173 // Sets the text to be autocompleted into the search box. | 169 // Sets the text to be autocompleted into the search box. |
| 174 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); | 170 static v8::Handle<v8::Value> SetQuerySuggestion(const v8::Arguments& args); |
| 175 | 171 |
| 176 // Like |SetQuerySuggestion| but uses a restricted ID to identify the text. | 172 // Like |SetQuerySuggestion| but uses a restricted ID to identify the text. |
| 177 static v8::Handle<v8::Value> SetQuerySuggestionFromAutocompleteResult( | 173 static v8::Handle<v8::Value> SetQuerySuggestionFromAutocompleteResult( |
| 178 const v8::Arguments& args); | 174 const v8::Arguments& args); |
| 179 | 175 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 209 } else if (name->Equals(v8::String::New("GetX"))) { | 205 } else if (name->Equals(v8::String::New("GetX"))) { |
| 210 return v8::FunctionTemplate::New(GetX); | 206 return v8::FunctionTemplate::New(GetX); |
| 211 } else if (name->Equals(v8::String::New("GetY"))) { | 207 } else if (name->Equals(v8::String::New("GetY"))) { |
| 212 return v8::FunctionTemplate::New(GetY); | 208 return v8::FunctionTemplate::New(GetY); |
| 213 } else if (name->Equals(v8::String::New("GetWidth"))) { | 209 } else if (name->Equals(v8::String::New("GetWidth"))) { |
| 214 return v8::FunctionTemplate::New(GetWidth); | 210 return v8::FunctionTemplate::New(GetWidth); |
| 215 } else if (name->Equals(v8::String::New("GetHeight"))) { | 211 } else if (name->Equals(v8::String::New("GetHeight"))) { |
| 216 return v8::FunctionTemplate::New(GetHeight); | 212 return v8::FunctionTemplate::New(GetHeight); |
| 217 } else if (name->Equals(v8::String::New("GetAutocompleteResults"))) { | 213 } else if (name->Equals(v8::String::New("GetAutocompleteResults"))) { |
| 218 return v8::FunctionTemplate::New(GetAutocompleteResults); | 214 return v8::FunctionTemplate::New(GetAutocompleteResults); |
| 219 } else if (name->Equals(v8::String::New("GetKeyCode"))) { | |
| 220 return v8::FunctionTemplate::New(GetKeyCode); | |
| 221 } else if (name->Equals(v8::String::New("SetSuggestions"))) { | 215 } else if (name->Equals(v8::String::New("SetSuggestions"))) { |
| 222 return v8::FunctionTemplate::New(SetSuggestions); | 216 return v8::FunctionTemplate::New(SetSuggestions); |
| 223 } else if (name->Equals(v8::String::New("SetQuerySuggestion"))) { | 217 } else if (name->Equals(v8::String::New("SetQuerySuggestion"))) { |
| 224 return v8::FunctionTemplate::New(SetQuerySuggestion); | 218 return v8::FunctionTemplate::New(SetQuerySuggestion); |
| 225 } else if (name->Equals(v8::String::New( | 219 } else if (name->Equals(v8::String::New( |
| 226 "SetQuerySuggestionFromAutocompleteResult"))) { | 220 "SetQuerySuggestionFromAutocompleteResult"))) { |
| 227 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); | 221 return v8::FunctionTemplate::New(SetQuerySuggestionFromAutocompleteResult); |
| 228 } else if (name->Equals(v8::String::New("SetQuery"))) { | 222 } else if (name->Equals(v8::String::New("SetQuery"))) { |
| 229 return v8::FunctionTemplate::New(SetQuery); | 223 return v8::FunctionTemplate::New(SetQuery); |
| 230 } else if (name->Equals(v8::String::New("SetQueryFromAutocompleteResult"))) { | 224 } else if (name->Equals(v8::String::New("SetQueryFromAutocompleteResult"))) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 v8::Int32::New(results[i].relevance)); | 330 v8::Int32::New(results[i].relevance)); |
| 337 result->Set(v8::String::New("rankingData"), ranking_data); | 331 result->Set(v8::String::New("rankingData"), ranking_data); |
| 338 | 332 |
| 339 results_array->Set(i, result); | 333 results_array->Set(i, result); |
| 340 } | 334 } |
| 341 | 335 |
| 342 return results_array; | 336 return results_array; |
| 343 } | 337 } |
| 344 | 338 |
| 345 // static | 339 // static |
| 346 v8::Handle<v8::Value> SearchBoxExtensionWrapper::GetKeyCode( | |
| 347 const v8::Arguments& args) { | |
| 348 content::RenderView* render_view = GetRenderView(); | |
| 349 if (!render_view) return v8::Undefined(); | |
| 350 return v8::Int32::New(SearchBox::Get(render_view)->key_code()); | |
| 351 } | |
| 352 | |
| 353 // static | |
| 354 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions( | 340 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetSuggestions( |
| 355 const v8::Arguments& args) { | 341 const v8::Arguments& args) { |
| 356 std::vector<InstantSuggestion> suggestions; | 342 std::vector<InstantSuggestion> suggestions; |
| 357 | 343 |
| 358 if (args.Length() && args[0]->IsObject()) { | 344 if (args.Length() && args[0]->IsObject()) { |
| 359 v8::Handle<v8::Object> suggestion_json = args[0]->ToObject(); | 345 v8::Handle<v8::Object> suggestion_json = args[0]->ToObject(); |
| 360 | 346 |
| 361 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; | 347 InstantCompleteBehavior behavior = INSTANT_COMPLETE_NOW; |
| 362 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; | 348 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; |
| 363 v8::Handle<v8::Value> complete_value = | 349 v8::Handle<v8::Value> complete_value = |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 459 VLOG(1) << "Invalid results_id " << results_id << "; " | 445 VLOG(1) << "Invalid results_id " << results_id << "; " |
| 460 << "results_base is " << results_base << "."; | 446 << "results_base is " << results_base << "."; |
| 461 } | 447 } |
| 462 } | 448 } |
| 463 return v8::Undefined(); | 449 return v8::Undefined(); |
| 464 } | 450 } |
| 465 | 451 |
| 466 // static | 452 // static |
| 467 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetQuery( | 453 v8::Handle<v8::Value> SearchBoxExtensionWrapper::SetQuery( |
| 468 const v8::Arguments& args) { | 454 const v8::Arguments& args) { |
| 469 // TODO(sreeram): Make the second argument (type) mandatory. | |
| 470 if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsString()) { | 455 if (1 <= args.Length() && args.Length() <= 2 && args[0]->IsString()) { |
| 471 string16 text = V8ValueToUTF16(args[0]); | 456 string16 text = V8ValueToUTF16(args[0]); |
| 472 InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE; | 457 InstantCompleteBehavior behavior = INSTANT_COMPLETE_REPLACE; |
| 473 InstantSuggestionType type = INSTANT_SUGGESTION_SEARCH; | 458 InstantSuggestionType type = INSTANT_SUGGESTION_URL; |
| 474 | 459 |
| 475 if (args.Length() >= 2 && args[1]->Uint32Value() == 1) | 460 if (args.Length() >= 2 && args[1]->Uint32Value() == 0) |
| 476 type = INSTANT_SUGGESTION_URL; | 461 type = INSTANT_SUGGESTION_SEARCH; |
| 477 | 462 |
| 478 if (content::RenderView* render_view = GetRenderView()) { | 463 if (content::RenderView* render_view = GetRenderView()) { |
| 479 std::vector<InstantSuggestion> suggestions; | 464 std::vector<InstantSuggestion> suggestions; |
| 480 suggestions.push_back(InstantSuggestion(text, behavior, type)); | 465 suggestions.push_back(InstantSuggestion(text, behavior, type)); |
| 481 SearchBox::Get(render_view)->SetSuggestions(suggestions); | 466 SearchBox::Get(render_view)->SetSuggestions(suggestions); |
| 482 } | 467 } |
| 483 } | 468 } |
| 484 return v8::Undefined(); | 469 return v8::Undefined(); |
| 485 } | 470 } |
| 486 | 471 |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 return v8::Undefined(); | 527 return v8::Undefined(); |
| 543 } | 528 } |
| 544 content::RenderView* render_view = GetRenderView(); | 529 content::RenderView* render_view = GetRenderView(); |
| 545 if (render_view && height >= 0) | 530 if (render_view && height >= 0) |
| 546 SearchBox::Get(render_view)->SetInstantPreviewHeight(height, units); | 531 SearchBox::Get(render_view)->SetInstantPreviewHeight(height, units); |
| 547 } | 532 } |
| 548 return v8::Undefined(); | 533 return v8::Undefined(); |
| 549 } | 534 } |
| 550 | 535 |
| 551 // static | 536 // static |
| 552 void Dispatch(WebKit::WebFrame* frame, WebKit::WebString script) { | 537 void Dispatch(WebKit::WebFrame* frame, const WebKit::WebString& script) { |
| 553 DCHECK(frame) << "Dispatch requires frame"; | 538 DCHECK(frame) << "Dispatch requires frame"; |
| 554 if (!frame) return; | 539 if (!frame) return; |
| 555 frame->executeScript(WebKit::WebScriptSource(script)); | 540 frame->executeScript(WebKit::WebScriptSource(script)); |
| 556 } | 541 } |
| 557 | 542 |
| 558 // static | 543 // static |
| 559 void SearchBoxExtension::DispatchChange(WebKit::WebFrame* frame) { | 544 void SearchBoxExtension::DispatchChange(WebKit::WebFrame* frame) { |
| 560 Dispatch(frame, kDispatchChangeEventScript); | 545 Dispatch(frame, kDispatchChangeEventScript); |
| 561 } | 546 } |
| 562 | 547 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 574 void SearchBoxExtension::DispatchResize(WebKit::WebFrame* frame) { | 559 void SearchBoxExtension::DispatchResize(WebKit::WebFrame* frame) { |
| 575 Dispatch(frame, kDispatchResizeEventScript); | 560 Dispatch(frame, kDispatchResizeEventScript); |
| 576 } | 561 } |
| 577 | 562 |
| 578 // static | 563 // static |
| 579 void SearchBoxExtension::DispatchAutocompleteResults(WebKit::WebFrame* frame) { | 564 void SearchBoxExtension::DispatchAutocompleteResults(WebKit::WebFrame* frame) { |
| 580 Dispatch(frame, kDispatchAutocompleteResultsEventScript); | 565 Dispatch(frame, kDispatchAutocompleteResultsEventScript); |
| 581 } | 566 } |
| 582 | 567 |
| 583 // static | 568 // static |
| 584 void SearchBoxExtension::DispatchKeyPress(WebKit::WebFrame* frame) { | 569 void SearchBoxExtension::DispatchUpOrDownKeyPress(WebKit::WebFrame* frame, |
| 585 Dispatch(frame, kDispatchKeyPressEventScript); | 570 int count) { |
| 571 Dispatch(frame, WebKit::WebString::fromUTF8( |
| 572 base::StringPrintf(kDispatchUpOrDownKeyPressEventScript, abs(count), |
| 573 count < 0 ? ui::VKEY_UP : ui::VKEY_DOWN))); |
| 586 } | 574 } |
| 587 | 575 |
| 588 // static | 576 // static |
| 589 bool SearchBoxExtension::PageSupportsInstant(WebKit::WebFrame* frame) { | 577 bool SearchBoxExtension::PageSupportsInstant(WebKit::WebFrame* frame) { |
| 590 DCHECK(frame) << "PageSupportsInstant requires frame"; | 578 DCHECK(frame) << "PageSupportsInstant requires frame"; |
| 591 if (!frame) return false; | 579 if (!frame) return false; |
| 592 | 580 |
| 593 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( | 581 v8::Handle<v8::Value> v = frame->executeScriptAndReturnValue( |
| 594 WebKit::WebScriptSource(kSupportsInstantScript)); | 582 WebKit::WebScriptSource(kSupportsInstantScript)); |
| 595 bool supports_instant = !v.IsEmpty() && v->BooleanValue(); | 583 bool supports_instant = !v.IsEmpty() && v->BooleanValue(); |
| 596 | 584 |
| 597 // Send a resize message to tell the page that Chrome is actively using the | 585 // Send a resize message to tell the page that Chrome is actively using the |
| 598 // searchbox API with it. The page uses the message to transition from | 586 // searchbox API with it. The page uses the message to transition from |
| 599 // "homepage" mode to "search" mode. | 587 // "homepage" mode to "search" mode. |
| 600 if (supports_instant) | 588 if (supports_instant) |
| 601 DispatchResize(frame); | 589 DispatchResize(frame); |
| 602 | 590 |
| 603 return supports_instant; | 591 return supports_instant; |
| 604 } | 592 } |
| 605 | 593 |
| 606 // static | 594 // static |
| 607 v8::Extension* SearchBoxExtension::Get() { | 595 v8::Extension* SearchBoxExtension::Get() { |
| 608 const base::StringPiece code = | 596 const base::StringPiece code = |
| 609 ResourceBundle::GetSharedInstance().GetRawDataResource( | 597 ResourceBundle::GetSharedInstance().GetRawDataResource( |
| 610 IDR_SEARCHBOX_API, ui::SCALE_FACTOR_NONE); | 598 IDR_SEARCHBOX_API, ui::SCALE_FACTOR_NONE); |
| 611 return new SearchBoxExtensionWrapper(code); | 599 return new SearchBoxExtensionWrapper(code); |
| 612 } | 600 } |
| 613 | 601 |
| 614 } // namespace extensions_v8 | 602 } // namespace extensions_v8 |
| OLD | NEW |