зеркало из https://github.com/mozilla/gecko-dev.git
644 строки
22 KiB
JavaScript
644 строки
22 KiB
JavaScript
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
|
|
* 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/. */
|
|
|
|
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
|
|
"resource://gre/modules/DeferredTask.jsm");
|
|
|
|
const TYPE_MAYBE_FEED = "application/vnd.mozilla.maybe.feed";
|
|
const TYPE_MAYBE_AUDIO_FEED = "application/vnd.mozilla.maybe.audio.feed";
|
|
const TYPE_MAYBE_VIDEO_FEED = "application/vnd.mozilla.maybe.video.feed";
|
|
|
|
const PREF_SHOW_FIRST_RUN_UI = "browser.feeds.showFirstRunUI";
|
|
|
|
const PREF_SELECTED_APP = "browser.feeds.handlers.application";
|
|
const PREF_SELECTED_WEB = "browser.feeds.handlers.webservice";
|
|
const PREF_SELECTED_ACTION = "browser.feeds.handler";
|
|
const PREF_SELECTED_READER = "browser.feeds.handler.default";
|
|
|
|
const PREF_VIDEO_SELECTED_APP = "browser.videoFeeds.handlers.application";
|
|
const PREF_VIDEO_SELECTED_WEB = "browser.videoFeeds.handlers.webservice";
|
|
const PREF_VIDEO_SELECTED_ACTION = "browser.videoFeeds.handler";
|
|
const PREF_VIDEO_SELECTED_READER = "browser.videoFeeds.handler.default";
|
|
|
|
const PREF_AUDIO_SELECTED_APP = "browser.audioFeeds.handlers.application";
|
|
const PREF_AUDIO_SELECTED_WEB = "browser.audioFeeds.handlers.webservice";
|
|
const PREF_AUDIO_SELECTED_ACTION = "browser.audioFeeds.handler";
|
|
const PREF_AUDIO_SELECTED_READER = "browser.audioFeeds.handler.default";
|
|
|
|
const PREF_UPDATE_DELAY = 2000;
|
|
|
|
const SETTABLE_PREFS = new Set([
|
|
PREF_VIDEO_SELECTED_ACTION,
|
|
PREF_AUDIO_SELECTED_ACTION,
|
|
PREF_SELECTED_ACTION,
|
|
PREF_VIDEO_SELECTED_READER,
|
|
PREF_AUDIO_SELECTED_READER,
|
|
PREF_SELECTED_READER,
|
|
PREF_VIDEO_SELECTED_WEB,
|
|
PREF_AUDIO_SELECTED_WEB,
|
|
PREF_SELECTED_WEB
|
|
]);
|
|
|
|
const EXECUTABLE_PREFS = new Set([
|
|
PREF_SELECTED_APP,
|
|
PREF_VIDEO_SELECTED_APP,
|
|
PREF_AUDIO_SELECTED_APP
|
|
]);
|
|
|
|
const VALID_ACTIONS = new Set(["ask", "reader", "bookmarks"]);
|
|
const VALID_READERS = new Set(["web", "client", "default", "bookmarks"]);
|
|
|
|
XPCOMUtils.defineLazyPreferenceGetter(this, "SHOULD_LOG",
|
|
"feeds.log", false);
|
|
|
|
function LOG(str) {
|
|
if (SHOULD_LOG)
|
|
dump("*** Feeds: " + str + "\n");
|
|
}
|
|
|
|
function getPrefActionForType(t) {
|
|
switch (t) {
|
|
case Ci.nsIFeed.TYPE_VIDEO:
|
|
return PREF_VIDEO_SELECTED_ACTION;
|
|
|
|
case Ci.nsIFeed.TYPE_AUDIO:
|
|
return PREF_AUDIO_SELECTED_ACTION;
|
|
|
|
default:
|
|
return PREF_SELECTED_ACTION;
|
|
}
|
|
}
|
|
|
|
function getPrefReaderForType(t) {
|
|
switch (t) {
|
|
case Ci.nsIFeed.TYPE_VIDEO:
|
|
return PREF_VIDEO_SELECTED_READER;
|
|
|
|
case Ci.nsIFeed.TYPE_AUDIO:
|
|
return PREF_AUDIO_SELECTED_READER;
|
|
|
|
default:
|
|
return PREF_SELECTED_READER;
|
|
}
|
|
}
|
|
|
|
function getPrefWebForType(t) {
|
|
switch (t) {
|
|
case Ci.nsIFeed.TYPE_VIDEO:
|
|
return PREF_VIDEO_SELECTED_WEB;
|
|
|
|
case Ci.nsIFeed.TYPE_AUDIO:
|
|
return PREF_AUDIO_SELECTED_WEB;
|
|
|
|
default:
|
|
return PREF_SELECTED_WEB;
|
|
}
|
|
}
|
|
|
|
function getPrefAppForType(t) {
|
|
switch (t) {
|
|
case Ci.nsIFeed.TYPE_VIDEO:
|
|
return PREF_VIDEO_SELECTED_APP;
|
|
|
|
case Ci.nsIFeed.TYPE_AUDIO:
|
|
return PREF_AUDIO_SELECTED_APP;
|
|
|
|
default:
|
|
return PREF_SELECTED_APP;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Maps a feed type to a maybe-feed mimetype.
|
|
*/
|
|
function getMimeTypeForFeedType(aFeedType) {
|
|
switch (aFeedType) {
|
|
case Ci.nsIFeed.TYPE_VIDEO:
|
|
return TYPE_MAYBE_VIDEO_FEED;
|
|
|
|
case Ci.nsIFeed.TYPE_AUDIO:
|
|
return TYPE_MAYBE_AUDIO_FEED;
|
|
|
|
default:
|
|
return TYPE_MAYBE_FEED;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The Feed Handler object manages discovery of RSS/ATOM feeds in web pages
|
|
* and shows UI when they are discovered.
|
|
*/
|
|
var FeedHandler = {
|
|
_prefChangeCallback: null,
|
|
|
|
/** Called when the user clicks on the Subscribe to This Page... menu item,
|
|
* or when the user clicks the feed button when the page contains multiple
|
|
* feeds.
|
|
* Builds a menu of unique feeds associated with the page, and if there
|
|
* is only one, shows the feed inline in the browser window.
|
|
* @param container
|
|
* The feed list container (menupopup or subview) to be populated.
|
|
* @param isSubview
|
|
* Whether we're creating a subview (true) or menu (false/undefined)
|
|
* @return true if the menu/subview should be shown, false if there was only
|
|
* one feed and the feed should be shown inline in the browser
|
|
* window (do not show the menupopup/subview).
|
|
*/
|
|
buildFeedList(container, isSubview) {
|
|
let feeds = gBrowser.selectedBrowser.feeds;
|
|
if (!isSubview && feeds == null) {
|
|
// XXX hack -- menu opening depends on setting of an "open"
|
|
// attribute, and the menu refuses to open if that attribute is
|
|
// set (because it thinks it's already open). onpopupshowing gets
|
|
// called after the attribute is unset, and it doesn't get unset
|
|
// if we return false. so we unset it here; otherwise, the menu
|
|
// refuses to work past this point.
|
|
container.parentNode.removeAttribute("open");
|
|
return false;
|
|
}
|
|
|
|
for (let i = container.childNodes.length - 1; i >= 0; --i) {
|
|
let node = container.childNodes[i];
|
|
if (isSubview && node.localName == "label")
|
|
continue;
|
|
container.removeChild(node);
|
|
}
|
|
|
|
if (!feeds || feeds.length <= 1)
|
|
return false;
|
|
|
|
// Build the menu showing the available feed choices for viewing.
|
|
let itemNodeType = isSubview ? "toolbarbutton" : "menuitem";
|
|
for (let feedInfo of feeds) {
|
|
let item = document.createElement(itemNodeType);
|
|
let baseTitle = feedInfo.title || feedInfo.href;
|
|
item.setAttribute("label", baseTitle);
|
|
item.setAttribute("feed", feedInfo.href);
|
|
item.setAttribute("tooltiptext", feedInfo.href);
|
|
item.setAttribute("crop", "center");
|
|
let className = "feed-" + itemNodeType;
|
|
if (isSubview) {
|
|
className += " subviewbutton";
|
|
}
|
|
item.setAttribute("class", className);
|
|
container.appendChild(item);
|
|
}
|
|
return true;
|
|
},
|
|
|
|
/**
|
|
* Subscribe to a given feed. Called when
|
|
* 1. Page has a single feed and user clicks feed icon in location bar
|
|
* 2. Page has a single feed and user selects Subscribe menu item
|
|
* 3. Page has multiple feeds and user selects from feed icon popup (or subview)
|
|
* 4. Page has multiple feeds and user selects from Subscribe submenu
|
|
* @param href
|
|
* The feed to subscribe to. May be null, in which case the
|
|
* event target's feed attribute is examined.
|
|
* @param event
|
|
* The event this method is handling. Used to decide where
|
|
* to open the preview UI. (Optional, unless href is null)
|
|
*/
|
|
subscribeToFeed(href, event) {
|
|
// Just load the feed in the content area to either subscribe or show the
|
|
// preview UI
|
|
if (!href)
|
|
href = event.target.getAttribute("feed");
|
|
urlSecurityCheck(href, gBrowser.contentPrincipal,
|
|
Ci.nsIScriptSecurityManager.DISALLOW_INHERIT_PRINCIPAL);
|
|
let feedURI = makeURI(href, document.characterSet);
|
|
// Use the feed scheme so X-Moz-Is-Feed will be set
|
|
// The value doesn't matter
|
|
if (/^https?$/.test(feedURI.scheme))
|
|
href = "feed:" + href;
|
|
this.loadFeed(href, event);
|
|
},
|
|
|
|
loadFeed(href, event) {
|
|
let feeds = gBrowser.selectedBrowser.feeds;
|
|
try {
|
|
openUILink(href, event, { ignoreAlt: true });
|
|
} finally {
|
|
// We might default to a livebookmarks modal dialog,
|
|
// so reset that if the user happens to click it again
|
|
gBrowser.selectedBrowser.feeds = feeds;
|
|
}
|
|
},
|
|
|
|
get _feedMenuitem() {
|
|
delete this._feedMenuitem;
|
|
return this._feedMenuitem = document.getElementById("singleFeedMenuitemState");
|
|
},
|
|
|
|
get _feedMenupopup() {
|
|
delete this._feedMenupopup;
|
|
return this._feedMenupopup = document.getElementById("multipleFeedsMenuState");
|
|
},
|
|
|
|
/**
|
|
* Update the browser UI to show whether or not feeds are available when
|
|
* a page is loaded or the user switches tabs to a page that has feeds.
|
|
*/
|
|
updateFeeds() {
|
|
if (this._updateFeedTimeout)
|
|
clearTimeout(this._updateFeedTimeout);
|
|
|
|
let feeds = gBrowser.selectedBrowser.feeds;
|
|
let haveFeeds = feeds && feeds.length > 0;
|
|
|
|
let feedButton = document.getElementById("feed-button");
|
|
if (feedButton) {
|
|
if (haveFeeds) {
|
|
feedButton.removeAttribute("disabled");
|
|
} else {
|
|
feedButton.setAttribute("disabled", "true");
|
|
}
|
|
}
|
|
|
|
if (!haveFeeds) {
|
|
this._feedMenuitem.setAttribute("disabled", "true");
|
|
this._feedMenuitem.removeAttribute("hidden");
|
|
this._feedMenupopup.setAttribute("hidden", "true");
|
|
return;
|
|
}
|
|
|
|
if (feeds.length > 1) {
|
|
this._feedMenuitem.setAttribute("hidden", "true");
|
|
this._feedMenupopup.removeAttribute("hidden");
|
|
} else {
|
|
this._feedMenuitem.setAttribute("feed", feeds[0].href);
|
|
this._feedMenuitem.removeAttribute("disabled");
|
|
this._feedMenuitem.removeAttribute("hidden");
|
|
this._feedMenupopup.setAttribute("hidden", "true");
|
|
}
|
|
},
|
|
|
|
addFeed(link, browserForLink) {
|
|
if (!browserForLink.feeds)
|
|
browserForLink.feeds = [];
|
|
|
|
browserForLink.feeds.push({ href: link.href, title: link.title });
|
|
|
|
// If this addition was for the current browser, update the UI. For
|
|
// background browsers, we'll update on tab switch.
|
|
if (browserForLink == gBrowser.selectedBrowser) {
|
|
// Batch updates to avoid updating the UI for multiple onLinkAdded events
|
|
// fired within 100ms of each other.
|
|
if (this._updateFeedTimeout)
|
|
clearTimeout(this._updateFeedTimeout);
|
|
this._updateFeedTimeout = setTimeout(this.updateFeeds.bind(this), 100);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Get the human-readable display name of a file. This could be the
|
|
* application name.
|
|
* @param file
|
|
* A nsIFile to look up the name of
|
|
* @return The display name of the application represented by the file.
|
|
*/
|
|
_getFileDisplayName(file) {
|
|
switch (AppConstants.platform) {
|
|
case "win":
|
|
if (file instanceof Ci.nsILocalFileWin) {
|
|
try {
|
|
return file.getVersionInfoField("FileDescription");
|
|
} catch (e) {}
|
|
}
|
|
break;
|
|
case "macosx":
|
|
if (file instanceof Ci.nsILocalFileMac) {
|
|
try {
|
|
return file.bundleDisplayName;
|
|
} catch (e) {}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return file.leafName;
|
|
},
|
|
|
|
_chooseClientApp(aTitle, aTypeName, aBrowser) {
|
|
const prefName = getPrefAppForType(aTypeName);
|
|
let fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
|
|
|
|
fp.init(window, aTitle, Ci.nsIFilePicker.modeOpen);
|
|
fp.appendFilters(Ci.nsIFilePicker.filterApps);
|
|
|
|
fp.open((aResult) => {
|
|
if (aResult == Ci.nsIFilePicker.returnOK) {
|
|
let selectedApp = fp.file;
|
|
if (selectedApp) {
|
|
// XXXben - we need to compare this with the running instance
|
|
// executable just don't know how to do that via script
|
|
// XXXmano TBD: can probably add this to nsIShellService
|
|
let appName = "";
|
|
switch (AppConstants.platform) {
|
|
case "win":
|
|
appName = AppConstants.MOZ_APP_NAME + ".exe";
|
|
break;
|
|
case "macosx":
|
|
appName = AppConstants.MOZ_MACBUNDLE_NAME;
|
|
break;
|
|
default:
|
|
appName = AppConstants.MOZ_APP_NAME + "-bin";
|
|
break;
|
|
}
|
|
|
|
if (fp.file.leafName != appName) {
|
|
Services.prefs.setComplexValue(prefName, Ci.nsILocalFile, selectedApp);
|
|
aBrowser.messageManager.sendAsyncMessage("FeedWriter:SetApplicationLauncherMenuItem",
|
|
{ name: this._getFileDisplayName(selectedApp),
|
|
type: "SelectedAppMenuItem" });
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
},
|
|
|
|
executeClientApp(aSpec, aTitle, aSubtitle, aFeedHandler) {
|
|
// aFeedHandler is either "default", indicating the system default reader, or a pref-name containing
|
|
// an nsILocalFile pointing to the feed handler's executable.
|
|
|
|
let clientApp = null;
|
|
if (aFeedHandler == "default") {
|
|
clientApp = Cc["@mozilla.org/browser/shell-service;1"]
|
|
.getService(Ci.nsIShellService)
|
|
.defaultFeedReader;
|
|
} else {
|
|
clientApp = Services.prefs.getComplexValue(aFeedHandler, Ci.nsILocalFile);
|
|
}
|
|
|
|
// For the benefit of applications that might know how to deal with more
|
|
// URLs than just feeds, send feed: URLs in the following format:
|
|
//
|
|
// http urls: replace scheme with feed, e.g.
|
|
// http://foo.com/index.rdf -> feed://foo.com/index.rdf
|
|
// other urls: prepend feed: scheme, e.g.
|
|
// https://foo.com/index.rdf -> feed:https://foo.com/index.rdf
|
|
let feedURI = NetUtil.newURI(aSpec);
|
|
if (feedURI.schemeIs("http")) {
|
|
feedURI.scheme = "feed";
|
|
aSpec = feedURI.spec;
|
|
} else {
|
|
aSpec = "feed:" + aSpec;
|
|
}
|
|
|
|
// Retrieving the shell service might fail on some systems, most
|
|
// notably systems where GNOME is not installed.
|
|
try {
|
|
let ss = Cc["@mozilla.org/browser/shell-service;1"]
|
|
.getService(Ci.nsIShellService);
|
|
ss.openApplicationWithURI(clientApp, aSpec);
|
|
} catch (e) {
|
|
// If we couldn't use the shell service, fallback to using a
|
|
// nsIProcess instance
|
|
let p = Cc["@mozilla.org/process/util;1"]
|
|
.createInstance(Ci.nsIProcess);
|
|
p.init(clientApp);
|
|
p.run(false, [aSpec], 1);
|
|
}
|
|
},
|
|
|
|
// nsISupports
|
|
|
|
QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
|
|
Ci.nsISupportsWeakReference]),
|
|
|
|
|
|
init() {
|
|
window.messageManager.addMessageListener("FeedWriter:ChooseClientApp", this);
|
|
window.messageManager.addMessageListener("FeedWriter:GetSubscriptionUI", this);
|
|
window.messageManager.addMessageListener("FeedWriter:SetFeedPrefsAndSubscribe", this);
|
|
window.messageManager.addMessageListener("FeedWriter:ShownFirstRun", this);
|
|
|
|
Services.ppmm.addMessageListener("FeedConverter:ExecuteClientApp", this);
|
|
|
|
const prefs = Services.prefs;
|
|
prefs.addObserver(PREF_SELECTED_ACTION, this, true);
|
|
prefs.addObserver(PREF_SELECTED_READER, this, true);
|
|
prefs.addObserver(PREF_SELECTED_WEB, this, true);
|
|
prefs.addObserver(PREF_VIDEO_SELECTED_ACTION, this, true);
|
|
prefs.addObserver(PREF_VIDEO_SELECTED_READER, this, true);
|
|
prefs.addObserver(PREF_VIDEO_SELECTED_WEB, this, true);
|
|
prefs.addObserver(PREF_AUDIO_SELECTED_ACTION, this, true);
|
|
prefs.addObserver(PREF_AUDIO_SELECTED_READER, this, true);
|
|
prefs.addObserver(PREF_AUDIO_SELECTED_WEB, this, true);
|
|
},
|
|
|
|
uninit() {
|
|
Services.ppmm.removeMessageListener("FeedConverter:ExecuteClientApp", this);
|
|
|
|
this._prefChangeCallback = null;
|
|
},
|
|
|
|
// nsIObserver
|
|
observe(subject, topic, data) {
|
|
if (topic == "nsPref:changed") {
|
|
LOG(`Pref changed ${data}`)
|
|
if (this._prefChangeCallback) {
|
|
this._prefChangeCallback.disarm();
|
|
}
|
|
// Multiple prefs are set at the same time, debounce to reduce noise
|
|
// This can happen in one feed and we want to message all feed pages
|
|
this._prefChangeCallback = new DeferredTask(() => {
|
|
this._prefChanged(data);
|
|
}, PREF_UPDATE_DELAY);
|
|
this._prefChangeCallback.arm();
|
|
}
|
|
},
|
|
|
|
_prefChanged(prefName) {
|
|
// Don't observe for PREF_*SELECTED_APP as user likely just picked one
|
|
// That is also handled by SetApplicationLauncherMenuItem call
|
|
// Rather than the others which happen on subscription
|
|
switch (prefName) {
|
|
case PREF_SELECTED_READER:
|
|
case PREF_SELECTED_WEB:
|
|
case PREF_VIDEO_SELECTED_READER:
|
|
case PREF_VIDEO_SELECTED_WEB:
|
|
case PREF_AUDIO_SELECTED_READER:
|
|
case PREF_AUDIO_SELECTED_WEB:
|
|
case PREF_SELECTED_ACTION:
|
|
case PREF_VIDEO_SELECTED_ACTION:
|
|
case PREF_AUDIO_SELECTED_ACTION:
|
|
const response = {
|
|
default: this._getReaderForType(Ci.nsIFeed.TYPE_FEED),
|
|
[Ci.nsIFeed.TYPE_AUDIO]: this._getReaderForType(Ci.nsIFeed.TYPE_AUDIO),
|
|
[Ci.nsIFeed.TYPE_VIDEO]: this._getReaderForType(Ci.nsIFeed.TYPE_VIDEO)
|
|
};
|
|
Services.mm.broadcastAsyncMessage("FeedWriter:PreferenceUpdated",
|
|
response);
|
|
break;
|
|
}
|
|
},
|
|
|
|
_initSubscriptionUIResponse(feedType) {
|
|
const wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
|
|
getService(Ci.nsIWebContentConverterService);
|
|
const handlersRaw = wccr.getContentHandlers(getMimeTypeForFeedType(feedType));
|
|
const handlers = [];
|
|
for (let handler of handlersRaw) {
|
|
LOG(`Handler found: ${handler}`);
|
|
handlers.push({
|
|
name: handler.name,
|
|
uri: handler.uri
|
|
});
|
|
}
|
|
let showFirstRunUI = true;
|
|
// eslint-disable-next-line mozilla/use-default-preference-values
|
|
try {
|
|
showFirstRunUI = Services.prefs.getBoolPref(PREF_SHOW_FIRST_RUN_UI);
|
|
} catch (ex) { }
|
|
const response = { handlers, showFirstRunUI };
|
|
let selectedClientApp;
|
|
const feedTypePref = getPrefAppForType(feedType);
|
|
try {
|
|
selectedClientApp = Services.prefs.getComplexValue(feedTypePref, Ci.nsILocalFile);
|
|
} catch (ex) {
|
|
// Just do nothing, then we won't bother populating
|
|
}
|
|
|
|
let defaultClientApp = null;
|
|
try {
|
|
// This can sometimes not exist
|
|
defaultClientApp = Cc["@mozilla.org/browser/shell-service;1"]
|
|
.getService(Ci.nsIShellService)
|
|
.defaultFeedReader;
|
|
} catch (ex) {
|
|
// Just do nothing, then we don't bother populating
|
|
}
|
|
|
|
if (selectedClientApp && selectedClientApp.exists()) {
|
|
if (defaultClientApp && selectedClientApp.path != defaultClientApp.path) {
|
|
// Only set the default menu item if it differs from the selected one
|
|
response.defaultMenuItem = this._getFileDisplayName(defaultClientApp);
|
|
}
|
|
response.selectedMenuItem = this._getFileDisplayName(selectedClientApp);
|
|
}
|
|
response.reader = this._getReaderForType(feedType);
|
|
return response;
|
|
},
|
|
|
|
_setPref(aPrefName, aPrefValue, aIsComplex = false) {
|
|
LOG(`FeedWriter._setPref ${aPrefName}`);
|
|
// Ensure we have a pref that is settable
|
|
if (aPrefName && SETTABLE_PREFS.has(aPrefName)) {
|
|
if (aIsComplex) {
|
|
Services.prefs.setStringPref(aPrefName, aPrefValue);
|
|
} else {
|
|
Services.prefs.setCharPref(aPrefName, aPrefValue);
|
|
}
|
|
} else {
|
|
LOG(`FeedWriter._setPref ${aPrefName} not allowed`);
|
|
}
|
|
},
|
|
|
|
_getReaderForType(feedType) {
|
|
let prefs = Services.prefs;
|
|
let handler = "bookmarks";
|
|
let url;
|
|
// eslint-disable-next-line mozilla/use-default-preference-values
|
|
try {
|
|
handler = prefs.getCharPref(getPrefReaderForType(feedType));
|
|
} catch (ex) { }
|
|
|
|
if (handler === "web") {
|
|
try {
|
|
url = prefs.getStringPref(getPrefWebForType(feedType));
|
|
} catch (ex) {
|
|
LOG("FeedWriter._setSelectedHandler: invalid or no handler in prefs");
|
|
url = null;
|
|
}
|
|
}
|
|
const alwaysUse = this._getAlwaysUseState(feedType);
|
|
const action = prefs.getCharPref(getPrefActionForType(feedType));
|
|
return { handler, url, alwaysUse, action };
|
|
},
|
|
|
|
_getAlwaysUseState(feedType) {
|
|
try {
|
|
return Services.prefs.getCharPref(getPrefActionForType(feedType)) != "ask";
|
|
} catch (ex) { }
|
|
return false;
|
|
},
|
|
|
|
receiveMessage(msg) {
|
|
let handler;
|
|
switch (msg.name) {
|
|
case "FeedWriter:GetSubscriptionUI":
|
|
const response = this._initSubscriptionUIResponse(msg.data.feedType);
|
|
msg.target.messageManager
|
|
.sendAsyncMessage("FeedWriter:GetSubscriptionUIResponse",
|
|
response);
|
|
break;
|
|
case "FeedWriter:ChooseClientApp":
|
|
this._chooseClientApp(msg.data.title, msg.data.feedType, msg.target);
|
|
break;
|
|
case "FeedWriter:ShownFirstRun":
|
|
Services.prefs.setBoolPref(PREF_SHOW_FIRST_RUN_UI, false);
|
|
break;
|
|
case "FeedWriter:SetFeedPrefsAndSubscribe":
|
|
const settings = msg.data;
|
|
if (!settings.action || !VALID_ACTIONS.has(settings.action)) {
|
|
LOG(`Invalid action ${settings.action}`);
|
|
return;
|
|
}
|
|
if (!settings.reader || !VALID_READERS.has(settings.reader)) {
|
|
LOG(`Invalid reader ${settings.reader}`);
|
|
return;
|
|
}
|
|
const actionPref = getPrefActionForType(settings.feedType);
|
|
this._setPref(actionPref, settings.action);
|
|
const readerPref = getPrefReaderForType(settings.feedType);
|
|
this._setPref(readerPref, settings.reader);
|
|
handler = null;
|
|
|
|
switch (settings.reader) {
|
|
case "web":
|
|
// This is a web set URI by content using window.registerContentHandler()
|
|
// Lets make sure we know about it before setting it
|
|
const webPref = getPrefWebForType(settings.feedType);
|
|
let wccr = Cc["@mozilla.org/embeddor.implemented/web-content-handler-registrar;1"].
|
|
getService(Ci.nsIWebContentConverterService);
|
|
// If the user provided an invalid web URL this function won't give us a reference
|
|
handler = wccr.getWebContentHandlerByURI(getMimeTypeForFeedType(settings.feedType), settings.uri);
|
|
if (handler) {
|
|
this._setPref(webPref, settings.uri, true);
|
|
if (settings.useAsDefault) {
|
|
wccr.setAutoHandler(getMimeTypeForFeedType(settings.feedType), handler);
|
|
}
|
|
msg.target.messageManager
|
|
.sendAsyncMessage("FeedWriter:SetFeedPrefsAndSubscribeResponse",
|
|
{ redirect: handler.getHandlerURI(settings.feedLocation) });
|
|
} else {
|
|
LOG(`No handler found for web ${settings.feedType} ${settings.uri}`);
|
|
}
|
|
break;
|
|
default:
|
|
const feedService = Cc["@mozilla.org/browser/feeds/result-service;1"].
|
|
getService(Ci.nsIFeedResultService);
|
|
|
|
feedService.addToClientReader(settings.feedLocation,
|
|
settings.feedTitle,
|
|
settings.feedSubtitle,
|
|
settings.feedType,
|
|
settings.reader);
|
|
}
|
|
break;
|
|
case "FeedConverter:ExecuteClientApp":
|
|
// Always check feedHandler is from a set array of executable prefs
|
|
if (EXECUTABLE_PREFS.has(msg.data.feedHandler)) {
|
|
this.executeClientApp(msg.data.spec, msg.data.title,
|
|
msg.data.subtitle, msg.data.feedHandler);
|
|
} else {
|
|
LOG(`FeedConverter:ExecuteClientApp - Will not exec ${msg.data.feedHandler}`);
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
};
|