Skip to content

Commit

Permalink
Merge pull request #1231 from smblott-github/tabs-order
Browse files Browse the repository at this point in the history
Tabs order; order tabs by recency for empty searches.
  • Loading branch information
smblott-github committed Nov 9, 2014
2 parents 3d647c9 + 5492249 commit 2687fbe
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
29 changes: 28 additions & 1 deletion background_scripts/completion.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,29 @@ class DomainCompleter
# Suggestions from the Domain completer have the maximum relevancy. They should be shown first in the list.
computeRelevancy: -> 1

# TabRecency associates a logical timestamp with each tab id.
class TabRecency
constructor: ->
@timestamp = 1
@cache = {}

chrome.tabs.onActivated.addListener (activeInfo) => @add activeInfo.tabId
chrome.tabs.onRemoved.addListener (tabId) => @remove tabId

chrome.tabs.onReplaced.addListener (addedTabId, removedTabId) =>
@remove removedTabId
@add addedTabId

add: (tabId) -> @cache[tabId] = ++@timestamp
remove: (tabId) -> delete @cache[tabId]

# Recently-visited tabs get a higher score (except the current tab, which gets a low score).
recencyScore: (tabId) ->
@cache[tabId] ||= 1
if @cache[tabId] == @timestamp then 0.0 else @cache[tabId] / @timestamp

tabRecency = new TabRecency()

# Searches through all open tabs, matching on title and URL.
class TabCompleter
filter: (queryTerms, onComplete) ->
Expand All @@ -276,7 +299,10 @@ class TabCompleter
onComplete(suggestions)

computeRelevancy: (suggestion) ->
RankingUtils.wordRelevancy(suggestion.queryTerms, suggestion.url, suggestion.title)
if suggestion.queryTerms.length
RankingUtils.wordRelevancy(suggestion.queryTerms, suggestion.url, suggestion.title)
else
tabRecency.recencyScore(suggestion.tabId)

# A completer which will return your search engines
class SearchEngineCompleter
Expand Down Expand Up @@ -549,3 +575,4 @@ root.SearchEngineCompleter = SearchEngineCompleter
root.HistoryCache = HistoryCache
root.RankingUtils = RankingUtils
root.RegexpCache = RegexpCache
root.TabRecency = TabRecency
42 changes: 41 additions & 1 deletion tests/unit_tests/completion_test.coffee
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
require "./test_helper.js"
extend(global, require "../../lib/utils.js")
extend(global, require "../../background_scripts/completion.js")
extend global, require "./test_chrome_stubs.js"

global.chrome = {}
global.document =
createElement: -> {}

Expand Down Expand Up @@ -399,6 +399,46 @@ context "RegexpCache",
should "search for a string with a prefix/suffix (negative case)", ->
assert.isTrue "hound dog".search(RegexpCache.get("do", "\\b", "\\b")) == -1

context "TabRecency",
setup ->
@tabRecency = new TabRecency()
@tabRecency.add 3
@tabRecency.add 2
@tabRecency.add 9
@tabRecency.add 1
@tabRecency.remove 9
@tabRecency.add 4

should "have entries for active tabs", ->
assert.isTrue @tabRecency.cache[1]
assert.isTrue @tabRecency.cache[2]
assert.isTrue @tabRecency.cache[3]
assert.isTrue @tabRecency.cache[4]

should "not have entries for removed tabs", ->
assert.isFalse @tabRecency.cache[9]

should "give a high score to the most recent tab", ->
assert.isTrue @tabRecency.recencyScore(4) < @tabRecency.recencyScore 1
assert.isTrue @tabRecency.recencyScore(3) < @tabRecency.recencyScore 1
assert.isTrue @tabRecency.recencyScore(2) < @tabRecency.recencyScore 1

should "give a low score to the current tab", ->
assert.isTrue @tabRecency.recencyScore(1) > @tabRecency.recencyScore 4
assert.isTrue @tabRecency.recencyScore(2) > @tabRecency.recencyScore 4
assert.isTrue @tabRecency.recencyScore(3) > @tabRecency.recencyScore 4

should "rank tabs by recency", ->
assert.isTrue @tabRecency.recencyScore(3) < @tabRecency.recencyScore 2
assert.isTrue @tabRecency.recencyScore(2) < @tabRecency.recencyScore 1
@tabRecency.add 3
@tabRecency.add 4 # Making 3 the most recent tab which isn't the current tab.
assert.isTrue @tabRecency.recencyScore(1) < @tabRecency.recencyScore 3
assert.isTrue @tabRecency.recencyScore(2) < @tabRecency.recencyScore 3
assert.isTrue @tabRecency.recencyScore(4) < @tabRecency.recencyScore 3
assert.isTrue @tabRecency.recencyScore(4) < @tabRecency.recencyScore 1
assert.isTrue @tabRecency.recencyScore(4) < @tabRecency.recencyScore 2

# A convenience wrapper around completer.filter() so it can be called synchronously in tests.
filterCompleter = (completer, queryTerms) ->
results = []
Expand Down
4 changes: 4 additions & 0 deletions tests/unit_tests/test_chrome_stubs.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ exports.chrome =
addListener: () -> true
onActiveChanged:
addListener: () -> true
onActivated:
addListener: () -> true
onReplaced:
addListener: () -> true
query: () -> true

windows:
Expand Down

0 comments on commit 2687fbe

Please sign in to comment.