Bug 1211726 - part 1: add results from a hardcoded list of top sites, r=Gijs,mak

MozReview-Commit-ID: 21FN4awJaXf

--HG--
extra : rebase_source : 7a19887273fb55e3a6285f79c50e7554067d39d4
This commit is contained in:
Svetlana Orlik 2017-01-02 03:28:31 +03:00
parent 4c3b2842d6
commit 615bc58434
7 changed files with 260 additions and 3 deletions

View File

@ -1059,6 +1059,12 @@ pref("browser.fixup.hide_user_pass", true);
// Location Bar AutoComplete
pref("browser.urlbar.autocomplete.enabled", true);
#ifdef NIGHTLY_BUILD
pref("browser.urlbar.usepreloadedtopurls.enabled", true);
#else
pref("browser.urlbar.usepreloadedtopurls.enabled", false);
#endif
pref("browser.urlbar.usepreloadedtopurls.expire_days", 14);
// Print header customization
// Use the following codes:

View File

@ -338,6 +338,8 @@ user_pref("browser.urlbar.suggest.searches", false);
// tests that don't expect it to be there.
user_pref("browser.urlbar.userMadeSearchSuggestionsChoice", true);
user_pref("browser.urlbar.usepreloadedtopurls.enabled", false);
user_pref("dom.audiochannel.mutedByDefault", false);
user_pref("webextensions.tests", true);

View File

