Enhance chrome://omnibox Presentation

Added ability of providers to append arbitrary information to be presented in the omnibox metrics window.
Adjust formatting somewhat.

BUG=None
TEST=Observe
Review URL: https://chromiumcodereview.appspot.com/10692075

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@148905 0039d316-1c4b-4281-b951-d872f2087c98
parent 7913d649
...@@ -4,9 +4,14 @@ ...@@ -4,9 +4,14 @@
#include "chrome/browser/autocomplete/autocomplete_match.h" #include "chrome/browser/autocomplete/autocomplete_match.h"
#include "base/i18n/time_formatting.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/string_number_conversions.h" #include "base/string_number_conversions.h"
#include "base/string_util.h" #include "base/string_util.h"
#include "base/string16.h"
#include "base/stringprintf.h"
#include "base/time.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_provider.h" #include "chrome/browser/autocomplete/autocomplete_provider.h"
#include "chrome/browser/search_engines/template_url.h" #include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h" #include "chrome/browser/search_engines/template_url_service.h"
...@@ -75,7 +80,8 @@ AutocompleteMatch::AutocompleteMatch(const AutocompleteMatch& match) ...@@ -75,7 +80,8 @@ AutocompleteMatch::AutocompleteMatch(const AutocompleteMatch& match)
from_previous(match.from_previous), from_previous(match.from_previous),
search_terms_args(match.search_terms_args.get() ? search_terms_args(match.search_terms_args.get() ?
new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) : new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) :
NULL) { NULL),
additional_info(match.additional_info) {
} }
AutocompleteMatch::~AutocompleteMatch() { AutocompleteMatch::~AutocompleteMatch() {
...@@ -108,6 +114,7 @@ AutocompleteMatch& AutocompleteMatch::operator=( ...@@ -108,6 +114,7 @@ AutocompleteMatch& AutocompleteMatch::operator=(
from_previous = match.from_previous; from_previous = match.from_previous;
search_terms_args.reset(match.search_terms_args.get() ? search_terms_args.reset(match.search_terms_args.get() ?
new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) : NULL); new TemplateURLRef::SearchTermsArgs(*match.search_terms_args) : NULL);
additional_info = match.additional_info;
return *this; return *this;
} }
...@@ -319,6 +326,24 @@ TemplateURL* AutocompleteMatch::GetTemplateURL(Profile* profile) const { ...@@ -319,6 +326,24 @@ TemplateURL* AutocompleteMatch::GetTemplateURL(Profile* profile) const {
GetTemplateURLForKeyword(keyword); GetTemplateURLForKeyword(keyword);
} }
void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
const std::string& value) {
DCHECK(property.size());
DCHECK(value.size());
additional_info[property] = value;
}
void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
int value) {
RecordAdditionalInfo(property, StringPrintf("%d", value));
}
void AutocompleteMatch::RecordAdditionalInfo(const std::string& property,
const base::Time& value) {
RecordAdditionalInfo(property,
UTF16ToUTF8(base::TimeFormatShortDateAndTime(value)));
}
#ifndef NDEBUG #ifndef NDEBUG
void AutocompleteMatch::Validate() const { void AutocompleteMatch::Validate() const {
ValidateClassifications(contents, contents_class); ValidateClassifications(contents, contents_class);
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_ #ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_
#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_ #define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_MATCH_H_
#include <map>
#include <string> #include <string>
#include <vector> #include <vector>
...@@ -17,6 +18,10 @@ class AutocompleteProvider; ...@@ -17,6 +18,10 @@ class AutocompleteProvider;
class Profile; class Profile;
class TemplateURL; class TemplateURL;
namespace base {
class Time;
} // namespace base
// AutocompleteMatch ---------------------------------------------------------- // AutocompleteMatch ----------------------------------------------------------
// A single result line with classified spans. The autocomplete popup displays // A single result line with classified spans. The autocomplete popup displays
...@@ -64,6 +69,10 @@ struct AutocompleteMatch { ...@@ -64,6 +69,10 @@ struct AutocompleteMatch {
typedef std::vector<ACMatchClassification> ACMatchClassifications; typedef std::vector<ACMatchClassification> ACMatchClassifications;
// Type used by providers to attach additional, optional information to
// an AutocompleteMatch.
typedef std::map<std::string, std::string> AdditionalInfo;
// The type of this match. // The type of this match.
enum Type { enum Type {
URL_WHAT_YOU_TYPED = 0, // The input as a URL. URL_WHAT_YOU_TYPED = 0, // The input as a URL.
...@@ -189,6 +198,13 @@ struct AutocompleteMatch { ...@@ -189,6 +198,13 @@ struct AutocompleteMatch {
// TemplateURL. See comments on |keyword| below. // TemplateURL. See comments on |keyword| below.
TemplateURL* GetTemplateURL(Profile* profile) const; TemplateURL* GetTemplateURL(Profile* profile) const;
// Adds optional information to the |additional_info| dictionary.
void RecordAdditionalInfo(const std::string& property,
const std::string& value);
void RecordAdditionalInfo(const std::string& property, int value);
void RecordAdditionalInfo(const std::string& property,
const base::Time& value);
// The provider of this match, used to remember which provider the user had // The provider of this match, used to remember which provider the user had
// selected when the input changes. This may be NULL, in which case there is // selected when the input changes. This may be NULL, in which case there is
// no provider (or memory of the user's selection). // no provider (or memory of the user's selection).
...@@ -283,6 +299,10 @@ struct AutocompleteMatch { ...@@ -283,6 +299,10 @@ struct AutocompleteMatch {
// AutocompleteController to do no additional transformations. // AutocompleteController to do no additional transformations.
scoped_ptr<TemplateURLRef::SearchTermsArgs> search_terms_args; scoped_ptr<TemplateURLRef::SearchTermsArgs> search_terms_args;
// Information dictionary into which each provider can optionally record a
// property and associated value and which is presented in chrome://omnibox.
AdditionalInfo additional_info;
#ifndef NDEBUG #ifndef NDEBUG
// Does a data integrity check on this match. // Does a data integrity check on this match.
void Validate() const; void Validate() const;
......
...@@ -245,6 +245,10 @@ AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch( ...@@ -245,6 +245,10 @@ AutocompleteMatch HistoryQuickProvider::QuickMatchToACMatch(
match.description_class = SpansFromTermMatch( match.description_class = SpansFromTermMatch(
history_match.title_matches, match.description.length(), false); history_match.title_matches, match.description.length(), false);
match.RecordAdditionalInfo("typed count", info.typed_count());
match.RecordAdditionalInfo("visit count", info.visit_count());
match.RecordAdditionalInfo("last visit", info.last_visit());
return match; return match;
} }
......
...@@ -936,5 +936,9 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch( ...@@ -936,5 +936,9 @@ AutocompleteMatch HistoryURLProvider::HistoryMatchToACMatch(
ACMatchClassification::NONE, ACMatchClassification::NONE,
&match.description_class); &match.description_class);
match.RecordAdditionalInfo("typed count", info.typed_count());
match.RecordAdditionalInfo("visit count", info.visit_count());
match.RecordAdditionalInfo("last visit", info.last_visit());
return match; return match;
} }
...@@ -40,3 +40,8 @@ p { ...@@ -40,3 +40,8 @@ p {
.table-header { .table-header {
white-space: nowrap; white-space: nowrap;
} }
.additional-info-property,
.additional-info-value {
white-space: nowrap;
}
...@@ -63,13 +63,17 @@ cr.define('omniboxDebug', function() { ...@@ -63,13 +63,17 @@ cr.define('omniboxDebug', function() {
* result record that we lookup. * result record that we lookup.
* @param {boolean} displayAlways whether the property should be displayed * @param {boolean} displayAlways whether the property should be displayed
* regardless of whether we're in detailed more. * regardless of whether we're in detailed more.
* @param {string} tooltip a description of the property that will be
* presented as a tooltip when the mouse is hovered over the column title.
* @constructor * @constructor
*/ */
function PresentationInfoRecord(header, url, propertyName, displayAlways) { function PresentationInfoRecord(header, url, propertyName, displayAlways,
tooltip) {
this.header = header; this.header = header;
this.urlLabelForHeader = url; this.urlLabelForHeader = url;
this.propertyName = propertyName; this.propertyName = propertyName;
this.displayAlways = displayAlways; this.displayAlways = displayAlways;
this.tooltip = tooltip;
} }
/** /**
...@@ -81,32 +85,50 @@ cr.define('omniboxDebug', function() { ...@@ -81,32 +85,50 @@ cr.define('omniboxDebug', function() {
* @const * @const
*/ */
var PROPERTY_OUTPUT_ORDER = [ var PROPERTY_OUTPUT_ORDER = [
new PresentationInfoRecord('Provider', '', 'provider_name', true), new PresentationInfoRecord('Provider', '', 'provider_name', true,
new PresentationInfoRecord('Type', '', 'type', true), 'The AutocompleteProvider suggesting this result.'),
new PresentationInfoRecord('Relevance', '', 'relevance', true), new PresentationInfoRecord('Type', '', 'type', true,
new PresentationInfoRecord('Contents', '', 'contents', true), 'The type of the result.'),
new PresentationInfoRecord('Starred', '', 'starred', false), new PresentationInfoRecord('Relevance', '', 'relevance', true,
'The result score. Higher is more relevant.'),
new PresentationInfoRecord('Contents', '', 'contents', true,
'The text that is presented identifying the result.'),
new PresentationInfoRecord('Starred', '', 'starred', false,
'A green checkmark indicates that the result has been bookmarked.'),
new PresentationInfoRecord( new PresentationInfoRecord(
'Is History What You Typed Match', '', 'HWYT', '', 'is_history_what_you_typed_match', false,
'is_history_what_you_typed_match', false), 'A green checkmark indicates that the result is an History What You ' +
new PresentationInfoRecord('Description', '', 'description', false), 'Typed Match'),
new PresentationInfoRecord('URL', '', 'destination_url', true), new PresentationInfoRecord('Description', '', 'description', false,
new PresentationInfoRecord('Fill Into Edit', '', 'fill_into_edit', false), 'The page title of the result.'),
new PresentationInfoRecord('URL', '', 'destination_url', true,
'The URL for the result.'),
new PresentationInfoRecord('Fill Into Edit', '', 'fill_into_edit', false,
'The text shown in the omnibox when the result is selected.'),
new PresentationInfoRecord( new PresentationInfoRecord(
'Inline Autocomplete Offset', '', 'inline_autocomplete_offset', false), 'IAO', '', 'inline_autocomplete_offset', false,
new PresentationInfoRecord('Deletable', '', 'deletable', false), 'The Inline Autocomplete Offset.'),
new PresentationInfoRecord('From Previous', '', 'from_previous', false), new PresentationInfoRecord('Del', '', 'deletable', false,
'A green checkmark indicates that the results can be deleted from ' +
'the visit history.'),
new PresentationInfoRecord('Prev', '', 'from_previous', false, ''),
new PresentationInfoRecord( new PresentationInfoRecord(
'Transition Type', 'Tran',
'http://code.google.com/codesearch#OAMlx_jo-ck/src/content/public/' + 'http://code.google.com/codesearch#OAMlx_jo-ck/src/content/public/' +
'common/page_transition_types.h&exact_package=chromium&l=24', 'common/page_transition_types.h&exact_package=chromium&l=24',
'transition', false), 'transition', false,
'How the user got to the result.'),
new PresentationInfoRecord( new PresentationInfoRecord(
'Is This Provider Done', '', 'provider_done', false), 'Done', '', 'provider_done', false,
'A green checkmark indicates that the provider is done looking for ' +
'more results.'),
new PresentationInfoRecord( new PresentationInfoRecord(
'Template URL', '', 'template_url', false), 'Template URL', '', 'template_url', false, ''),
new PresentationInfoRecord( new PresentationInfoRecord(
'Associated Keyword', '', 'associated_keyword', false) 'Associated Keyword', '', 'associated_keyword', false, ''),
new PresentationInfoRecord(
'Additional Info', '', 'additional_info', false,
'Provider-specific information about the result.')
]; ];
/** /**
...@@ -131,6 +153,7 @@ cr.define('omniboxDebug', function() { ...@@ -131,6 +153,7 @@ cr.define('omniboxDebug', function() {
// Output header text without a URL. // Output header text without a URL.
headerCell.textContent = PROPERTY_OUTPUT_ORDER[i].header; headerCell.textContent = PROPERTY_OUTPUT_ORDER[i].header;
headerCell.className = 'table-header'; headerCell.className = 'table-header';
headerCell.title = PROPERTY_OUTPUT_ORDER[i].tooltip;
} }
row.appendChild(headerCell); row.appendChild(headerCell);
} }
...@@ -150,7 +173,30 @@ cr.define('omniboxDebug', function() { ...@@ -150,7 +173,30 @@ cr.define('omniboxDebug', function() {
propertyName) { propertyName) {
var cell = document.createElement('td'); var cell = document.createElement('td');
if (propertyName in autocompleteSuggestion) { if (propertyName in autocompleteSuggestion) {
if (typeof autocompleteSuggestion[propertyName] == 'boolean') { if (propertyName == 'additional_info') {
// |additional_info| embeds a two-column table of provider-specific data
// within this cell.
var additionalInfoTable = document.createElement('table');
for (var additionalInfoKey in autocompleteSuggestion[propertyName]) {
var additionalInfoRow = document.createElement('tr');
// Set the title (name of property) cell text.
var propertyCell = document.createElement('td');
propertyCell.textContent = additionalInfoKey + ':';
propertyCell.className = 'additional-info-property';
additionalInfoRow.appendChild(propertyCell);
// Set the value of the property cell text.
var valueCell = document.createElement('td');
valueCell.textContent =
autocompleteSuggestion[propertyName][additionalInfoKey];
valueCell.className = 'additional-info-value';
additionalInfoRow.appendChild(valueCell);
additionalInfoTable.appendChild(additionalInfoRow);
}
cell.appendChild(additionalInfoTable);
} else if (typeof autocompleteSuggestion[propertyName] == 'boolean') {
// If this is a boolean, display a checkmark or an X instead of // If this is a boolean, display a checkmark or an X instead of
// the strings true or false. // the strings true or false.
if (autocompleteSuggestion[propertyName]) { if (autocompleteSuggestion[propertyName]) {
......
...@@ -125,6 +125,11 @@ void OmniboxUIHandler::AddResultToDictionary(const std::string& prefix, ...@@ -125,6 +125,11 @@ void OmniboxUIHandler::AddResultToDictionary(const std::string& prefix,
output->SetString(item_prefix + ".keyword", it->keyword); output->SetString(item_prefix + ".keyword", it->keyword);
output->SetBoolean(item_prefix + ".starred", it->starred); output->SetBoolean(item_prefix + ".starred", it->starred);
output->SetBoolean(item_prefix + ".from_previous", it->from_previous); output->SetBoolean(item_prefix + ".from_previous", it->from_previous);
for (AutocompleteMatch::AdditionalInfo::const_iterator j =
it->additional_info.begin(); j != it->additional_info.end(); ++j) {
output->SetString(item_prefix + ".additional_info." + j->first,
j->second);
}
} }
output->SetInteger(prefix + ".num_items", i); output->SetInteger(prefix + ".num_items", i);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment