Bug 1333990: Part 3b - Preload matching content scripts when opening document channels. r=aswan,billm

This uses the http-on-opening-request observer that's dispatched in the child
process to begin preloading matching content scripts as early in the load
cycle as possible. Ideally we would use the network predictor for this, but
most of its prediction work happens in the parent process, and there are no
simple ways for us to hook into it.

This currently does not do any pre-loading in the parent process, mainly
because there isn't a good way to distinguish top-level document loads that
are happening directly in the parent versus those that are being proxied from
the child.

MozReview-Commit-ID: dIQW68HtxZ

--HG--
extra : rebase_source : b36f6c8516d0550a0d5bb0df895ce6db76ab3538
This commit is contained in:
Kris Maglione 2017-03-10 21:01:52 -08:00
Родитель 53e241ffbc
Коммит 6a80b8df35
1 изменённых файлов: 62 добавлений и 17 удалений

Просмотреть файл

@ -159,6 +159,40 @@ Script.prototype = {
return urls;
},
matchesLoadInfo(uri, loadInfo) {
if (!this.matchesURI(uri)) {
return false;
}
if (!this.options.all_frames && !loadInfo.isTopLevelLoad) {
return false;
}
return true;
},
matchesURI(uri) {
if (!(this.matches_.matches(uri) || this.matches_host_.matchesIgnoringPath(uri))) {
return false;
}
if (this.exclude_matches_.matches(uri)) {
return false;
}
if (this.options.include_globs != null) {
if (!this.include_globs_.matches(uri.spec)) {
return false;
}
}
if (this.exclude_globs_.matches(uri.spec)) {
return false;
}
return true;
},
matches(window) {
let uri = window.document.documentURIObject;
let principal = window.document.nodePrincipal;
@ -191,21 +225,7 @@ Script.prototype = {
uri = principal.URI;
}
if (!(this.matches_.matches(uri) || this.matches_host_.matchesIgnoringPath(uri))) {
return false;
}
if (this.exclude_matches_.matches(uri)) {
return false;
}
if (this.options.include_globs != null) {
if (!this.include_globs_.matches(uri.spec)) {
return false;
}
}
if (this.exclude_globs_.matches(uri.spec)) {
if (!this.matchesURI(uri)) {
return false;
}
@ -511,12 +531,18 @@ DocumentManager = {
extensionPageWindows: new Map(),
init() {
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
Services.obs.addObserver(this, "http-on-opening-request", false);
}
Services.obs.addObserver(this, "content-document-global-created", false);
Services.obs.addObserver(this, "document-element-inserted", false);
Services.obs.addObserver(this, "inner-window-destroyed", false);
},
uninit() {
if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
Services.obs.removeObserver(this, "http-on-opening-request");
}
Services.obs.removeObserver(this, "content-document-global-created");
Services.obs.removeObserver(this, "document-element-inserted");
Services.obs.removeObserver(this, "inner-window-destroyed");
@ -556,7 +582,7 @@ DocumentManager = {
}
},
observe: function(subject, topic, data) {
observe(subject, topic, data) {
// For some types of documents (about:blank), we only see the first
// notification, for others (data: URIs) we only observe the second.
if (topic == "content-document-global-created" || topic == "document-element-inserted") {
@ -613,10 +639,19 @@ DocumentManager = {
}
ExtensionChild.destroyExtensionContext(windowId);
} else if (topic === "http-on-opening-request") {
let {loadInfo} = subject.QueryInterface(Ci.nsIChannel);
if (loadInfo) {
let {externalContentPolicyType: type} = loadInfo;
if (type === Ci.nsIContentPolicy.TYPE_DOCUMENT ||
type === Ci.nsIContentPolicy.TYPE_SUBDOCUMENT) {
this.preloadScripts(subject.URI, loadInfo);
}
}
}
},
handleEvent: function(event) {
handleEvent(event) {
let window = event.currentTarget;
if (event.target != window.document) {
// We use capturing listeners so we have precedence over content script
@ -775,6 +810,16 @@ DocumentManager = {
}
},
preloadScripts(uri, loadInfo) {
for (let extension of ExtensionManager.extensions.values()) {
for (let script of extension.scripts) {
if (script.matchesLoadInfo(uri, loadInfo)) {
script.compileScripts();
}
}
}
},
trigger(when, window) {
if (when === "document_start") {
for (let extension of ExtensionManager.extensions.values()) {