@ -10,6 +10,8 @@
const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
const MS_PER_DAY = 86400000; // 24 * 60 * 60 * 1000
// Match type constants.
// These indicate what type of search function we should be using.
const MATCH_ANYWHERE = Ci.mozIPlacesAutoComplete.MATCH_ANYWHERE;
@ -47,6 +49,9 @@ const PREF_SUGGEST_SEARCHES = [ "suggest.searches", false ];
const PREF_MAX_CHARS_FOR_SUGGEST = [ "maxCharsForSearchSuggestions", 20];
const PREF_PREFILL_SITES_ENABLED = [ "usepreloadedtopurls.enabled", true ];
const PREF_PREFILL_SITES_EXPIRE_DAYS = [ "usepreloadedtopurls.expire_days", 14 ];
// AutoComplete query type constants.
// Describes the various types of queries that we can process rows for.
const QUERYTYPE_FILTERED = 0;
@ -284,6 +289,8 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesRemoteTabsAutocompleteProvider",
"resource://gre/modules/PlacesRemoteTabsAutocompleteProvider.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
"resource://gre/modules/BrowserUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
"resource://gre/modules/ProfileAge.jsm");
XPCOMUtils.defineLazyServiceGetter(this, "textURIService",
"@mozilla.org/intl/texttosuburi;1",
@ -466,6 +473,8 @@ XPCOMUtils.defineLazyGetter(this, "Prefs", () => {
store.suggestTyped = prefs.get(...PREF_SUGGEST_HISTORY_ONLYTYPED);
store.suggestSearches = prefs.get(...PREF_SUGGEST_SEARCHES);
store.maxCharsForSearchSuggestions = prefs.get(...PREF_MAX_CHARS_FOR_SUGGEST);
store.prefillSitesEnabled = prefs.get(...PREF_PREFILL_SITES_ENABLED);
store.prefillSitesExpireDays = prefs.get(...PREF_PREFILL_SITES_EXPIRE_DAYS);
store.keywordEnabled = true;
try {
store.keywordEnabled = Services.prefs.getBoolPref("keyword.enabled");
@ -539,6 +548,42 @@ XPCOMUtils.defineLazyGetter(this, "Prefs", () => {
return Object.seal(store);
});
// Prefill Sites related
function PrefillSite(url, title) {
this.uri = NetUtil.newURI(url);
this.title = title;
this._matchTitle = title.toLowerCase();
}
/**
* Storage object for Prefill Sites.
* add(url, title): adds a site to storage
* populate() : populates the storage with data (hard-coded for now)
* sites[]: resulting array of sites (PrefillSite objects)
*/
XPCOMUtils.defineLazyGetter(this, "PrefillSiteStorage", () => Object.seal({
sites: [],
add(url, title) {
let site = new PrefillSite(url, title);
this.sites.push(site);
},
populate() {
this.add("https://google.com/", "Google");
this.add("https://youtube.com/", "YouTube");
this.add("https://facebook.com/", "Facebook");
this.add("https://baidu.com/", "\u767E\u5EA6\u4E00\u4E0B\uFF0C\u4F60\u5C31\u77E5\u9053");
this.add("https://wikipedia.org/", "Wikipedia");
this.add("https://yahoo.com/", "Yahoo");
},
}));
XPCOMUtils.defineLazyGetter(this, "ProfileAgeCreatedPromise", () => {
return (new ProfileAge(null, null)).created;
});
// Helper functions
/**
@ -929,6 +974,9 @@ Search.prototype = {
}
queries.push(this._searchQuery);
// Check for Prefill Sites Expiry before Autofill
yield this._checkPrefillSitesExpiry();
// Add the first heuristic result, if any. Set _addingHeuristicFirstMatch
// to true so that when the result is added, "heuristic" can be included in
// its style.
@ -992,11 +1040,62 @@ Search.prototype = {
ExtensionSearchHandler.handleInputCancelled();
}
this._matchPrefillSites();
// Ensure to fill any remaining space. Suggestions which come from extensions are
// inserted at the beginning, so any suggestions
yield Promise.all(this._remoteMatchesPromises);
}),
*_checkPrefillSitesExpiry() {
if (!Prefs.prefillSitesEnabled)
return;
let profileCreationDate = yield ProfileAgeCreatedPromise;
let daysSinceProfileCreation = (Date.now() - profileCreationDate) / MS_PER_DAY;
if (daysSinceProfileCreation > Prefs.prefillSitesExpireDays)
Services.prefs.setBoolPref("browser.urlbar.usepreloadedtopurls.enabled", false);
},
// TODO: manage protocol and "www." like _matchSearchEngineUrl() does
_matchPrefillSites() {
if (!Prefs.prefillSitesEnabled)
return;
for (let site of PrefillSiteStorage.sites) {
if (site.uri.host.includes(this._searchString) ||
site._matchTitle.includes(this._searchString)) {
let match = {
value: site.uri.spec,
comment: site.title,
style: "prefill-site",
finalCompleteValue: site.uri.spec,
frecency: FRECENCY_DEFAULT - 1,
};
this._addMatch(match);
}
}
},
_matchPrefillSiteForAutofill() {
if (!Prefs.prefillSitesEnabled)
return false;
for (let site of PrefillSiteStorage.sites) {
if (site.uri.host.startsWith(this._searchString)) {
let match = {
value: stripPrefix(site.uri.spec),
comment: site.title,
style: "autofill",
finalCompleteValue: site.uri.spec,
frecency: FRECENCY_DEFAULT,
};
this._result.setDefaultIndex(0);
this._addMatch(match);
return true;
}
}
return false;
},
*_matchFirstHeuristicResult(conn) {
// We always try to make the first result a special "heuristic" result. The
// heuristics below determine what type of result it will be, if any.
@ -1044,6 +1143,13 @@ Search.prototype = {
}
}
if (this.pending && shouldAutofill) {
let matched = this._matchPrefillSiteForAutofill();
if (matched) {
return true;
}
}
if (this.pending && hasSearchTerms && this._enableActions) {
// If we don't have a result that matches what we know about, then
// we use a fallback for things we don't know about.
@ -1951,6 +2057,14 @@ function UnifiedComplete() {
// then all the other suggest preferences for history, bookmarks and
// open pages should be set to false.
Prefs;
if (Prefs.prefillSitesEnabled) {
// force initializing the profile age check
// to ensure the off-main-thread-IO happens ASAP
// and we don't have to wait for it when doing an autocomplete lookup
ProfileAgeCreatedPromise;
PrefillSiteStorage.populate(); // with hard-coded data for now
}
}
UnifiedComplete.prototype = {
@ -1999,9 +2113,9 @@ UnifiedComplete.prototype = {
return conn;
}).then(null, ex => {
dump("Couldn't get database handle: " + ex + "\n");
Cu.reportError(ex);
});
dump("Couldn't get database handle: " + ex + "\n");
Cu.reportError(ex);
});
}
return this._promiseDatabase;
},
@ -2016,6 +2130,10 @@ UnifiedComplete.prototype = {
SwitchToTabStorage.delete(uri, userContextId);
},
addPrefillSite(url, title) {
PrefillSiteStorage.add(url, title);
},
// nsIAutoCompleteSearch
startSearch(searchString, searchParam, previousResult, listener) {

View File

@ -135,4 +135,14 @@ interface mozIPlacesAutoComplete : nsISupports
* The Container Id of the tab.
*/
void unregisterOpenPage(in nsIURI aURI, in uint32_t aUserContextId);
/**
* Add a site to list of Prefill Sites.
*
* @param url
* The URL of added site.
* @param title
* The title of added site.
*/
void addPrefillSite(in AUTF8String url, in AUTF8String title);
};

View File

@ -77,6 +77,10 @@ var gTestDir = do_get_cwd();
// Initialize profile.
var gProfD = do_get_profile();
Services.prefs.setBoolPref("browser.urlbar.usepreloadedtopurls.enabled", false);
do_register_cleanup(() =>
Services.prefs.clearUserPref("browser.urlbar.usepreloadedtopurls.enabled"));
// Remove any old database.
clearDB();

View File

@ -0,0 +1,116 @@
/**
* Test for bug 1211726 - prefill list of top web sites for better
* autocompletion on empty profiles.
*/
const PREF_FEATURE_ENABLED = "browser.urlbar.usepreloadedtopurls.enabled";
const PREF_FEATURE_EXPIRE_DAYS = "browser.urlbar.usepreloadedtopurls.expire_days";
const autocompleteObject = Cc["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
.getService(Ci.mozIPlacesAutoComplete);
// With or without trailing slash - no matter. URI.spec does have it always.
// Then, check_autocomplete() doesn't cut it off (uses stripPrefix()).
let yahoooURI = NetUtil.newURI("https://yahooo.com/");
let gooogleURI = NetUtil.newURI("https://gooogle.com/");
autocompleteObject.addPrefillSite(yahoooURI.spec, "Yahooo");
autocompleteObject.addPrefillSite(gooogleURI.spec, "Gooogle");
function *assert_feature_works(condition) {
do_print("List Results do appear " + condition);
yield check_autocomplete({
search: "ooo",
matches: [
{ uri: yahoooURI, title: "Yahooo", style: ["prefill-site"] },
{ uri: gooogleURI, title: "Gooogle", style: ["prefill-site"] },
],
});
do_print("Autofill does appear " + condition);
yield check_autocomplete({
search: "gooo",
autofilled: "gooogle.com/", // Will fail without trailing slash
completed: "https://gooogle.com/",
});
}
function *assert_feature_does_not_appear(condition) {
do_print("List Results don't appear " + condition);
yield check_autocomplete({
search: "ooo",
matches: [],
});
do_print("Autofill doesn't appear " + condition);
// "search" is what you type,
// "autofilled" is what you get in response in the url bar,
// "completed" is what you get there when you hit enter.
// So if they are all equal - it's the proof there was no autofill
// (knowing we have a suitable prefill site).
yield check_autocomplete({
search: "gooo",
autofilled: "gooo",
completed: "gooo",
});
}
add_task(function* test_it_works() {
// Not expired but OFF
Services.prefs.setIntPref(PREF_FEATURE_EXPIRE_DAYS, 14);
Services.prefs.setBoolPref(PREF_FEATURE_ENABLED, false);
yield assert_feature_does_not_appear("when OFF by prefs");
// Now turn it ON
Services.prefs.setBoolPref(PREF_FEATURE_ENABLED, true);
yield assert_feature_works("when ON by prefs");
// And expire
Services.prefs.setIntPref(PREF_FEATURE_EXPIRE_DAYS, 0);
yield assert_feature_does_not_appear("when expired");
yield cleanup();
});
add_task(function* test_sorting_against_bookmark() {
let boookmarkURI = NetUtil.newURI("https://boookmark.com");
yield addBookmark( { uri: boookmarkURI, title: "Boookmark" } );
Services.prefs.setBoolPref(PREF_FEATURE_ENABLED, true);
Services.prefs.setIntPref(PREF_FEATURE_EXPIRE_DAYS, 14);
do_print("Prefill Sites are placed lower than Bookmarks");
yield check_autocomplete({
checkSorting: true,
search: "ooo",
matches: [
{ uri: boookmarkURI, title: "Boookmark", style: ["bookmark"] },
{ uri: yahoooURI, title: "Yahooo", style: ["prefill-site"] },
{ uri: gooogleURI, title: "Gooogle", style: ["prefill-site"] },
],
});
yield cleanup();
});
add_task(function* test_sorting_against_history() {
let histoooryURI = NetUtil.newURI("https://histooory.com");
yield PlacesTestUtils.addVisits( { uri: histoooryURI, title: "Histooory" } );
Services.prefs.setBoolPref(PREF_FEATURE_ENABLED, true);
Services.prefs.setIntPref(PREF_FEATURE_EXPIRE_DAYS, 14);
do_print("Prefill Sites are placed lower than History entries");
yield check_autocomplete({
checkSorting: true,
search: "ooo",
matches: [
{ uri: histoooryURI, title: "Histooory" },
{ uri: yahoooURI, title: "Yahooo", style: ["prefill-site"] },
{ uri: gooogleURI, title: "Gooogle", style: ["prefill-site"] },
],
});
yield cleanup();
});

View File

@ -30,6 +30,7 @@ support-files =
[test_keywords.js]
[test_match_beginning.js]
[test_multi_word_search.js]
[test_prefill_sites.js]
[test_query_url.js]
[test_remote_tab_matches.js]
skip-if = !sync