blob: 7a7e1b0b090ed052a0ae2b0801a9ba033a037e80 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
/**
* Javascript for omnibox.html, served from chrome://omnibox/
* This is used to debug omnibox ranking. The user enters some text
* into a box, submits it, and then sees lots of debug information
* from the autocompleter that shows what omnibox would do with that
* input.
*
* The simple object defined in this javascript file listens for
* certain events on omnibox.html, sends (when appropriate) the
* input text to C++ code to start the omnibox autcomplete controller
* working, and listens from callbacks from the C++ code saying that
* results are available. When results (possibly intermediate ones)
* are available, the Javascript formats them and displays them.
*/
(function () {
/**
* @type {number} the value for cursor position we sent with the most
* recent request. We need to remember this in order to display it
* in the output; otherwise it's hard or impossible to determine
* from screen captures or print-to-PDFs.
*/
let cursorPosition = -1;
/**
* Tracks and aggregates responses from the C++ autocomplete controller.
* Typically, the C++ controller returns 3 sets of results per query, unless
* a new query is submitted before all 3 responses. OutputController also
* triggers appending to and clearing of OmniboxOutput when appropriate (e.g.,
* upon receiving a new response or a change in display inputs).
*/
class OutputController {
constructor() {
/** @private {!Array<mojom.OmniboxResult>} */
this.outputResultsGroups_ = [];
}
clear() {
this.outputResultsGroups_ = [];
omniboxOutput.clearOutput();
}
/*
* Adds a new response to the page. If we're not displaying incomplete
* results, we clear the page and display only the new result. If we are
* displaying incomplete results, then this is more efficient than refresh,
* as there's no need to clear and re-add previous results.
*/
/** @param {!mojom.OmniboxResult} response A response from C++ autocomplete controller */
add(response) {
this.outputResultsGroups_.push(response);
if (!omniboxInputs.$$('show-incomplete-results').checked)
omniboxOutput.clearOutput();
addResultToOutput(
this.outputResultsGroups_[this.outputResultsGroups_.length - 1]);
}
/*
* Refreshes all results. We only display the last (most recent) entry
* unless incomplete results is enabled.
*/
refresh() {
omniboxOutput.clearOutput();
if (omniboxInputs.$$('show-incomplete-results').checked) {
this.outputResultsGroups_.forEach(addResultToOutput);
} else if (this.outputResultsGroups_.length) {
addResultToOutput(
this.outputResultsGroups_[this.outputResultsGroups_.length - 1]);
}
}
}
/**
* Appends some human-readable information about the provided
* autocomplete result to the HTML node with id omnibox-debug-text.
* The current human-readable form is a few lines about general
* autocomplete result statistics followed by a table with one line
* for each autocomplete match. The input parameter is an OmniboxResultMojo.
*/
function addResultToOutput(result) {
const resultsGroup = new omnibox_output.OutputResultsGroup(result).render(
omniboxInputs.$$('show-details').checked,
omniboxInputs.$$('show-incomplete-results').checked,
omniboxInputs.$$('show-all-providers').checked);
omniboxOutput.addOutput(resultsGroup);
}
class BrowserProxy {
constructor() {
/** @private {!mojom.OmniboxPageHandlerPtr} */
this.pagehandlePtr_ = new mojom.OmniboxPageHandlerPtr;
Mojo.bindInterface(
mojom.OmniboxPageHandler.name,
mojo.makeRequest(this.pagehandlePtr_).handle);
const client = new mojom.OmniboxPagePtr;
// NOTE: Need to keep a global reference to the |binding_| such that it is
// not garbage collected, which causes the pipe to close and future calls
// from C++ to JS to get dropped.
/** @private {!mojo.Binding} */
this.binding_ =
new mojo.Binding(mojom.OmniboxPage, this, mojo.makeRequest(client));
this.pagehandlePtr_.setClientPage(client);
}
/**
* Extracts the input text from the text field and sends it to the
* C++ portion of chrome to handle. The C++ code will iteratively
* call handleNewAutocompleteResult as results come in.
*/
makeRequest(inputString,
cursorPosition,
preventInlineAutocomplete,
preferKeyword,
pageClassification) {
outputController.clear();
// Then, call chrome with a five-element list:
// - first element: the value in the text box
// - second element: the location of the cursor in the text box
// - third element: the value of prevent-inline-autocomplete
// - forth element: the value of prefer-keyword
// - fifth element: the value of page-classification
this.pagehandlePtr_.startOmniboxQuery(
inputString,
cursorPosition,
preventInlineAutocomplete,
preferKeyword,
pageClassification);
}
handleNewAutocompleteResult(response) {
outputController.add(response);
}
}
/** @type {BrowserProxy} */
const browserProxy = new BrowserProxy();
/** @type {OmniboxInputs} */
let omniboxInputs;
/** @type {omnibox_output.OmniboxOutput} */
let omniboxOutput;
/** @type {OutputController} */
const outputController = new OutputController();
document.addEventListener('DOMContentLoaded', () => {
omniboxInputs = /** @type {!OmniboxInputs} */ ($('omnibox-inputs'));
omniboxOutput =
/** @type {!omnibox_output.OmniboxOutput} */ ($('omnibox-output'));
omniboxInputs.addEventListener('query-inputs-changed', event =>
browserProxy.makeRequest(
event.detail.inputText,
event.detail.cursorPosition,
event.detail.preventInlineAutocomplete,
event.detail.preferKeyword,
event.detail.pageClassification
));
omniboxInputs.addEventListener('display-inputs-changed',
outputController.refresh.bind(outputController));
});
})();