зеркало из https://github.com/mozilla/gecko-dev.git
Bug 462674 - URLBar: Autocomplete "about:" URLs r=mak
Pages that are whitelisted for displaying on about:about can be autocompleted in the URL bar. MozReview-Commit-ID: BYhWUImyiJH Differential Revision: https://phabricator.services.mozilla.com/D3072 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
617554ae49
Коммит
b5b19652b2
|
@ -334,6 +334,7 @@ ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|||
XPCOMUtils.defineLazyGlobalGetters(this, ["fetch"]);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
AboutPagesUtils: "resource://gre/modules/AboutPagesUtils.jsm",
|
||||
BrowserUtils: "resource://gre/modules/BrowserUtils.jsm",
|
||||
ExtensionSearchHandler: "resource://gre/modules/ExtensionSearchHandler.jsm",
|
||||
OS: "resource://gre/modules/osfile.jsm",
|
||||
|
@ -1020,6 +1021,8 @@ Search.prototype = {
|
|||
// may be really slow and we may end up showing old results for too long.
|
||||
this._cleanUpNonCurrentMatches(UrlbarUtils.MATCHTYPE.GENERAL);
|
||||
|
||||
this._matchAboutPages();
|
||||
|
||||
// If we do not have enough results, and our match type is
|
||||
// MATCH_BOUNDARY_ANYWHERE, search again with MATCH_ANYWHERE to get more
|
||||
// results.
|
||||
|
@ -1043,6 +1046,46 @@ Search.prototype = {
|
|||
await extensionsCompletePromise;
|
||||
},
|
||||
|
||||
_shouldMatchAboutPages() {
|
||||
// Only autocomplete input that starts with 'about:' and has at least 1 more
|
||||
// character.
|
||||
return (this._strippedPrefix == "about:" &&
|
||||
this._searchString);
|
||||
},
|
||||
|
||||
_matchAboutPages() {
|
||||
if (!this._shouldMatchAboutPages()) {
|
||||
return;
|
||||
}
|
||||
for (const url of AboutPagesUtils.visibleAboutUrls) {
|
||||
if (url.startsWith(`about:${this._searchString}`)) {
|
||||
this._addMatch({
|
||||
value: url,
|
||||
comment: url,
|
||||
frecency: FRECENCY_DEFAULT,
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_matchAboutPageForAutofill() {
|
||||
if (!this._shouldMatchAboutPages()) {
|
||||
return false;
|
||||
}
|
||||
for (const url of AboutPagesUtils.visibleAboutUrls) {
|
||||
if (url.startsWith(`about:${this._searchString}`)) {
|
||||
this._addAutofillMatch(
|
||||
url.replace(/^about:/, ""),
|
||||
url,
|
||||
Infinity,
|
||||
[]
|
||||
);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
async _checkPreloadedSitesExpiry() {
|
||||
if (!UrlbarPrefs.get("usepreloadedtopurls.enabled"))
|
||||
return;
|
||||
|
@ -1138,6 +1181,15 @@ Search.prototype = {
|
|||
}
|
||||
|
||||
let shouldAutofill = this._shouldAutofill;
|
||||
|
||||
if (this.pending && shouldAutofill) {
|
||||
// It may also look like an about: link.
|
||||
let matched = await this._matchAboutPageForAutofill();
|
||||
if (matched) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.pending && shouldAutofill) {
|
||||
// It may also look like a URL we know from the database.
|
||||
let matched = await this._matchKnownUrl(conn);
|
||||
|
@ -2154,7 +2206,7 @@ Search.prototype = {
|
|||
if (this._searchTokens.length != 1)
|
||||
return false;
|
||||
|
||||
// autoFill can only cope with history or bookmarks entries.
|
||||
// autoFill can only cope with history, bookmarks, and about: entries.
|
||||
if (!this.hasBehavior("history") &&
|
||||
!this.hasBehavior("bookmark"))
|
||||
return false;
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
// "about:ab" should match "about:about"
|
||||
add_task(async function aboutAb() {
|
||||
await check_autocomplete({
|
||||
search: "about:ab",
|
||||
autofilled: "about:ab",
|
||||
completed: "about:ab",
|
||||
matches: [{
|
||||
value: "about:about",
|
||||
comment: "about:about",
|
||||
style: ["autofill", "heuristic"],
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
// "about:about" should match "about:about"
|
||||
add_task(async function aboutAbout() {
|
||||
await check_autocomplete({
|
||||
search: "about:about",
|
||||
autofilled: "about:about",
|
||||
completed: "about:about",
|
||||
matches: [{
|
||||
value: "about:about",
|
||||
comment: "about:about",
|
||||
style: ["autofill", "heuristic"],
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
// "about:a" should complete to "about:about" and also match "about:addons"
|
||||
add_task(async function aboutAboutAndAboutAddons() {
|
||||
await check_autocomplete({
|
||||
search: "about:a",
|
||||
autofilled: "about:a",
|
||||
completed: "about:a",
|
||||
matches: [{
|
||||
value: "about:about",
|
||||
comment: "about:about",
|
||||
style: ["autofill", "heuristic"],
|
||||
}, {
|
||||
value: "about:addons",
|
||||
comment: "about:addons",
|
||||
}],
|
||||
});
|
||||
});
|
||||
|
||||
// "about:" should *not* match anything
|
||||
add_task(async function aboutColonHasNoMatch() {
|
||||
await check_autocomplete({
|
||||
search: "about:",
|
||||
autofilled: "about:",
|
||||
completed: "about:",
|
||||
matches: [],
|
||||
});
|
||||
});
|
|
@ -49,9 +49,9 @@ add_task(async function() {
|
|||
|
||||
info("visit url, about: protocol (no host)");
|
||||
await check_autocomplete({
|
||||
search: "about:config",
|
||||
search: "about:nonexistent",
|
||||
searchParam: "enable-actions",
|
||||
matches: [ { uri: makeActionURI("visiturl", {url: "about:config", input: "about:config"}), title: "about:config", style: [ "action", "visiturl", "heuristic" ] } ],
|
||||
matches: [ { uri: makeActionURI("visiturl", {url: "about:nonexistent", input: "about:nonexistent"}), title: "about:nonexistent", style: [ "action", "visiturl", "heuristic" ] } ],
|
||||
});
|
||||
|
||||
info("visit url, with non-standard whitespace");
|
||||
|
|
|
@ -19,6 +19,7 @@ support-files =
|
|||
[test_adaptive_limited.js]
|
||||
[test_autocomplete_functional.js]
|
||||
[test_autocomplete_stopSearch_no_throw.js]
|
||||
[test_autofill_about_urls.js]
|
||||
[test_autofill_origins.js]
|
||||
[test_autofill_search_engines.js]
|
||||
[test_autofill_urls.js]
|
||||
|
|
|
@ -2,44 +2,20 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/AboutPagesUtils.jsm");
|
||||
|
||||
var gProtocols = [];
|
||||
var gContainer;
|
||||
window.onload = function() {
|
||||
gContainer = document.getElementById("abouts");
|
||||
findAbouts();
|
||||
AboutPagesUtils.visibleAboutUrls.forEach(createProtocolListing);
|
||||
};
|
||||
|
||||
function findAbouts() {
|
||||
for (var cid in Cc) {
|
||||
var result = cid.match(/@mozilla.org\/network\/protocol\/about;1\?what\=(.*)$/);
|
||||
if (result) {
|
||||
var aboutType = result[1];
|
||||
var contract = "@mozilla.org/network/protocol/about;1?what=" + aboutType;
|
||||
try {
|
||||
var am = Cc[contract].getService(Ci.nsIAboutModule);
|
||||
var uri = Services.io.newURI("about:" + aboutType);
|
||||
var flags = am.getURIFlags(uri);
|
||||
if (!(flags & Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT)) {
|
||||
gProtocols.push(aboutType);
|
||||
}
|
||||
} catch (e) {
|
||||
// getService might have thrown if the component doesn't actually
|
||||
// implement nsIAboutModule
|
||||
}
|
||||
}
|
||||
}
|
||||
gProtocols.sort().forEach(createProtocolListing);
|
||||
}
|
||||
|
||||
function createProtocolListing(aProtocol) {
|
||||
var uri = "about:" + aProtocol;
|
||||
function createProtocolListing(aUrl) {
|
||||
var li = document.createElement("li");
|
||||
var link = document.createElement("a");
|
||||
var text = document.createTextNode(uri);
|
||||
var text = document.createTextNode(aUrl);
|
||||
|
||||
link.href = uri;
|
||||
link.href = aUrl;
|
||||
link.appendChild(text);
|
||||
li.appendChild(link);
|
||||
gContainer.appendChild(li);
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
||||
* vim: sw=2 ts=2 sts=2 expandtab
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const EXPORTED_SYMBOLS = ["AboutPagesUtils"];
|
||||
|
||||
ChromeUtils.import("resource://gre/modules/Services.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
const AboutPagesUtils = {};
|
||||
|
||||
XPCOMUtils.defineLazyGetter(AboutPagesUtils, "visibleAboutUrls", () => {
|
||||
const urls = [];
|
||||
const rx = /@mozilla.org\/network\/protocol\/about;1\?what\=(.*)$/;
|
||||
for (const cid in Cc) {
|
||||
const result = cid.match(rx);
|
||||
if (!result) {
|
||||
continue;
|
||||
}
|
||||
const [, aboutType] = result;
|
||||
try {
|
||||
const am = Cc[cid].getService(Ci.nsIAboutModule);
|
||||
const uri = Services.io.newURI(`about:${aboutType}`);
|
||||
const flags = am.getURIFlags(uri);
|
||||
if (!(flags & Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT)) {
|
||||
urls.push(`about:${aboutType}`);
|
||||
}
|
||||
} catch (e) {
|
||||
// getService() might have thrown if the component doesn't actually
|
||||
// implement nsIAboutModule
|
||||
}
|
||||
}
|
||||
urls.sort();
|
||||
return urls;
|
||||
});
|
|
@ -166,6 +166,7 @@ with Files('docs/**'):
|
|||
SCHEDULES.exclusive = ['docs']
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'AboutPagesUtils.jsm',
|
||||
'ActorChild.jsm',
|
||||
'ActorManagerChild.jsm',
|
||||
'ActorManagerParent.jsm',
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
{
|
||||
"AboutPagesUtils.jsm": ["AboutPagesUtils"],
|
||||
"AddonManager.jsm": ["AddonManager", "AddonManagerPrivate"],
|
||||
"addons.js": ["AddonsEngine", "AddonValidator"],
|
||||
"addons.jsm": ["Addon", "STATE_ENABLED", "STATE_DISABLED"],
|
||||
|
|
Загрузка…
Ссылка в новой задаче