diff options
author | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-21 23:38:45 +0000 |
---|---|---|
committer | mpcomplete@chromium.org <mpcomplete@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-06-21 23:38:45 +0000 |
commit | 8d677ff0f5085bb583d1b8248f977d009ec4b867 (patch) | |
tree | a8d1cb7e23128f910a33effde71fb083e5698838 | |
parent | 14f769f460022e0d28852adc9ff1ce02f4fe2871 (diff) | |
download | chromium_src-8d677ff0f5085bb583d1b8248f977d009ec4b867.zip chromium_src-8d677ff0f5085bb583d1b8248f977d009ec4b867.tar.gz chromium_src-8d677ff0f5085bb583d1b8248f977d009ec4b867.tar.bz2 |
Address some visual problems with the omnibox extension API:
- Remove some of the boilerplate strings.
- Allow the description field to be fully customizable and stylable.
BUG=46478
BUG=46479
Review URL: http://codereview.chromium.org/2849015
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@50411 0039d316-1c4b-4281-b951-d872f2087c98
12 files changed, 809 insertions, 77 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 0c14e22..b6fd109 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -1065,12 +1065,6 @@ each locale. --> <message name="IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION" desc="Description for a keyword match."> (Keyword: <ph name="KEYWORD">$1</ph>) </message> - <message name="IDS_AUTOCOMPLETE_EXTENSION_KEYWORD_DESCRIPTION" desc="Description for an extension keyword match."> - (Keyword: <ph name="KEYWORD">$1</ph>) - </message> - <message name="IDS_AUTOCOMPLETE_EXTENSION_KEYWORD_CONTENT" desc="Extra text describing usage of the suggested extension keyword command."> - <ph name="EXTENSION_COMMAND">$1<ex>send-mail-to</ex></ph> <ph name="EXTENSION_DESCRIPTION">$2<ex>(username@example.com)</ex></ph> - </message> <if expr="not pp_ifdef('use_titlecase')"> <message name="IDS_EDIT_SEARCH_ENGINES" desc="Title of the popup menu item for editing search engines"> @@ -3820,7 +3814,7 @@ Keep your key file in a safe place. You will need it to create new versions of y Search <ph name="SITE_NAME">$1<ex>google.com</ex></ph>: </message> <message name="IDS_OMNIBOX_EXTENSION_KEYWORD_TEXT" desc="Text shown in the search button at the front of the omnibox when the user has selected an extension keyword"> - <ph name="EXTENSION_NAME">$1<ex>Google Talk</ex></ph> command: + <ph name="EXTENSION_NAME">$1<ex>Google Talk</ex></ph>: </message> <!-- TODO(tc): This doesn't handle singular/plural properly. It needs to be reworded. --> <message name="IDS_OMNIBOX_RECENT_HISTORY" desc="Text shown in the omnibox that shows how many recent matches there are and allows the user to navigate to destinations->history with the selected text."> diff --git a/chrome/browser/autocomplete/keyword_provider.cc b/chrome/browser/autocomplete/keyword_provider.cc index a0130b7..0da37e8 100644 --- a/chrome/browser/autocomplete/keyword_provider.cc +++ b/chrome/browser/autocomplete/keyword_provider.cc @@ -324,22 +324,23 @@ AutocompleteMatch KeywordProvider::CreateAutocompleteMatch( // into keyword templates. FillInURLAndContents(remaining_input, element, &result); - // Create popup entry description based on the keyword name. - int message_id = element->IsExtensionKeyword() ? - IDS_AUTOCOMPLETE_EXTENSION_KEYWORD_DESCRIPTION : - IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION; - result.description.assign(l10n_util::GetStringF(message_id, keyword)); if (supports_replacement) result.template_url = element; - static const std::wstring kKeywordDesc(l10n_util::GetString(message_id)); - AutocompleteMatch::ClassifyLocationInString(kKeywordDesc.find(L"%s"), - prefix_length, - result.description.length(), - ACMatchClassification::DIM, - &result.description_class); - result.transition = PageTransition::KEYWORD; + // Create popup entry description based on the keyword name. + if (!element->IsExtensionKeyword()) { + result.description.assign(l10n_util::GetStringF( + IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION, keyword)); + static const std::wstring kKeywordDesc( + l10n_util::GetString(IDS_AUTOCOMPLETE_KEYWORD_DESCRIPTION)); + AutocompleteMatch::ClassifyLocationInString(kKeywordDesc.find(L"%s"), + prefix_length, + result.description.length(), + ACMatchClassification::DIM, + &result.description_class); + } + return result; } @@ -350,8 +351,9 @@ void KeywordProvider::Observe(NotificationType type, // AutocompleteProvider::kMaxMatches. DCHECK(type == NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY); - int suggest_id = Details<ExtensionOmniboxSuggestions>(details).ptr()->first; - if (suggest_id != current_input_id_) + const ExtensionOmniboxSuggestions& suggestions = + *Details<ExtensionOmniboxSuggestions>(details).ptr(); + if (suggestions.request_id != current_input_id_) return; // This is an old result. Just ignore. const AutocompleteInput& input = extension_suggest_last_input_; @@ -364,16 +366,8 @@ void KeywordProvider::Observe(NotificationType type, TemplateURLModel* model = profile_ ? profile_->GetTemplateURLModel() : model_; - ListValue* suggestions = - Details<ExtensionOmniboxSuggestions>(details).ptr()->second; - for (size_t i = 0; i < suggestions->GetSize(); ++i) { - DictionaryValue* suggestion; - string16 content, description; - if (!suggestions->GetDictionary(i, &suggestion) || - !suggestion->GetString("content", &content) || - !suggestion->GetString("description", &description)) - break; - + for (size_t i = 0; i < suggestions.suggestions.size(); ++i) { + const ExtensionOmniboxSuggestion& suggestion = suggestions.suggestions[i]; // We want to order these suggestions in descending order, so start with // the relevance of the first result (added synchronously in Start()), // and subtract 1 for each subsequent suggestion from the extension. @@ -382,20 +376,14 @@ void KeywordProvider::Observe(NotificationType type, int first_relevance = CalculateRelevance(input.type(), true, input.prefer_keyword()); extension_suggest_matches_.push_back(CreateAutocompleteMatch( - model, keyword, input, keyword.length(), UTF16ToWide(content), - first_relevance - (i + 1))); - - if (!description.empty()) { - AutocompleteMatch* match = &extension_suggest_matches_.back(); - std::vector<size_t> offsets; - match->contents.assign(l10n_util::GetStringF( - IDS_AUTOCOMPLETE_EXTENSION_KEYWORD_CONTENT, - match->contents, UTF16ToWide(description), &offsets)); - CHECK_EQ(2U, offsets.size()) << - "Expected 2 params for IDS_AUTOCOMPLETE_EXTENSION_KEYWORD_CONTENT"; - match->contents_class.push_back( - ACMatchClassification(offsets[1], ACMatchClassification::NONE)); - } + model, keyword, input, keyword.length(), + UTF16ToWide(suggestion.content), first_relevance - (i + 1))); + + AutocompleteMatch* match = &extension_suggest_matches_.back(); + match->contents.assign(UTF16ToWide(suggestion.description)); + match->contents_class = suggestion.description_styles; + match->description.clear(); + match->description_class.clear(); } done_ = true; diff --git a/chrome/browser/extensions/extension_omnibox_api.cc b/chrome/browser/extensions/extension_omnibox_api.cc index 7b526d7..5c046a3 100644 --- a/chrome/browser/extensions/extension_omnibox_api.cc +++ b/chrome/browser/extensions/extension_omnibox_api.cc @@ -16,6 +16,20 @@ const char kOnInputChanged[] = "experimental.omnibox.onInputChanged/"; const char kOnInputEntered[] = "experimental.omnibox.onInputEntered/"; }; // namespace events +namespace { +const char kDescriptionStylesOrderError[] = + "Suggestion descriptionStyles must be in increasing non-overlapping order."; +const char kDescriptionStylesLengthError[] = + "Suggestion descriptionStyles contains an offset longer than the" + " description text"; + +const wchar_t kSuggestionContent[] = L"content"; +const wchar_t kSuggestionDescription[] = L"description"; +const wchar_t kSuggestionDescriptionStyles[] = L"descriptionStyles"; +const wchar_t kDescriptionStylesType[] = L"type"; +const wchar_t kDescriptionStylesOffset[] = L"offset"; +}; // namespace + // static bool ExtensionOmniboxEventRouter::OnInputChanged( Profile* profile, const std::string& extension_id, @@ -51,17 +65,74 @@ void ExtensionOmniboxEventRouter::OnInputEntered( } bool OmniboxSendSuggestionsFunction::RunImpl() { - int request_id; + ExtensionOmniboxSuggestions suggestions; ListValue* suggestions_value; - EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &request_id)); + EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &suggestions.request_id)); EXTENSION_FUNCTION_VALIDATE(args_->GetList(1, &suggestions_value)); - ExtensionOmniboxSuggestions details(request_id, suggestions_value); + suggestions.suggestions.resize(suggestions_value->GetSize()); + for (size_t i = 0; i < suggestions_value->GetSize(); ++i) { + ExtensionOmniboxSuggestion& suggestion = suggestions.suggestions[i]; + DictionaryValue* suggestion_value; + EXTENSION_FUNCTION_VALIDATE(suggestions_value->GetDictionary( + i, &suggestion_value)); + EXTENSION_FUNCTION_VALIDATE(suggestion_value->GetStringAsUTF16( + kSuggestionContent, &suggestion.content)); + EXTENSION_FUNCTION_VALIDATE(suggestion_value->GetStringAsUTF16( + kSuggestionDescription, &suggestion.description)); + + if (suggestion_value->HasKey(kSuggestionDescriptionStyles)) { + ListValue* styles; + EXTENSION_FUNCTION_VALIDATE( + suggestion_value->GetList(kSuggestionDescriptionStyles, &styles)); + + suggestion.description_styles.clear(); + + int last_offset = -1; + for (size_t j = 0; j < styles->GetSize(); ++j) { + DictionaryValue* style; + std::string type; + int offset; + EXTENSION_FUNCTION_VALIDATE(styles->GetDictionary(j, &style)); + EXTENSION_FUNCTION_VALIDATE( + style->GetString(kDescriptionStylesType, &type)); + EXTENSION_FUNCTION_VALIDATE( + style->GetInteger(kDescriptionStylesOffset, &offset)); + + int type_class = + (type == "none") ? ACMatchClassification::NONE : + (type == "match") ? ACMatchClassification::MATCH : + (type == "dim") ? ACMatchClassification::DIM : -1; + EXTENSION_FUNCTION_VALIDATE(type_class != -1); + + if (offset <= last_offset) { + error_ = kDescriptionStylesOrderError; + return false; + } + if (static_cast<size_t>(offset) >= suggestion.description.length()) { + error_ = kDescriptionStylesLengthError; + return false; + } + + suggestion.description_styles.push_back( + ACMatchClassification(offset, type_class)); + last_offset = offset; + } + } + + // Ensure the styles cover the whole range of text. + if (suggestion.description_styles.empty() || + suggestion.description_styles[0].offset != 0) { + suggestion.description_styles.insert( + suggestion.description_styles.begin(), + ACMatchClassification(0, ACMatchClassification::NONE)); + } + } + NotificationService::current()->Notify( NotificationType::EXTENSION_OMNIBOX_SUGGESTIONS_READY, Source<Profile>(profile_), - Details<ExtensionOmniboxSuggestions>(&details)); + Details<ExtensionOmniboxSuggestions>(&suggestions)); return true; } - diff --git a/chrome/browser/extensions/extension_omnibox_api.h b/chrome/browser/extensions/extension_omnibox_api.h index f77e904..4af9ee5 100644 --- a/chrome/browser/extensions/extension_omnibox_api.h +++ b/chrome/browser/extensions/extension_omnibox_api.h @@ -5,10 +5,10 @@ #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_OMNIBOX_API_H_ #define CHROME_BROWSER_EXTENSIONS_EXTENSION_OMNIBOX_API_H_ +#include "base/string16.h" +#include "chrome/browser/autocomplete/autocomplete.h" #include "chrome/browser/extensions/extension_function.h" -class ListValue; - // Event router class for events related to the omnibox API. class ExtensionOmniboxEventRouter { public: @@ -34,6 +34,20 @@ class OmniboxSendSuggestionsFunction : public SyncExtensionFunction { DECLARE_EXTENSION_FUNCTION_NAME("experimental.omnibox.sendSuggestions"); }; -typedef std::pair<int, ListValue*> ExtensionOmniboxSuggestions; +struct ExtensionOmniboxSuggestion { + // The text that gets put in the edit box. + string16 content; + + // The text that is displayed in the drop down. + string16 description; + + // Contains style ranges for the description. + ACMatchClassifications description_styles; +}; + +struct ExtensionOmniboxSuggestions { + int request_id; + std::vector<ExtensionOmniboxSuggestion> suggestions; +}; #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_OMNIBOX_API_H_ diff --git a/chrome/browser/extensions/extension_omnibox_apitest.cc b/chrome/browser/extensions/extension_omnibox_apitest.cc index a012d8e..61021b5 100644 --- a/chrome/browser/extensions/extension_omnibox_apitest.cc +++ b/chrome/browser/extensions/extension_omnibox_apitest.cc @@ -122,6 +122,30 @@ IN_PROC_BROWSER_TEST_F(OmniboxApiTest, Basic) { EXPECT_EQ(L"keyword suggestion2", result.match_at(2).fill_into_edit); EXPECT_EQ(L"keyword suggestion3", result.match_at(3).fill_into_edit); + std::wstring description = L"Description with style: <match> [dim], none"; + EXPECT_EQ(description, result.match_at(1).contents); + ASSERT_EQ(5u, result.match_at(1).contents_class.size()); + EXPECT_EQ(0u, + result.match_at(1).contents_class[0].offset); + EXPECT_EQ(ACMatchClassification::NONE, + result.match_at(1).contents_class[0].style); + EXPECT_EQ(description.find('<'), + result.match_at(1).contents_class[1].offset); + EXPECT_EQ(ACMatchClassification::MATCH, + result.match_at(1).contents_class[1].style); + EXPECT_EQ(description.find('>'), + result.match_at(1).contents_class[2].offset); + EXPECT_EQ(ACMatchClassification::NONE, + result.match_at(1).contents_class[2].style); + EXPECT_EQ(description.find('['), + result.match_at(1).contents_class[3].offset); + EXPECT_EQ(ACMatchClassification::DIM, + result.match_at(1).contents_class[3].style); + EXPECT_EQ(description.find(']'), + result.match_at(1).contents_class[4].offset); + EXPECT_EQ(ACMatchClassification::NONE, + result.match_at(1).contents_class[4].style); + AutocompleteMatch match = result.match_at(4); EXPECT_EQ(AutocompleteMatch::SEARCH_WHAT_YOU_TYPED, match.type); EXPECT_FALSE(match.deletable); diff --git a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc index e937c7f..8f9334f2e 100644 --- a/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc +++ b/chrome/browser/views/autocomplete/autocomplete_popup_contents_view.cc @@ -431,6 +431,8 @@ int AutocompleteResultView::DrawString( const ResultViewState state = GetState(); if (style & ACMatchClassification::URL) current_data->color = GetColor(state, URL); + else if (style & ACMatchClassification::DIM) + current_data->color = GetColor(state, DIMMED_TEXT); else current_data->color = GetColor(state, force_dim ? DIMMED_TEXT : TEXT); current_data->pixel_width = diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json index 8481a20..b309a55 100644 --- a/chrome/common/extensions/api/extension_api.json +++ b/chrome/common/extensions/api/extension_api.json @@ -3025,27 +3025,71 @@ }, { "namespace": "experimental.omnibox", - "types": [], + "types": [ + { + "id": "SuggestResult", + "type": "object", + "description": "A suggest result.", + "properties": { + "content": { + "type": "string", + "minLength": 1, + "description": "The text that is put into the URL bar, and that is sent to the extension when the user chooses this entry." + }, + "description": { + "type": "string", + "minLength": 1, + "description": "The text that is displayed in the URL dropdown. Can optionally be stylized by the descriptionStyles parameter." + }, + "descriptionStyles": { + "type": "array", + "optional": true, + "items": { + "type": "object", + "description": "A style object, created using styleNone, styleMatch, or styleDim. A style applies to the region of text starting at the style's offset, until either the next style or the end of the description.", + "properties": { + "type": {"type": "string", "enum": ["none", "match", "dim"]}, + "offset": {"type": "integer"} + } + } + } + } + } + ], "functions": [ { "name": "sendSuggestions", "nodoc": true, "type": "function", - "description": "", + "description": "A callback passed to the onInputChanged event used for sending suggestions back to the browser.", "parameters": [ {"type": "integer", "name": "requestId"}, { "type": "array", "description": "Array of suggest results", "items": { - "type": "object", - "properties": { - "content": {"type": "string"}, - "description": {"type": "string"} - } + "$ref": "SuggestResult" } } ] + }, + { + "name": "styleNone", + "type": "function", + "description": "Constructor for the descriptionStyles parameter of the suggest callback.", + "parameters": [ {"type": "integer", "name": "offset", "minimum": 0} ] + }, + { + "name": "styleMatch", + "type": "function", + "description": "Constructor for the descriptionStyles parameter of the suggest callback. This style designates a region of text matching what the user typed.", + "parameters": [ {"type": "integer", "name": "offset", "minimum": 0} ] + }, + { + "name": "styleDim", + "type": "function", + "description": "Constructor for the descriptionStyles parameter of the suggest callback. This style designates a region of dim helper text.", + "parameters": [ {"type": "integer", "name": "offset", "minimum": 0} ] } ], "events": [ @@ -3059,18 +3103,16 @@ "name": "text" }, { - "type": "function", "name": "suggest", + "type": "function", + "description": "A callback passed to the onInputChanged event used for sending suggestions back to the browser.", "parameters": [ + {"type": "integer", "name": "requestId"}, { "type": "array", "description": "Array of suggest results", "items": { - "type": "object", - "properties": { - "content": {"type": "string"}, - "description": {"type": "string"} - } + "$ref": "SuggestResult" } } ] diff --git a/chrome/common/extensions/docs/examples/extensions/chrome_search/background.html b/chrome/common/extensions/docs/examples/extensions/chrome_search/background.html new file mode 100644 index 0000000..258ee77 --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/chrome_search/background.html @@ -0,0 +1,95 @@ +<script> +var currentRequest = null; + +chrome.experimental.omnibox.onInputChanged.addListener( + function(text, suggest) { + if (text == '') { + return; + } + + if (currentRequest != null) { + currentRequest.onreadystatechange = null; + currentRequest.abort(); + currentRequest = null; + } + + currentRequest = search(text, function(xml) { + var results = []; + var entries = xml.getElementsByTagName("entry"); + + for (var i = 0, entry; i < 5 && (entry = entries[i]); i++) { + var path = entry.getElementsByTagName("file")[0].getAttribute("name"); + var line = + entry.getElementsByTagName("match")[0].getAttribute("lineNumber"); + var file = path.split("/").pop(); + + // Remove HTML tags from description since omnibox cannot display them. + var description = entry.getElementsByTagName("content")[0].textContent; + description = description.replace(/<\/?.+?>/g, ''); + description = file + ': ' + description; + + results.push({ + content: path + '@' + line, + description: description, + descriptionStyles: [ + chrome.experimental.omnibox.styleMatch(0), + chrome.experimental.omnibox.styleNone(file.length), + ], + }); + } + + suggest(results); + }); + } +); + +function search(query, callback) { + var url = "http://www.google.com/codesearch/feeds/search?" + + "q=package:git.chromium.org/chromium.git+" + query; + var req = new XMLHttpRequest(); + req.open("GET", url, true); + req.setRequestHeader("GData-Version", "2"); + req.onreadystatechange = function() { + if (req.readyState == 4) { + callback(req.responseXML); + } + } + req.send(null); + return req; +} + +function getUrl(path, line) { + var url = + "http://src.chromium.org/cgi-bin/gitweb.cgi?p=chromium.git;a=blob;hb=HEAD;f=" + + path + "#l" + line; + return url; +} + +function getEntryUrl(entry) { + return getUrl( + entry.getElementsByTagName("file")[0].getAttribute("name"), + entry.getElementsByTagName("match")[0].getAttribute("lineNumber")); + return url; +} + +function navigate(url) { + chrome.tabs.getSelected(null, function(tab) { + chrome.tabs.update(tab.id, {url: url}); + }); +} + +chrome.experimental.omnibox.onInputEntered.addListener( + function(text) { + if (text.indexOf('@') > 0) { + var chunks = text.split('@'); + var path = chunks[0]; + var line = chunks[1]; + navigate(getUrl(path, line)); + } else { + search(text, function(xml) { + navigate(getEntryUrl(xml.getElementsByTagName("entry")[0])); + }); + } + } +); +</script> diff --git a/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json b/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json new file mode 100644 index 0000000..ace8a0b --- /dev/null +++ b/chrome/common/extensions/docs/examples/extensions/chrome_search/manifest.json @@ -0,0 +1,10 @@ +{
+ "background_page": "background.html",
+ "description": "Add support to the omnibox to search the Chromium source code.",
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDRx0y4f/CuomPPeGxcVMo7yfYZ1apxD+9e3ItNtPRBi8WMmzG0xhjnqvm03LTfTljbzA1L93s31HkjS5Bd12qM8SSZxOOizsZveK1tdpX0QelikSUaz1wwIyjatoC/jJy7vuuk0j5kPeLkNAhYGJTqN3H/Pqt0lFF1VFX4+fCEvQIDAQAB",
+ "name": "Chromium Search",
+ "omnibox_keyword": "src",
+ "permissions": [ "experimental", "tabs", "http://www.google.com/" ],
+ "update_url": "http://dl.dropbox.com/u/124107/chromium-search/update.xml",
+ "version": "4"
+}
diff --git a/chrome/common/extensions/docs/experimental.omnibox.html b/chrome/common/extensions/docs/experimental.omnibox.html index 5a52e54..d89360e 100644 --- a/chrome/common/extensions/docs/experimental.omnibox.html +++ b/chrome/common/extensions/docs/experimental.omnibox.html @@ -225,6 +225,12 @@ <ol> <li style="display: none; "> <a href="#method-anchor">methodName</a> + </li><li> + <a href="#method-styleDim">styleDim</a> + </li><li> + <a href="#method-styleMatch">styleMatch</a> + </li><li> + <a href="#method-styleNone">styleNone</a> </li> </ol> </li> @@ -238,11 +244,11 @@ </li> </ol> </li> - <li style="display: none; "> + <li> <a href="#types">Types</a> <ol> <li> - <a href="#id-anchor">id</a> + <a href="#type-SuggestResult">SuggestResult</a> </li> </ol> </li> @@ -350,6 +356,297 @@ see the <a href="experimental.html">chrome.experimental.* APIs</a> page. </div> <!-- /description --> + </div><div class="apiItem"> + <a name="method-styleDim"></a> <!-- method-anchor --> + <h4>styleDim</h4> + + <div class="summary"><span style="display: none; ">void</span> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.experimental.omnibox.styleDim</span>(<span class="null"><span style="display: none; ">, </span><span>integer</span> + <var><span>offset</span></var></span>)</div> + + <div class="description"> + <p class="todo" style="display: none; ">Undocumented.</p> + <p>Constructor for the descriptionStyles parameter of the suggest callback. This style designates a region of dim helper text.</p> + + <!-- PARAMETERS --> + <h4>Parameters</h4> + <dl> + <div> + <div> + <dt> + <var>offset</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>integer</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + </div> + </div> + </dl> + + <!-- RETURNS --> + <h4 style="display: none; ">Returns</h4> + <dl> + <div style="display: none; "> + <div> + </div> + </div> + </dl> + + <!-- CALLBACK --> + <div style="display: none; "> + <div> + <h4>Callback function</h4> + <p> + The callback <em>parameter</em> should specify a function + that looks like this: + </p> + <p> + If you specify the <em>callback</em> parameter, it should + specify a function that looks like this: + </p> + + <!-- Note: intentionally longer 80 columns --> + <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre> + <dl> + <div> + <div> + </div> + </div> + </dl> + </div> + </div> + + </div> <!-- /description --> + + </div><div class="apiItem"> + <a name="method-styleMatch"></a> <!-- method-anchor --> + <h4>styleMatch</h4> + + <div class="summary"><span style="display: none; ">void</span> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.experimental.omnibox.styleMatch</span>(<span class="null"><span style="display: none; ">, </span><span>integer</span> + <var><span>offset</span></var></span>)</div> + + <div class="description"> + <p class="todo" style="display: none; ">Undocumented.</p> + <p>Constructor for the descriptionStyles parameter of the suggest callback. This style designates a region of text matching what the user typed.</p> + + <!-- PARAMETERS --> + <h4>Parameters</h4> + <dl> + <div> + <div> + <dt> + <var>offset</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>integer</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + </div> + </div> + </dl> + + <!-- RETURNS --> + <h4 style="display: none; ">Returns</h4> + <dl> + <div style="display: none; "> + <div> + </div> + </div> + </dl> + + <!-- CALLBACK --> + <div style="display: none; "> + <div> + <h4>Callback function</h4> + <p> + The callback <em>parameter</em> should specify a function + that looks like this: + </p> + <p> + If you specify the <em>callback</em> parameter, it should + specify a function that looks like this: + </p> + + <!-- Note: intentionally longer 80 columns --> + <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre> + <dl> + <div> + <div> + </div> + </div> + </dl> + </div> + </div> + + </div> <!-- /description --> + + </div><div class="apiItem"> + <a name="method-styleNone"></a> <!-- method-anchor --> + <h4>styleNone</h4> + + <div class="summary"><span style="display: none; ">void</span> + <!-- Note: intentionally longer 80 columns --> + <span>chrome.experimental.omnibox.styleNone</span>(<span class="null"><span style="display: none; ">, </span><span>integer</span> + <var><span>offset</span></var></span>)</div> + + <div class="description"> + <p class="todo" style="display: none; ">Undocumented.</p> + <p>Constructor for the descriptionStyles parameter of the suggest callback.</p> + + <!-- PARAMETERS --> + <h4>Parameters</h4> + <dl> + <div> + <div> + <dt> + <var>offset</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>integer</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + </div> + </div> + </dl> + + <!-- RETURNS --> + <h4 style="display: none; ">Returns</h4> + <dl> + <div style="display: none; "> + <div> + </div> + </div> + </dl> + + <!-- CALLBACK --> + <div style="display: none; "> + <div> + <h4>Callback function</h4> + <p> + The callback <em>parameter</em> should specify a function + that looks like this: + </p> + <p> + If you specify the <em>callback</em> parameter, it should + specify a function that looks like this: + </p> + + <!-- Note: intentionally longer 80 columns --> + <pre>function(<span>Type param1, Type param2</span>) <span class="subdued">{...}</span>);</pre> + <dl> + <div> + <div> + </div> + </div> + </dl> + </div> + </div> + + </div> <!-- /description --> + </div> <!-- /apiItem --> </div> <!-- /apiGroup --> @@ -445,12 +742,10 @@ see the <a href="experimental.html">chrome.experimental.* APIs</a> page. </em> </dt> - <dd class="todo"> + <dd class="todo" style="display: none; "> Undocumented. </dd> - <dd style="display: none; "> - Description of this parameter from the json schema. - </dd> + <dd>A callback passed to the onInputChanged event used for sending suggestions back to the browser.</dd> <!-- OBJECT PROPERTIES --> <dd style="display: none; "> @@ -536,17 +831,187 @@ see the <a href="experimental.html">chrome.experimental.* APIs</a> page. </div> <!-- /apiGroup --> <!-- TYPES --> - <div class="apiGroup" style="display: none; "> + <div class="apiGroup"> <a name="types.sort(sortByName)"></a> <h3 id="types">Types</h3> <!-- iterates over all types --> <div class="apiItem"> - <a></a> - <h4>type name</h4> + <a name="type-SuggestResult"></a> + <h4>SuggestResult</h4> <div> + <dt> + <var style="display: none; ">paramName</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>object</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>A suggest result.</dd> + + <!-- OBJECT PROPERTIES --> + <dd> + <dl> + <div> + <div> + <dt> + <var>content</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The text that is put into the URL bar, and that is sent to the extension when the user chooses this entry.</dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> </div> + </dl> + </dd> + </div> + </div><div> + <div> + <dt> + <var>description</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional" style="display: none; ">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>string</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo" style="display: none; "> + Undocumented. + </dd> + <dd>The text that is displayed in the URL dropdown. Can optionally be stylized by the descriptionStyles parameter.</dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + </div> + </div><div> + <div> + <dt> + <var>descriptionStyles</var> + <em> + + <!-- TYPE --> + <div style="display:inline"> + ( + <span class="optional">optional</span> + <span id="typeTemplate"> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span> + array of <span><span> + <span style="display: none; "> + <a> Type</a> + </span> + <span> + <span style="display: none; "> + array of <span><span></span></span> + </span> + <span>object</span> + </span> + </span></span> + </span> + <span style="display: none; ">paramType</span> + </span> + </span> + ) + </div> + + </em> + </dt> + <dd class="todo"> + Undocumented. + </dd> + <dd style="display: none; "> + Description of this parameter from the json schema. + </dd> + + <!-- OBJECT PROPERTIES --> + <dd style="display: none; "> + <dl> + <div> + <div> + </div> + </div> + </dl> + </dd> + </div> + </div> + </dl> + </dd> + </div> </div> <!-- /apiItem --> diff --git a/chrome/renderer/resources/extension_process_bindings.js b/chrome/renderer/resources/extension_process_bindings.js index 779a13a..c408f8e 100644 --- a/chrome/renderer/resources/extension_process_bindings.js +++ b/chrome/renderer/resources/extension_process_bindings.js @@ -654,6 +654,19 @@ var chrome = chrome || {}; return newArgs; }; + apiFunctions["experimental.omnibox.styleNone"].handleRequest = + function(offset) { + return {type: "none", offset: offset}; + } + apiFunctions["experimental.omnibox.styleMatch"].handleRequest = + function(offset) { + return {type: "match", offset: offset}; + } + apiFunctions["experimental.omnibox.styleDim"].handleRequest = + function(offset) { + return {type: "dim", offset: offset}; + } + if (chrome.test) { chrome.test.getApiDefinitions = GetExtensionAPIDefinition; } diff --git a/chrome/test/data/extensions/api_test/omnibox/test.html b/chrome/test/data/extensions/api_test/omnibox/test.html index 6c2c6e0..95cfcc2 100644 --- a/chrome/test/data/extensions/api_test/omnibox/test.html +++ b/chrome/test/data/extensions/api_test/omnibox/test.html @@ -5,10 +5,24 @@ if (!chrome.omnibox) { chrome.omnibox.onInputChanged.addListener( function(text, suggest) { + chrome.test.log("onInputChanged: " + text); + if (text != "suggestio") + return; + + var desc = 'Description with style: <match> [dim], none'; suggest([ - {content: text + "n1", description: "description1"}, + { + content: text + "n1", + description: desc, + descriptionStyles: [ + chrome.omnibox.styleMatch(desc.indexOf('<')), + chrome.omnibox.styleNone(desc.indexOf('>')), + chrome.omnibox.styleDim(desc.indexOf('[')), + chrome.omnibox.styleNone(desc.indexOf(']')), + ] + }, {content: text + "n2", description: "description2"}, - {content: text + "n3", description: "description3"} + {content: text + "n3", description: "description3"}, ]); }); |