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 /** | 5 /** |
| 6 * Javascript for omnibox.html, served from chrome://omnibox/ | 6 * Javascript for omnibox.html, served from chrome://omnibox/ |
| 7 * This is used to debug omnibox ranking. The user enters some text | 7 * This is used to debug omnibox ranking. The user enters some text |
| 8 * into a box, submits it, and then sees lots of debug information | 8 * into a box, submits it, and then sees lots of debug information |
| 9 * from the autocompleter that shows what omnibox would do with that | 9 * from the autocompleter that shows what omnibox would do with that |
| 10 * input. | 10 * input. |
| 11 * | 11 * |
| 12 * The simple object defined in this javascript file listens for | 12 * The simple object defined in this javascript file listens for |
| 13 * certain events on omnibox.html, sends (when appropriate) the | 13 * certain events on omnibox.html, sends (when appropriate) the |
| 14 * input text to C++ code to start the omnibox autcomplete controller | 14 * input text to C++ code to start the omnibox autcomplete controller |
| 15 * working, and listens from callbacks from the C++ code saying that | 15 * working, and listens from callbacks from the C++ code saying that |
| 16 * results are available. When results (possibly intermediate ones) | 16 * results are available. When results (possibly intermediate ones) |
| 17 * are available, the Javascript formats them and displays them. | 17 * are available, the Javascript formats them and displays them. |
| 18 */ | 18 */ |
| 19 cr.define('omniboxDebug', function() { | 19 define('main', [ |
| 20 'mojo/public/bindings/js/connection', | |
| 21 'chrome/browser/ui/webui/omnibox/omnibox.mojom', | |
| 22 ], function(connector, browser) { | |
| 20 'use strict'; | 23 'use strict'; |
| 21 | 24 |
| 25 var connection; | |
|
sky
2014/04/02 17:54:10
I think this file can be restructured quite a bit.
| |
| 26 var page; | |
| 27 | |
| 22 /** | 28 /** |
| 23 * Register our event handlers. | 29 * Register our event handlers. |
| 24 */ | 30 */ |
| 25 function initialize() { | 31 function initialize() { |
| 26 $('omnibox-input-form').addEventListener( | 32 $('omnibox-input-form').addEventListener( |
| 27 'submit', startOmniboxQuery, false); | 33 'submit', startOmniboxQuery, false); |
| 28 $('prevent-inline-autocomplete').addEventListener( | 34 $('prevent-inline-autocomplete').addEventListener( |
| 29 'change', startOmniboxQuery); | 35 'change', startOmniboxQuery); |
| 30 $('prefer-keyword').addEventListener('change', startOmniboxQuery); | 36 $('prefer-keyword').addEventListener('change', startOmniboxQuery); |
| 31 $('page-classification').addEventListener('change', startOmniboxQuery); | 37 $('page-classification').addEventListener('change', startOmniboxQuery); |
| 32 $('show-details').addEventListener('change', refresh); | 38 $('show-details').addEventListener('change', refresh); |
| 33 $('show-incomplete-results').addEventListener('change', refresh); | 39 $('show-incomplete-results').addEventListener('change', refresh); |
| 34 $('show-all-providers').addEventListener('change', refresh); | 40 $('show-all-providers').addEventListener('change', refresh); |
| 35 } | 41 } |
| 36 | 42 |
| 37 /** | 43 /** |
| 38 * @type {Array.<Object>} an array of all autocomplete results we've seen | 44 * @type {OmniboxResultMojo} an array of all autocomplete results we've seen |
| 39 * for this query. We append to this list once for every call to | 45 * for this query. We append to this list once for every call to |
| 40 * handleNewAutocompleteResult. For details on the structure of | 46 * handleNewAutocompleteResult. See omnibox.mojom for details.. |
| 41 * the object inside, see the comments by addResultToOutput. | |
| 42 */ | 47 */ |
| 43 var progressiveAutocompleteResults = []; | 48 var progressiveAutocompleteResults = []; |
| 44 | 49 |
| 45 /** | 50 /** |
| 46 * @type {number} the value for cursor position we sent with the most | 51 * @type {number} the value for cursor position we sent with the most |
| 47 * recent request. We need to remember this in order to display it | 52 * recent request. We need to remember this in order to display it |
| 48 * in the output; otherwise it's hard or impossible to determine | 53 * in the output; otherwise it's hard or impossible to determine |
| 49 * from screen captures or print-to-PDFs. | 54 * from screen captures or print-to-PDFs. |
| 50 */ | 55 */ |
| 51 var cursorPositionUsed = -1; | 56 var cursorPositionUsed = -1; |
| 52 | 57 |
| 53 /** | 58 /** |
| 54 * Extracts the input text from the text field and sends it to the | 59 * Extracts the input text from the text field and sends it to the |
| 55 * C++ portion of chrome to handle. The C++ code will iteratively | 60 * C++ portion of chrome to handle. The C++ code will iteratively |
| 56 * call handleNewAutocompleteResult as results come in. | 61 * call handleNewAutocompleteResult as results come in. |
| 57 */ | 62 */ |
| 58 function startOmniboxQuery(event) { | 63 function startOmniboxQuery(event) { |
| 59 // First, clear the results of past calls (if any). | 64 // First, clear the results of past calls (if any). |
| 60 progressiveAutocompleteResults = []; | 65 progressiveAutocompleteResults = []; |
| 61 // Then, call chrome with a five-element list: | 66 // Then, call chrome with a five-element list: |
| 62 // - first element: the value in the text box | 67 // - first element: the value in the text box |
| 63 // - second element: the location of the cursor in the text box | 68 // - second element: the location of the cursor in the text box |
| 64 // - third element: the value of prevent-inline-autocomplete | 69 // - third element: the value of prevent-inline-autocomplete |
| 65 // - forth element: the value of prefer-keyword | 70 // - forth element: the value of prefer-keyword |
| 66 // - fifth element: the value of page-classification | 71 // - fifth element: the value of page-classification |
| 67 cursorPositionUsed = $('input-text').selectionEnd; | 72 cursorPositionUsed = $('input-text').selectionEnd; |
| 68 chrome.send('startOmniboxQuery', [ | 73 page.browser_.startOmniboxQuery( |
| 69 $('input-text').value, | 74 $('input-text').value, |
| 70 cursorPositionUsed, | 75 cursorPositionUsed, |
| 71 $('prevent-inline-autocomplete').checked, | 76 $('prevent-inline-autocomplete').checked, |
| 72 $('prefer-keyword').checked, | 77 $('prefer-keyword').checked, |
| 73 parseInt($('page-classification').value)]); | 78 parseInt($('page-classification').value)); |
| 74 // Cancel the submit action. i.e., don't submit the form. (We handle | 79 // Cancel the submit action. i.e., don't submit the form. (We handle |
| 75 // display the results solely with Javascript.) | 80 // display the results solely with Javascript.) |
| 76 event.preventDefault(); | 81 event.preventDefault(); |
| 77 } | 82 } |
| 78 | 83 |
| 79 /** | 84 /** |
| 80 * Returns a simple object with information about how to display an | 85 * Returns a simple object with information about how to display an |
| 81 * autocomplete result data field. | 86 * autocomplete result data field. |
| 82 * @param {string} header the label for the top of the column/table. | 87 * @param {string} header the label for the top of the column/table. |
| 83 * @param {string} urlLabelForHeader the URL that the header should point | 88 * @param {string} urlLabelForHeader the URL that the header should point |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 145 'Tran', | 150 'Tran', |
| 146 'http://code.google.com/codesearch#OAMlx_jo-ck/src/content/public/' + | 151 'http://code.google.com/codesearch#OAMlx_jo-ck/src/content/public/' + |
| 147 'common/page_transition_types.h&exact_package=chromium&l=24', | 152 'common/page_transition_types.h&exact_package=chromium&l=24', |
| 148 'transition', false, | 153 'transition', false, |
| 149 'How the user got to the result.'), | 154 'How the user got to the result.'), |
| 150 new PresentationInfoRecord( | 155 new PresentationInfoRecord( |
| 151 'Done', '', 'provider_done', false, | 156 'Done', '', 'provider_done', false, |
| 152 'A green checkmark indicates that the provider is done looking for ' + | 157 'A green checkmark indicates that the provider is done looking for ' + |
| 153 'more results.'), | 158 'more results.'), |
| 154 new PresentationInfoRecord( | 159 new PresentationInfoRecord( |
| 155 'Template URL', '', 'template_url', false, ''), | |
| 156 new PresentationInfoRecord( | |
| 157 'Associated Keyword', '', 'associated_keyword', false, | 160 'Associated Keyword', '', 'associated_keyword', false, |
| 158 'If non-empty, a "press tab to search" hint will be shown and will ' + | 161 'If non-empty, a "press tab to search" hint will be shown and will ' + |
| 159 'engage this keyword.'), | 162 'engage this keyword.'), |
| 160 new PresentationInfoRecord( | 163 new PresentationInfoRecord( |
| 161 'Keyword', '', 'keyword', false, | 164 'Keyword', '', 'keyword', false, |
| 162 'The keyword of the search engine to be used.'), | 165 'The keyword of the search engine to be used.'), |
| 163 new PresentationInfoRecord( | 166 new PresentationInfoRecord( |
| 164 'Duplicates', '', 'duplicates', false, | 167 'Duplicates', '', 'duplicates', false, |
| 165 'The number of matches that have been marked as duplicates of this ' + | 168 'The number of matches that have been marked as duplicates of this ' + |
| 166 'match.'), | 169 'match.'), |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 206 * suggestion that should go in this cell. | 209 * suggestion that should go in this cell. |
| 207 * @return {HTMLTableCellElement} that contains the value within this | 210 * @return {HTMLTableCellElement} that contains the value within this |
| 208 * autocompleteSuggestion associated with propertyName. | 211 * autocompleteSuggestion associated with propertyName. |
| 209 */ | 212 */ |
| 210 function createCellForPropertyAndRemoveProperty(autocompleteSuggestion, | 213 function createCellForPropertyAndRemoveProperty(autocompleteSuggestion, |
| 211 propertyName) { | 214 propertyName) { |
| 212 var cell = document.createElement('td'); | 215 var cell = document.createElement('td'); |
| 213 if (propertyName in autocompleteSuggestion) { | 216 if (propertyName in autocompleteSuggestion) { |
| 214 if (propertyName == 'additional_info') { | 217 if (propertyName == 'additional_info') { |
| 215 // |additional_info| embeds a two-column table of provider-specific data | 218 // |additional_info| embeds a two-column table of provider-specific data |
| 216 // within this cell. | 219 // within this cell. |additional_info| is an array of |
| 220 // AutocompleteAdditionalInfo. | |
| 217 var additionalInfoTable = document.createElement('table'); | 221 var additionalInfoTable = document.createElement('table'); |
| 218 for (var additionalInfoKey in autocompleteSuggestion[propertyName]) { | 222 for (var i = 0; i < autocompleteSuggestion[propertyName].length; i++) { |
| 223 var additionalInfo = autocompleteSuggestion[propertyName][i]; | |
| 219 var additionalInfoRow = document.createElement('tr'); | 224 var additionalInfoRow = document.createElement('tr'); |
| 220 | 225 |
| 221 // Set the title (name of property) cell text. | 226 // Set the title (name of property) cell text. |
| 222 var propertyCell = document.createElement('td'); | 227 var propertyCell = document.createElement('td'); |
| 223 propertyCell.textContent = additionalInfoKey + ':'; | 228 propertyCell.textContent = additionalInfo.key + ':'; |
| 224 propertyCell.className = 'additional-info-property'; | 229 propertyCell.className = 'additional-info-property'; |
| 225 additionalInfoRow.appendChild(propertyCell); | 230 additionalInfoRow.appendChild(propertyCell); |
| 226 | 231 |
| 227 // Set the value of the property cell text. | 232 // Set the value of the property cell text. |
| 228 var valueCell = document.createElement('td'); | 233 var valueCell = document.createElement('td'); |
| 229 valueCell.textContent = | 234 valueCell.textContent = additionalInfo.value; |
| 230 autocompleteSuggestion[propertyName][additionalInfoKey]; | |
| 231 valueCell.className = 'additional-info-value'; | 235 valueCell.className = 'additional-info-value'; |
| 232 additionalInfoRow.appendChild(valueCell); | 236 additionalInfoRow.appendChild(valueCell); |
| 233 | 237 |
| 234 additionalInfoTable.appendChild(additionalInfoRow); | 238 additionalInfoTable.appendChild(additionalInfoRow); |
| 235 } | 239 } |
| 236 cell.appendChild(additionalInfoTable); | 240 cell.appendChild(additionalInfoTable); |
| 237 } else if (typeof autocompleteSuggestion[propertyName] == 'boolean') { | 241 } else if (typeof autocompleteSuggestion[propertyName] == 'boolean') { |
| 238 // If this is a boolean, display a checkmark or an X instead of | 242 // If this is a boolean, display a checkmark or an X instead of |
| 239 // the strings true or false. | 243 // the strings true or false. |
| 240 if (autocompleteSuggestion[propertyName]) { | 244 if (autocompleteSuggestion[propertyName]) { |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 257 // All other data types (integer, strings, etc.) display their | 261 // All other data types (integer, strings, etc.) display their |
| 258 // normal toString() output. | 262 // normal toString() output. |
| 259 cell.textContent = autocompleteSuggestion[propertyName]; | 263 cell.textContent = autocompleteSuggestion[propertyName]; |
| 260 } | 264 } |
| 261 } | 265 } |
| 262 } // else: if propertyName is undefined, we leave the cell blank | 266 } // else: if propertyName is undefined, we leave the cell blank |
| 263 return cell; | 267 return cell; |
| 264 } | 268 } |
| 265 | 269 |
| 266 /** | 270 /** |
| 267 * Called by C++ code when we get an update from the | |
| 268 * AutocompleteController. We simply append the result to | |
| 269 * progressiveAutocompleteResults and refresh the page. | |
| 270 */ | |
| 271 function handleNewAutocompleteResult(result) { | |
| 272 progressiveAutocompleteResults.push(result); | |
| 273 refresh(); | |
| 274 } | |
| 275 | |
| 276 /** | |
| 277 * Appends some human-readable information about the provided | 271 * Appends some human-readable information about the provided |
| 278 * autocomplete result to the HTML node with id omnibox-debug-text. | 272 * autocomplete result to the HTML node with id omnibox-debug-text. |
| 279 * The current human-readable form is a few lines about general | 273 * The current human-readable form is a few lines about general |
| 280 * autocomplete result statistics followed by a table with one line | 274 * autocomplete result statistics followed by a table with one line |
| 281 * for each autocomplete match. The input parameter result is a | 275 * for each autocomplete match. The input parameter is an OmniboxResultMojo. |
| 282 * complex Object with lots of information about various | |
| 283 * autocomplete matches. Here's an example of what it looks like: | |
| 284 * <pre> | |
| 285 * {@code | |
| 286 * { | |
| 287 * 'done': false, | |
| 288 * 'time_since_omnibox_started_ms': 15, | |
| 289 * 'host': 'mai', | |
| 290 * 'is_typed_host': false, | |
| 291 * 'combined_results' : { | |
| 292 * 'num_items': 4, | |
| 293 * 'item_0': { | |
| 294 * 'destination_url': 'http://mail.google.com', | |
| 295 * 'provider_name': 'HistoryURL', | |
| 296 * 'relevance': 1410, | |
| 297 * ... | |
| 298 * } | |
| 299 * 'item_1: { | |
| 300 * ... | |
| 301 * } | |
| 302 * ... | |
| 303 * } | |
| 304 * 'results_by_provider': { | |
| 305 * 'HistoryURL' : { | |
| 306 * 'num_items': 3, | |
| 307 * ... | |
| 308 * } | |
| 309 * 'Search' : { | |
| 310 * 'num_items': 1, | |
| 311 * ... | |
| 312 * } | |
| 313 * ... | |
| 314 * } | |
| 315 * } | |
| 316 * } | |
| 317 * </pre> | |
| 318 * For more information on how the result is packed, see the | |
| 319 * corresponding code in chrome/browser/ui/webui/omnibox_ui.cc | |
| 320 */ | 276 */ |
| 321 function addResultToOutput(result) { | 277 function addResultToOutput(result) { |
| 322 var output = $('omnibox-debug-text'); | 278 var output = $('omnibox-debug-text'); |
| 323 var inDetailedMode = $('show-details').checked; | 279 var inDetailedMode = $('show-details').checked; |
| 324 var showIncompleteResults = $('show-incomplete-results').checked; | 280 var showIncompleteResults = $('show-incomplete-results').checked; |
| 325 var showPerProviderResults = $('show-all-providers').checked; | 281 var showPerProviderResults = $('show-all-providers').checked; |
| 326 | 282 |
| 327 // Always output cursor position. | 283 // Always output cursor position. |
| 328 var p = document.createElement('p'); | 284 var p = document.createElement('p'); |
| 329 p.textContent = 'cursor position = ' + cursorPositionUsed; | 285 p.textContent = 'cursor position = ' + cursorPositionUsed; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 370 | 326 |
| 371 // Individual results go after the lines below. | 327 // Individual results go after the lines below. |
| 372 var group = document.createElement('a'); | 328 var group = document.createElement('a'); |
| 373 group.className = 'group-separator'; | 329 group.className = 'group-separator'; |
| 374 group.textContent = 'Results for individual providers.'; | 330 group.textContent = 'Results for individual providers.'; |
| 375 output.appendChild(group); | 331 output.appendChild(group); |
| 376 | 332 |
| 377 // Add the per-provider result tables with labels. We do not append the | 333 // Add the per-provider result tables with labels. We do not append the |
| 378 // combined/merged result table since we already have the per provider | 334 // combined/merged result table since we already have the per provider |
| 379 // results. | 335 // results. |
| 380 for (var provider in result.results_by_provider) { | 336 for (var i = 0; i < result.results_by_provider.length; i++) { |
| 381 var results = result.results_by_provider[provider]; | 337 var providerResults = result.results_by_provider[i]; |
| 382 // If we have no results we do not display anything. | 338 // If we have no results we do not display anything. |
| 383 if (results.num_items == 0) { | 339 if (providerResults.results.length == 0) { |
| 384 continue; | 340 continue; |
| 385 } | 341 } |
| 386 var p = document.createElement('p'); | 342 var p = document.createElement('p'); |
| 387 p.appendChild(addResultTableToOutput(results)); | 343 p.appendChild(addResultTableToOutput(providerResults.results)); |
| 388 output.appendChild(p); | 344 output.appendChild(p); |
| 389 } | 345 } |
| 390 } | 346 } |
| 391 | 347 |
| 392 /** | 348 /** |
| 393 * @param {Object} result either the combined_results component of | 349 * @param {Object} result an array of AutocompleteMatchMojos. |
| 394 * the structure described in the comment by addResultToOutput() | |
| 395 * above or one of the per-provider results in the structure. | |
| 396 * (Both have the same format). | |
| 397 * @return {HTMLTableCellElement} that is a user-readable HTML | 350 * @return {HTMLTableCellElement} that is a user-readable HTML |
| 398 * representation of this object. | 351 * representation of this object. |
| 399 */ | 352 */ |
| 400 function addResultTableToOutput(result) { | 353 function addResultTableToOutput(result) { |
| 401 var inDetailedMode = $('show-details').checked; | 354 var inDetailedMode = $('show-details').checked; |
| 402 // Create a table to hold all the autocomplete items. | 355 // Create a table to hold all the autocomplete items. |
| 403 var table = document.createElement('table'); | 356 var table = document.createElement('table'); |
| 404 table.className = 'autocomplete-results-table'; | 357 table.className = 'autocomplete-results-table'; |
| 405 table.appendChild(createAutocompleteResultTableHeader()); | 358 table.appendChild(createAutocompleteResultTableHeader()); |
| 406 // Loop over every autocomplete item and add it as a row in the table. | 359 // Loop over every autocomplete item and add it as a row in the table. |
| 407 for (var i = 0; i < result.num_items; i++) { | 360 for (var i = 0; i < result.length; i++) { |
| 408 var autocompleteSuggestion = result['item_' + i]; | 361 var autocompleteSuggestion = result[i]; |
| 409 var row = document.createElement('tr'); | 362 var row = document.createElement('tr'); |
| 410 // Loop over all the columns/properties and output either them | 363 // Loop over all the columns/properties and output either them |
| 411 // all (if we're in detailed mode) or only the ones marked displayAlways. | 364 // all (if we're in detailed mode) or only the ones marked displayAlways. |
| 412 // Keep track of which properties we displayed. | 365 // Keep track of which properties we displayed. |
| 413 var displayedProperties = {}; | 366 var displayedProperties = {}; |
| 414 for (var j = 0; j < PROPERTY_OUTPUT_ORDER.length; j++) { | 367 for (var j = 0; j < PROPERTY_OUTPUT_ORDER.length; j++) { |
| 415 if (inDetailedMode || PROPERTY_OUTPUT_ORDER[j].displayAlways) { | 368 if (inDetailedMode || PROPERTY_OUTPUT_ORDER[j].displayAlways) { |
| 416 row.appendChild(createCellForPropertyAndRemoveProperty( | 369 row.appendChild(createCellForPropertyAndRemoveProperty( |
| 417 autocompleteSuggestion, PROPERTY_OUTPUT_ORDER[j].propertyName)); | 370 autocompleteSuggestion, PROPERTY_OUTPUT_ORDER[j].propertyName)); |
| 418 displayedProperties[PROPERTY_OUTPUT_ORDER[j].propertyName] = true; | 371 displayedProperties[PROPERTY_OUTPUT_ORDER[j].propertyName] = true; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 457 // Display the results. | 410 // Display the results. |
| 458 var showIncompleteResults = $('show-incomplete-results').checked; | 411 var showIncompleteResults = $('show-incomplete-results').checked; |
| 459 var startIndex = showIncompleteResults ? 0 : | 412 var startIndex = showIncompleteResults ? 0 : |
| 460 progressiveAutocompleteResults.length - 1; | 413 progressiveAutocompleteResults.length - 1; |
| 461 for (var i = startIndex; i < progressiveAutocompleteResults.length; i++) { | 414 for (var i = startIndex; i < progressiveAutocompleteResults.length; i++) { |
| 462 addResultToOutput(progressiveAutocompleteResults[i]); | 415 addResultToOutput(progressiveAutocompleteResults[i]); |
| 463 } | 416 } |
| 464 } | 417 } |
| 465 } | 418 } |
| 466 | 419 |
| 467 return { | 420 function OmniboxPageImpl(browser) { |
| 468 initialize: initialize, | 421 this.browser_ = browser; |
| 469 startOmniboxQuery: startOmniboxQuery, | 422 page = this; |
| 470 handleNewAutocompleteResult: handleNewAutocompleteResult | 423 initialize(); |
| 424 } | |
| 425 | |
| 426 OmniboxPageImpl.prototype = | |
| 427 Object.create(browser.OmniboxPageStub.prototype); | |
| 428 | |
| 429 OmniboxPageImpl.prototype.handleNewAutocompleteResult = function(result) { | |
| 430 progressiveAutocompleteResults.push(result); | |
| 431 refresh(); | |
| 432 }; | |
| 433 | |
| 434 return function(handle) { | |
| 435 connection = new connector.Connection(handle, OmniboxPageImpl, | |
| 436 browser.OmniboxUIHandlerMojoProxy); | |
| 471 }; | 437 }; |
| 472 }); | 438 }); |
| 473 | |
| 474 document.addEventListener('DOMContentLoaded', omniboxDebug.initialize); | |
| OLD | NEW |