Bug 1140172 - Use a single reader worker instead of spawning infinite workers. r=bnicholson f=Yoric

This commit is contained in:
Margaret Leibovic 2015-03-05 17:31:05 -08:00
parent 9251e6915e
commit 6cf362c962
8 changed files with 100 additions and 60 deletions

View File

@ -15,6 +15,7 @@ Cu.importGlobalProperties(["XMLHttpRequest"]);
XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", "resource://services-common/utils.js");
XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ReaderWorker", "resource://gre/modules/reader/ReaderWorker.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Task", "resource://gre/modules/Task.jsm");
this.ReaderMode = {
@ -199,57 +200,41 @@ this.ReaderMode = {
* @return {Promise}
* @resolves JS object representing the article, or null if no article is found.
*/
_readerParse: function (uri, doc) {
return new Promise((resolve, reject) => {
let numTags = doc.getElementsByTagName("*").length;
if (numTags > this.MAX_ELEMS_TO_PARSE) {
this.log("Aborting parse for " + uri.spec + "; " + numTags + " elements found");
resolve(null);
return;
}
_readerParse: Task.async(function* (uri, doc) {
let numTags = doc.getElementsByTagName("*").length;
if (numTags > this.MAX_ELEMS_TO_PARSE) {
this.log("Aborting parse for " + uri.spec + "; " + numTags + " elements found");
return null;
}
let worker = new ChromeWorker("chrome://global/content/reader/readerWorker.js");
worker.onmessage = evt => {
let article = evt.data;
let uriParam = {
spec: uri.spec,
host: uri.host,
prePath: uri.prePath,
scheme: uri.scheme,
pathBase: Services.io.newURI(".", null, uri).spec
};
if (!article) {
this.log("Worker did not return an article");
resolve(null);
return;
}
let serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
createInstance(Ci.nsIDOMSerializer);
let serializedDoc = yield Promise.resolve(serializer.serializeToString(doc));
// Readability returns a URI object, but we only care about the URL.
article.url = article.uri.spec;
delete article.uri;
let article = yield ReaderWorker.post("parseDocument", [uriParam, serializedDoc]);
let flags = Ci.nsIDocumentEncoder.OutputSelectionOnly | Ci.nsIDocumentEncoder.OutputAbsoluteLinks;
article.title = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils)
.convertToPlainText(article.title, flags, 0);
resolve(article);
};
if (!article) {
this.log("Worker did not return an article");
return null;
}
worker.onerror = evt => {
reject("Error in worker: " + evt.message);
};
// Readability returns a URI object, but we only care about the URL.
article.url = article.uri.spec;
delete article.uri;
try {
let serializer = Cc["@mozilla.org/xmlextras/xmlserializer;1"].
createInstance(Ci.nsIDOMSerializer);
worker.postMessage({
uri: {
spec: uri.spec,
host: uri.host,
prePath: uri.prePath,
scheme: uri.scheme,
pathBase: Services.io.newURI(".", null, uri).spec
},
doc: serializer.serializeToString(doc)
});
} catch (e) {
reject("Reader: could not build Readability arguments: " + e);
}
});
},
let flags = Ci.nsIDocumentEncoder.OutputSelectionOnly | Ci.nsIDocumentEncoder.OutputAbsoluteLinks;
article.title = Cc["@mozilla.org/parserutils;1"].getService(Ci.nsIParserUtils)
.convertToPlainText(article.title, flags, 0);
return article;
}),
get _cryptoHash() {
delete this._cryptoHash;

View File

@ -0,0 +1,46 @@
/* 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";
/**
* A worker dedicated to handle parsing documents for reader view.
*/
importScripts("resource://gre/modules/workers/require.js",
"resource://gre/modules/reader/JSDOMParser.js",
"resource://gre/modules/reader/Readability.js");
let PromiseWorker = require("resource://gre/modules/workers/PromiseWorker.js");
let worker = new PromiseWorker.AbstractWorker();
worker.dispatch = function(method, args = []) {
return Agent[method](...args);
};
worker.postMessage = function(result, ...transfers) {
self.postMessage(result, ...transfers);
};
worker.close = function() {
self.close();
};
worker.log = function(...args) {
dump("ReaderWorker: " + args.join(" ") + "\n");
};
self.addEventListener("message", msg => worker.handleMessage(msg));
let Agent = {
/**
* Parses structured article data from a document.
*
* @param {object} uri URI data for the document.
* @param {string} serializedDoc The serialized document.
*
* @return {object} Article object returned from Readability.
*/
parseDocument: function (uri, serializedDoc) {
let doc = new JSDOMParser().parse(serializedDoc);
return new Readability(uri, doc).parse();
},
};

View File

@ -0,0 +1,17 @@
/* 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";
/**
* Interface to a dedicated thread handling readability parsing.
*/
const Cu = Components.utils;
Cu.import("resource://gre/modules/PromiseWorker.jsm", this);
this.EXPORTED_SYMBOLS = ["ReaderWorker"];
this.ReaderWorker = new BasePromiseWorker("resource://gre/modules/reader/ReaderWorker.js");

View File

@ -1,12 +0,0 @@
/* 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/. */
importScripts("JSDOMParser.js", "Readability.js");
self.onmessage = function (msg) {
let uri = msg.data.uri;
let doc = new JSDOMParser().parse(msg.data.doc);
let article = new Readability(uri, doc).parse();
postMessage(article);
};

View File

@ -5,6 +5,3 @@
toolkit.jar:
content/global/reader/aboutReader.html (content/aboutReader.html)
content/global/reader/aboutReader.js (content/aboutReader.js)
content/global/reader/Readability.js (content/Readability.js)
content/global/reader/JSDOMParser.js (content/JSDOMParser.js)
content/global/reader/readerWorker.js (content/readerWorker.js)

View File

@ -10,3 +10,10 @@ EXTRA_JS_MODULES += [
'AboutReader.jsm',
'ReaderMode.jsm'
]
EXTRA_JS_MODULES.reader = [
'JSDOMParser.js',
'Readability.js',
'ReaderWorker.js',
'ReaderWorker.jsm'
]