| Index: chrome/renderer/resources/extensions/searchbox_api.js
|
| diff --git a/chrome/renderer/resources/extensions/searchbox_api.js b/chrome/renderer/resources/extensions/searchbox_api.js
|
| index d5d58afbbfd0f7cd9f5855ec06fc09226e307b5c..70471d0be283c2fcefbd28d1df9855a24da0ba8a 100644
|
| --- a/chrome/renderer/resources/extensions/searchbox_api.js
|
| +++ b/chrome/renderer/resources/extensions/searchbox_api.js
|
| @@ -3,342 +3,38 @@
|
| // found in the LICENSE file.
|
|
|
| var chrome;
|
| +
|
| if (!chrome)
|
| chrome = {};
|
|
|
| -if (!chrome.embeddedSearch) {
|
| - chrome.embeddedSearch = new function() {
|
| -
|
| - // =========================================================================
|
| - // Private functions
|
| - // =========================================================================
|
| - native function GetFont();
|
| - native function NavigateContentWindow();
|
| -
|
| - function escapeHTML(text) {
|
| - return text.replace(/[<>&"']/g, function(match) {
|
| - switch (match) {
|
| - case '<': return '<';
|
| - case '>': return '>';
|
| - case '&': return '&';
|
| - case '"': return '"';
|
| - case "'": return ''';
|
| - }
|
| - });
|
| - }
|
| -
|
| - var safeObjects = {};
|
| -
|
| - // Returns the |restrictedText| wrapped in a ShadowDOM.
|
| - function SafeWrap(restrictedText, width, height, opt_fontSize,
|
| - opt_direction) {
|
| - var node = document.createElement('div');
|
| - var nodeShadow = safeObjects.createShadowRoot.apply(node);
|
| - nodeShadow.applyAuthorStyles = true;
|
| - nodeShadow.innerHTML =
|
| - '<div style="' +
|
| - 'width: ' + width + 'px !important;' +
|
| - 'height: ' + height + 'px !important;' +
|
| - 'font-family: \'' + GetFont() + '\', \'Arial\' !important;' +
|
| - (opt_fontSize ?
|
| - 'font-size: ' + opt_fontSize + 'px !important;' : '') +
|
| - 'overflow: hidden !important;' +
|
| - 'text-overflow: ellipsis !important;' +
|
| - 'white-space: nowrap !important"' +
|
| - (opt_direction ? ' dir="' + opt_direction + '"' : '') +
|
| - '>' +
|
| - restrictedText +
|
| - '</div>';
|
| - safeObjects.defineProperty(node, 'webkitShadowRoot', { value: null });
|
| - return node;
|
| - }
|
| -
|
| - chrome.embeddedSearchOnWindowReady = function() {
|
| - // |embeddedSearchOnWindowReady| is used for initializing window context
|
| - // and should be called only once per context.
|
| - safeObjects.createShadowRoot = Element.prototype.webkitCreateShadowRoot;
|
| - safeObjects.defineProperty = Object.defineProperty;
|
| - delete window.chrome.embeddedSearchOnWindowReady;
|
| - };
|
| -
|
| - // =========================================================================
|
| - // Exported functions
|
| - // =========================================================================
|
| - this.navigateContentWindow = function(destination, disposition) {
|
| - return NavigateContentWindow(destination, disposition);
|
| - };
|
| -
|
| - this.searchBox = new function() {
|
| -
|
| - // =======================================================================
|
| - // Constants
|
| - // =======================================================================
|
| - var MAX_CLIENT_SUGGESTIONS_TO_DEDUPE = 6;
|
| - var MAX_ALLOWED_DEDUPE_ATTEMPTS = 5;
|
| -
|
| - var HTTP_REGEX = /^https?:\/\//;
|
| -
|
| - var WWW_REGEX = /^www\./;
|
| -
|
| - // =======================================================================
|
| - // Private functions
|
| - // =======================================================================
|
| - native function GetQuery();
|
| - native function GetVerbatim();
|
| - native function GetSelectionStart();
|
| - native function GetSelectionEnd();
|
| - native function GetStartMargin();
|
| - native function GetRightToLeft();
|
| - native function GetAutocompleteResults();
|
| - native function GetDisplayInstantResults();
|
| - native function GetFontSize();
|
| - native function IsKeyCaptureEnabled();
|
| - native function SetSuggestions();
|
| - native function SetQuerySuggestion();
|
| - native function SetQuerySuggestionFromAutocompleteResult();
|
| - native function SetQuery();
|
| - native function SetQueryFromAutocompleteResult();
|
| - native function ShowOverlay();
|
| - native function FocusOmnibox();
|
| - native function StartCapturingKeyStrokes();
|
| - native function StopCapturingKeyStrokes();
|
| -
|
| - function SafeWrapSuggestion(restrictedText) {
|
| - return SafeWrap(restrictedText, window.innerWidth - 155, 22);
|
| - }
|
| -
|
| - // Wraps the AutocompleteResult query and URL into ShadowDOM nodes so that
|
| - // the JS cannot access them and deletes the raw values.
|
| - function GetAutocompleteResultsWrapper() {
|
| - var autocompleteResults = DedupeAutocompleteResults(
|
| - GetAutocompleteResults());
|
| - var userInput = GetQuery();
|
| - for (var i = 0, result; result = autocompleteResults[i]; ++i) {
|
| - var title = escapeHTML(result.contents);
|
| - var url = escapeHTML(CleanUrl(result.destination_url, userInput));
|
| - var combinedHtml = '<span class=chrome_url>' + url + '</span>';
|
| - // TODO(dcblack): Rename these titleElement, urlElement, and
|
| - // combinedElement for optimal correctness.
|
| - if (title) {
|
| - result.titleNode = SafeWrapSuggestion(title);
|
| - combinedHtml += '<span class=chrome_separator> – </span>' +
|
| - '<span class=chrome_title>' + title + '</span>';
|
| - }
|
| - result.urlNode = SafeWrapSuggestion(url);
|
| - result.combinedNode = SafeWrapSuggestion(combinedHtml);
|
| - delete result.contents;
|
| - delete result.destination_url;
|
| - }
|
| - return autocompleteResults;
|
| - }
|
| -
|
| - // TODO(dcblack): Do this in C++ instead of JS.
|
| - function CleanUrl(url, userInput) {
|
| - if (url.indexOf(userInput) == 0) {
|
| - return url;
|
| - }
|
| - url = url.replace(HTTP_REGEX, '');
|
| - if (url.indexOf(userInput) == 0) {
|
| - return url;
|
| - }
|
| - return url.replace(WWW_REGEX, '');
|
| - }
|
| -
|
| - // TODO(dcblack): Do this in C++ instead of JS.
|
| - function CanonicalizeUrl(url) {
|
| - return url.replace(HTTP_REGEX, '').replace(WWW_REGEX, '');
|
| - }
|
| -
|
| - // Removes duplicates from AutocompleteResults.
|
| - // TODO(dcblack): Do this in C++ instead of JS.
|
| - function DedupeAutocompleteResults(autocompleteResults) {
|
| - var urlToResultMap = {};
|
| - for (var i = 0, result; result = autocompleteResults[i]; ++i) {
|
| - var url = CanonicalizeUrl(result.destination_url);
|
| - if (url in urlToResultMap) {
|
| - var oldRelevance = urlToResultMap[url].rankingData.relevance;
|
| - var newRelevance = result.rankingData.relevance;
|
| - if (newRelevance > oldRelevance) {
|
| - urlToResultMap[url] = result;
|
| - }
|
| - } else {
|
| - urlToResultMap[url] = result;
|
| - }
|
| - }
|
| - var dedupedResults = [];
|
| - for (url in urlToResultMap) {
|
| - dedupedResults.push(urlToResultMap[url]);
|
| - }
|
| - return dedupedResults;
|
| - }
|
| -
|
| - var lastPrefixQueriedForDuplicates = '';
|
| - var numDedupeAttempts = 0;
|
| -
|
| - function DedupeClientSuggestions(clientSuggestions) {
|
| - var userInput = GetQuery();
|
| - if (userInput == lastPrefixQueriedForDuplicates) {
|
| - numDedupeAttempts += 1;
|
| - if (numDedupeAttempts > MAX_ALLOWED_DEDUPE_ATTEMPTS) {
|
| - // Request blocked for privacy reasons.
|
| - // TODO(dcblack): This check is insufficient. We should have a
|
| - // check such that it's only callable once per onnativesuggestions,
|
| - // not once per prefix. Also, there is a timing problem where if
|
| - // the user types quickly then the client will (correctly) attempt
|
| - // to render stale results, and end up calling dedupe multiple times
|
| - // when getValue shows the same prefix. A better solution would be
|
| - // to have the client send up rid ranges to dedupe against and have
|
| - // the binary keep around all the old suggestions ever given to this
|
| - // overlay. I suspect such an approach would clean up this code
|
| - // quite a bit.
|
| - return false;
|
| - }
|
| - } else {
|
| - lastPrefixQueriedForDuplicates = userInput;
|
| - numDedupeAttempts = 1;
|
| - }
|
| -
|
| - var autocompleteResults = DedupeAutocompleteResults(
|
| - GetAutocompleteResults());
|
| - var nativeUrls = {};
|
| - for (var i = 0, result; result = autocompleteResults[i]; ++i) {
|
| - var nativeUrl = CanonicalizeUrl(result.destination_url);
|
| - nativeUrls[nativeUrl] = result.rid;
|
| - }
|
| - for (var i = 0; clientSuggestions[i] &&
|
| - i < MAX_CLIENT_SUGGESTIONS_TO_DEDUPE; ++i) {
|
| - var result = clientSuggestions[i];
|
| - if (result.url) {
|
| - var clientUrl = CanonicalizeUrl(result.url);
|
| - if (clientUrl in nativeUrls) {
|
| - result.duplicateOf = nativeUrls[clientUrl];
|
| - }
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - // =======================================================================
|
| - // Exported functions
|
| - // =======================================================================
|
| - this.__defineGetter__('value', GetQuery);
|
| - this.__defineGetter__('verbatim', GetVerbatim);
|
| - this.__defineGetter__('selectionStart', GetSelectionStart);
|
| - this.__defineGetter__('selectionEnd', GetSelectionEnd);
|
| - this.__defineGetter__('startMargin', GetStartMargin);
|
| - this.__defineGetter__('rtl', GetRightToLeft);
|
| - this.__defineGetter__('nativeSuggestions', GetAutocompleteResultsWrapper);
|
| - this.__defineGetter__('isKeyCaptureEnabled', IsKeyCaptureEnabled);
|
| - this.__defineGetter__('displayInstantResults', GetDisplayInstantResults);
|
| - this.__defineGetter__('font', GetFont);
|
| - this.__defineGetter__('fontSize', GetFontSize);
|
| -
|
| - this.setSuggestions = function(text) {
|
| - SetSuggestions(text);
|
| - };
|
| - this.setAutocompleteText = function(text, behavior) {
|
| - SetQuerySuggestion(text, behavior);
|
| - };
|
| - this.setRestrictedAutocompleteText = function(resultId) {
|
| - SetQuerySuggestionFromAutocompleteResult(resultId);
|
| - };
|
| - this.setValue = function(text, type) {
|
| - SetQuery(text, type);
|
| - };
|
| - this.setRestrictedValue = function(resultId) {
|
| - SetQueryFromAutocompleteResult(resultId);
|
| - };
|
| - // TODO(jered): Remove the deprecated "reason" argument.
|
| - this.showOverlay = function(reason, height) {
|
| - ShowOverlay(reason, height);
|
| - };
|
| - // TODO(jered): Remove this when GWS knows about showOverlay().
|
| - this.show = this.showOverlay;
|
| - this.markDuplicateSuggestions = function(clientSuggestions) {
|
| - return DedupeClientSuggestions(clientSuggestions);
|
| - };
|
| - this.focus = function() {
|
| - FocusOmnibox();
|
| - };
|
| - this.startCapturingKeyStrokes = function() {
|
| - StartCapturingKeyStrokes();
|
| - };
|
| - this.stopCapturingKeyStrokes = function() {
|
| - StopCapturingKeyStrokes();
|
| - };
|
| - this.onchange = null;
|
| - this.onsubmit = null;
|
| - this.oncancel = null;
|
| - this.onresize = null;
|
| - this.onkeypress = null;
|
| - this.onkeycapturechange = null;
|
| - this.oncontextchange = null;
|
| - this.onmarginchange = null;
|
| - this.onnativesuggestions = null;
|
| -
|
| - // DEPRECATED. These methods are from the legacy searchbox API.
|
| - // TODO(jered): Delete these.
|
| - native function GetX();
|
| - native function GetY();
|
| - native function GetWidth();
|
| - native function GetHeight();
|
| - this.__defineGetter__('x', GetX);
|
| - this.__defineGetter__('y', GetY);
|
| - this.__defineGetter__('width', GetWidth);
|
| - this.__defineGetter__('height', GetHeight);
|
| - };
|
| -
|
| - this.newTabPage = new function() {
|
| -
|
| - // =======================================================================
|
| - // Private functions
|
| - // =======================================================================
|
| - native function GetMostVisitedItems();
|
| - native function GetThemeBackgroundInfo();
|
| - native function DeleteMostVisitedItem();
|
| - native function UndoAllMostVisitedDeletions();
|
| - native function UndoMostVisitedDeletion();
|
| -
|
| - function SafeWrapMostVisited(restrictedText, width, opt_direction) {
|
| - return SafeWrap(restrictedText, width, 18, 11, opt_direction);
|
| - }
|
| -
|
| - function GetMostVisitedItemsWrapper() {
|
| - var mostVisitedItems = GetMostVisitedItems();
|
| - for (var i = 0, item; item = mostVisitedItems[i]; ++i) {
|
| - var title = escapeHTML(item.title);
|
| - var domain = escapeHTML(item.domain);
|
| - item.titleElement = SafeWrapMostVisited(title, 140, item.direction);
|
| - item.domainElement = SafeWrapMostVisited(domain, 123);
|
| - delete item.title;
|
| - delete item.domain;
|
| - delete item.direction;
|
| - }
|
| - return mostVisitedItems;
|
| - }
|
| -
|
| - // =======================================================================
|
| - // Exported functions
|
| - // =======================================================================
|
| - this.__defineGetter__('mostVisited', GetMostVisitedItemsWrapper);
|
| - this.__defineGetter__('themeBackgroundInfo', GetThemeBackgroundInfo);
|
| -
|
| - this.deleteMostVisitedItem = function(restrictId) {
|
| - DeleteMostVisitedItem(restrictId);
|
| - };
|
| - this.undoAllMostVisitedDeletions = function() {
|
| - UndoAllMostVisitedDeletions();
|
| - };
|
| - this.undoMostVisitedDeletion = function(restrictId) {
|
| - UndoMostVisitedDeletion(restrictId);
|
| - };
|
| -
|
| - this.onmostvisitedchange = null;
|
| - this.onthemechange = null;
|
| +if (!chrome.searchBox) {
|
| + chrome.searchBox = new function() {
|
| + native function GetQuery();
|
| + native function GetVerbatim();
|
| + native function GetSelectionStart();
|
| + native function GetSelectionEnd();
|
| + native function GetX();
|
| + native function GetY();
|
| + native function GetWidth();
|
| + native function GetHeight();
|
| + native function SetSuggestion();
|
| +
|
| + this.__defineGetter__('value', GetQuery);
|
| + this.__defineGetter__('verbatim', GetVerbatim);
|
| + this.__defineGetter__('selectionStart', GetSelectionStart);
|
| + this.__defineGetter__('selectionEnd', GetSelectionEnd);
|
| + this.__defineGetter__('x', GetX);
|
| + this.__defineGetter__('y', GetY);
|
| + this.__defineGetter__('width', GetWidth);
|
| + this.__defineGetter__('height', GetHeight);
|
| +
|
| + this.setSuggestions = function(obj) {
|
| + SetSuggestion(obj);
|
| };
|
|
|
| - // Export legacy searchbox API.
|
| - // TODO: Remove this when Instant Extended is fully launched.
|
| - chrome.searchBox = this.searchBox;
|
| + this.onchange = null;
|
| + this.onsubmit = null;
|
| + this.oncancel = null;
|
| + this.onresize = null;
|
| };
|
| }
|
|
|