Wire up new feed processor to Zotero's feed reader
This connects the new feed processor to Zotero's existing feed reader. The new feed processor assumes a content window environment, so a sandbox in a parent window is used to load it.
This commit is contained in:
parent
2bd4904ead
commit
eaa01901ef
3 changed files with 72 additions and 21 deletions
|
@ -130,11 +130,49 @@ Zotero.FeedReader = function (url) {
|
||||||
lastItem.resolve(null);
|
lastItem.resolve(null);
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
|
|
||||||
// Set up asynchronous feed processor
|
// The feed processor and related modules assume a content window environment, so we'll simulate
|
||||||
let feedProcessor = Components.classes["@mozilla.org/feed-processor;1"]
|
// one via a sandbox in a parent window. You might think we could jump straight to
|
||||||
.createInstance(Components.interfaces.nsIFeedProcessor);
|
// `hiddenDOMWindow` as a parent window, since it does indeed exist on all platforms...
|
||||||
|
// However, when loading scripts into the `hiddenDOMWindow` on Windows and Linux, they get
|
||||||
|
// stuck in some lazily parsed state which bizarrely drops function prototypes. To avoid this,
|
||||||
|
// we prefer other parent windows first, which work fine on all platforms.
|
||||||
|
let parentWindow = Services.wm.getMostRecentWindow("navigator:browser");
|
||||||
|
if (!parentWindow) {
|
||||||
|
parentWindow = Services.ww.activeWindow;
|
||||||
|
}
|
||||||
|
// Use the hidden DOM window on macOS with the main window closed
|
||||||
|
if (!parentWindow) {
|
||||||
|
parentWindow = Services.appShell.hiddenDOMWindow;
|
||||||
|
}
|
||||||
|
if (!parentWindow) {
|
||||||
|
this.terminate("Parent window not available for feed reader");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let feedUrl = Services.io.newURI(url, null, null);
|
const sandbox = new Cu.Sandbox(parentWindow, {
|
||||||
|
sandboxPrototype: parentWindow,
|
||||||
|
sandboxName: "Feed Processor",
|
||||||
|
});
|
||||||
|
sandbox.Zotero = {
|
||||||
|
debug: Components.utils.exportFunction(Zotero.debug, sandbox),
|
||||||
|
};
|
||||||
|
|
||||||
|
Services.scriptloader.loadSubScript("resource://zotero/feeds/FeedProcessor.js", sandbox);
|
||||||
|
Services.scriptloader.loadSubScript("resource://zotero/feeds/SAXXMLReader.js", sandbox);
|
||||||
|
|
||||||
|
// Set up asynchronous feed processor
|
||||||
|
const { FeedProcessor } = sandbox;
|
||||||
|
const feedProcessor = new FeedProcessor();
|
||||||
|
if (!feedProcessor.parseAsync) {
|
||||||
|
this.terminate("Feed processor failed to load in parent window");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Borrow web utils to fetch feed content
|
||||||
|
const { fetch, URL } = parentWindow;
|
||||||
|
|
||||||
|
// Pass along the URL
|
||||||
|
const feedUrl = new URL(url);
|
||||||
feedProcessor.parseAsync(null, feedUrl);
|
feedProcessor.parseAsync(null, feedUrl);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -148,19 +186,21 @@ Zotero.FeedReader = function (url) {
|
||||||
this.terminate("No Feed");
|
this.terminate("No Feed");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
feedFetched.resolve(result.doc);
|
||||||
let newFeed = result.doc.QueryInterface(Components.interfaces.nsIFeed);
|
|
||||||
feedFetched.resolve(newFeed);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Zotero.debug("FeedReader: Fetching feed from " + feedUrl.spec);
|
Zotero.debug("FeedReader: Fetching feed from " + feedUrl);
|
||||||
|
|
||||||
this._channel = Services.io.newChannelFromURI2(feedUrl, null,
|
// Fetch and start processing
|
||||||
Services.scriptSecurityManager.getSystemPrincipal(), null,
|
fetch(feedUrl, {
|
||||||
Ci.nsILoadInfo.SEC_NORMAL, Ci.nsIContentPolicy.TYPE_OTHER);
|
cache: "no-store",
|
||||||
this._channel.loadFlags |= Components.interfaces.nsIRequest.LOAD_BYPASS_CACHE;
|
}).then((response) => {
|
||||||
this._channel.asyncOpen(feedProcessor, null); // Sends an HTTP request
|
return feedProcessor.onResponseAvailable(response);
|
||||||
|
}).catch((e) => {
|
||||||
|
Zotero.debug(e);
|
||||||
|
this.terminate("Processing failed");
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -195,11 +235,6 @@ Zotero.FeedReader.prototype.terminate = function (status) {
|
||||||
er.handledRejection = true;
|
er.handledRejection = true;
|
||||||
lastItem.reject(er);
|
lastItem.reject(er);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Close feed connection
|
|
||||||
if (this._channel.isPending()) {
|
|
||||||
this._channel.cancel(Components.results.NS_BINDING_ABORTED);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Zotero.defineProperty(Zotero.FeedReader.prototype, 'feedProperties', {
|
Zotero.defineProperty(Zotero.FeedReader.prototype, 'feedProperties', {
|
||||||
|
|
|
@ -35,8 +35,18 @@ describe("Zotero.FeedReader", function () {
|
||||||
var atomFeedURL = getTestDataUrl("feed.atom");
|
var atomFeedURL = getTestDataUrl("feed.atom");
|
||||||
var mediaFeedURL = getTestDataUrl("feedMedia.xml");
|
var mediaFeedURL = getTestDataUrl("feedMedia.xml");
|
||||||
|
|
||||||
after(function* () {
|
var win;
|
||||||
yield clearFeeds();
|
|
||||||
|
before(async function() {
|
||||||
|
// Browser window is needed as parent window to load the feed reader scripts.
|
||||||
|
win = await loadBrowserWindow();
|
||||||
|
});
|
||||||
|
|
||||||
|
after(async function() {
|
||||||
|
if (win) {
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
|
await clearFeeds();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('FeedReader()', function () {
|
describe('FeedReader()', function () {
|
||||||
|
|
|
@ -311,8 +311,11 @@ describe("Zotero.Feed", function() {
|
||||||
var feed, scheduleNextFeedCheck;
|
var feed, scheduleNextFeedCheck;
|
||||||
var feedUrl = getTestDataUrl("feed.rss");
|
var feedUrl = getTestDataUrl("feed.rss");
|
||||||
var modifiedFeedUrl = getTestDataUrl("feedModified.rss");
|
var modifiedFeedUrl = getTestDataUrl("feedModified.rss");
|
||||||
|
var win;
|
||||||
|
|
||||||
before(function() {
|
before(async function() {
|
||||||
|
// Browser window is needed as parent window to load the feed reader scripts.
|
||||||
|
win = await loadBrowserWindow();
|
||||||
scheduleNextFeedCheck = sinon.stub(Zotero.Feeds, 'scheduleNextFeedCheck').resolves();
|
scheduleNextFeedCheck = sinon.stub(Zotero.Feeds, 'scheduleNextFeedCheck').resolves();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -328,6 +331,9 @@ describe("Zotero.Feed", function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
after(function() {
|
after(function() {
|
||||||
|
if (win) {
|
||||||
|
win.close();
|
||||||
|
}
|
||||||
scheduleNextFeedCheck.restore();
|
scheduleNextFeedCheck.restore();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue