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; |
}; |
} |